【问题标题】:Asynctask inside Adapterview classAdapterview 类中的 Asynctask
【发布时间】:2013-05-31 18:50:01
【问题描述】:

我正在尝试更改列表视图项目的字体。没有 AsyncTasc 会花费太多时间。将 AsyncTask 活动与该列表视图一起使用会很快出现,然后在实例应用程序崩溃后出现。我知道我不能直接从 AsyncTasc 更改 UI。我可以使用什么?提前致谢

import ru.ayratbadykov.feedhandler.FEED;
import ru.ayratbadykov.feedhandler.RssMessage;
import android.content.Context;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class CustomAdapter extends BaseAdapter {
    private FEED _data;
    Context _c;

    CustomAdapter(FEED data, Context c) {
        _data = data;
        _c = c;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        Log.w("here","here");
        View v = convertView;
        if (v == null) {
            LayoutInflater vi = (LayoutInflater) _c
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.customadapter, null);
        }

        TextView fromView = (TextView) v.findViewById(R.id.textView1);
        TextView subView = (TextView) v.findViewById(R.id.textView2);
        TextView View = (TextView) v.findViewById(R.id.textView3);

        RssMessage msg = _data.getMessages().get(position);
        new Font().execute(fromView,subView,View);





        fromView.setText(msg.getTitle());
        subView.setText(msg.getPUBDATE());
        View.setText(_data.getTitle());

        return v;
    }
    public class Font extends AsyncTask<TextView, Void, Boolean> {

        @Override
        protected Boolean doInBackground(TextView... params) {
            // TODO Auto-generated method stub
            String fontPath = "fonts/Qlassik_TB.ttf";
            Typeface tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
            params[0].setTypeface(tf);
            fontPath="fonts/damase.ttf";

            tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
            params[1].setTypeface(tf);

            tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
            params[3].setTypeface(tf);
            return true;

        }

    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return _data.getMessages().size();

    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return _data.getMessages().get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }
}

日志

05-31 22:32:27.602: E/AndroidRuntime(2803): FATAL EXCEPTION: AsyncTask #1
    05-31 22:32:27.602: E/AndroidRuntime(2803): java.lang.RuntimeException: An error occured while executing doInBackground()
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.lang.Thread.run(Thread.java:1019)
    05-31 22:32:27.602: E/AndroidRuntime(2803): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at android.os.Handler.<init>(Handler.java:121)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at ru.ayratbadykov.rssunion.CustomAdapter$Font$1.<init>(CustomAdapter.java:63)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at ru.ayratbadykov.rssunion.CustomAdapter$Font.doInBackground(CustomAdapter.java:63)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at ru.ayratbadykov.rssunion.CustomAdapter$Font.doInBackground(CustomAdapter.java:1)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
    05-31 22:32:27.602: E/AndroidRuntime(2803):     ... 4 more

【问题讨论】:

  • 您正在后台线程上更新 ui。同样使用runonuithread

标签: android android-listview android-asynctask


【解决方案1】:

您可以在AsyncTask 中更新UI,但不能从doInBackground() 中更新。但是任何其他方法都可以。并且由于它是您的 Adapter 类的内部类,它包含对 Context 的引用,所以可以这样做。只需移动使用Context 或需要将UI 更新为任何其他方法的代码即可。

例如,您可以将paramsArrayList 返回到onPostExecute() 并在那里更新,或者您可以使用publishProgress() 并在onProgressUpdate() 中更新它们

onPostExecute

onProogressUpdate

所以也有很多很好的使用例子

【讨论】:

  • 别忘了 onPreExecute() ;)
  • @Jarvis 是的,这就是为什么我通常会说除了doInBackground() 之外的任何内容,但通常会指出这两个,因为根据我的经验,它们似乎被更多地使用,至少在这种情况下是这样。但我可能应该开始明确添加关于onPreExecute() 的评论,因为这不是我第一次指出它。谢谢! :)
  • 不客气,我已经添加了一个回复以尝试解释一个 asyntack
  • @Jarvis ,您的建议有效,但 listview 变得非常缓慢
  • 我决定只使用一种字体
【解决方案2】:

AsyncTask 允许您启动一个长进程并通过 UIThread 方法访问 UI:

  • onPreExecute():在开始处理之前更新 UI(doInBackground 中的线程)
  • onProgressUpdate():在治疗期间刷新 UI
  • onPostExecute():在结束过程中更新 UI。

如果您了解 Asynctask 的操作,您将拥有所需做的一切

【讨论】:

    【解决方案3】:

    您无法在后台线程上更新 ui。 doInBackground 在后台线程上调用。您应该在 ui 线程上更新 ui。

    您正在尝试更新 doInBackground 中的 textview。如果您需要在 doInBackground() 中更新 ui,请使用 runOnUiThread。

    我也不确定你为什么需要 asynctask 来完成你正在做的事情。

          runOnUiThread(new Runnable(){
    
              @Override
              public void run(){
                //update ui here
              }
           });
    

    onPreExecute(),onPostExecute(Result),在 ui 线程上调用。所以你可以在这里更新ui。

    onProgressUpdate(Progress...),在调用 publishProgress(Progress...) 后在 UI 线程上调用。可用于动画进度条或在文本字段中显示日志。

    doInbackground() 计算的结果是 onPostExecute(Result) 的参数,所以在 doinBackground() 中返回结果并在 onPostExecute(Result) 中显示你的 toast

    为了清楚起见,请查看以下主题下的链接 4 个步骤。

    http://developer.android.com/reference/android/os/AsyncTask.html

    您也可以为此使用处理程序。

    http://developer.android.com/reference/android/os/Handler.html

    【讨论】:

      【解决方案4】:

      Conisder 解决方案不为每个字段从资产创建字体。 例如,使静态方法返回 Typeface。 我正在为 UI 线程中没有性能问题的列表元素设置字体。

      例如:

      public class CustomAdapter extends BaseAdapter {
      
      static Typeface mFont = YourClass.getDefaultTypeFace();
      
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
         ...
         TextView tv;
         ... 
         tv.setTypeface(mFont);
         ...
        }
      }
      

      此外,字体资源的内存分配存在一些问题,请勿创建多个字体实例。检查一下,对我来说非常适合: To use or not to use Custom Fonts on Android

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-05
        • 2011-03-18
        相关资源
        最近更新 更多