如何异步设置TextView的文本?

时间:2012-07-12 16:57:49

标签: android android-asynctask

我必须用ListView填写需要时间收集的文字信息。 我的方法是使用AsyncTask来执行后台作业,但是当结果到达时将文本设置为TextView会减慢列表:每次调用getView()时列表都会滞后。

这是我的AsyncTask班级

private class BreadcrumbTask extends AsyncTask<FFile, Void, String>{
    private WeakReference<TextView> mTextView; 
    public BreadcrumbTask(TextView textView){
        mTextView = new WeakReference<TextView>(textView);
    }

    @Override
    protected String doInBackground(FFile... params) {
           // text processing
    }

    @Override
    protected void onPostExecute(String result) {
        if (mTextView != null){
            TextView tv = mTextView.get();
            if (tv != null)
                //this line blocks the UI. if I comment it the lag is gone
                tv.setText(result); 
        }

// mTextView.setText(result);         }

我在getView()中创建了一个新任务,然后执行它。 问题显然来自tv.setText(result)中的onPostExecute()。当我评论列表很好地流动。那么如何在不降低用户界面的情况下更新TextView

3 个答案:

答案 0 :(得分:1)

使用ViewHolder模式。

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

在视图持有人中保留视图对象

在滚动ListView期间,您的代码可能经常调用findViewById(),这会降低性能。即使适配器返回一个膨胀的视图以进行回收,您仍然需要查找元素并更新它们。重复使用findViewById()的方法是使用“视图持有者”设计模式。

  

ViewHolder对象将每个组件视图存储在标记内   布局的字段,因此您可以立即访问它们而不需要   需要反复查找它们。首先,您需要创建一个类   保持您的确切观点。例如:

static class ViewHolder {
  TextView text;
  TextView timestamp;
  ImageView icon;
  ProgressBar progress;
  int position;
}
  

然后填充ViewHolder并将其存储在布局中。

ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);

其他一些例子:

http://xjaphx.wordpress.com/2011/06/16/viewholder-pattern-caching-view-efficiently http://www.jmanzano.es/blog/?p=166

答案 1 :(得分:0)

您无法从其他线程更新UI。但您可以使用Handler动态更新UI。在类中定义一个处理程序并按如下方式使用它:

<强>声明:

String result = "";
Handler regularHandler = new Handler(new Handler.Callback() {
    public boolean handleMessage(Message msg) {
        // Update UI
   if(msg.what==3){
    if (mTextView != null){
            TextView tv = mTextView.get();
            if (tv != null){
                //this line blocks the UI. if I comment it the lag is gone
                tv.setText(result); 
            }
        }
     }
        return true;
    }
});

您在onPostExecute中的代码

@Override
    protected void onPostExecute(String result) {
                //store the value in class variable result
                this.result = result;
                handler.sendEmptyMessage(3);
        }

答案 2 :(得分:0)

  @Override
protected void onPostExecute(String result) {

 if (mTextView != null){
        TextView tv = mTextView.get();
        if (tv != null)
            //this line blocks the UI. if I comment it the lag is gone
            tv.setText(result); 

}