3

我必须填写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(结果); }

我在 getView() 中创建了一个新任务并执行它。问题显然来自tv.setText(result)onPostExecute(). 当我发表评论时,列表很流畅。那么如何在TextView不减慢 UI 的情况下更新呢?

4

3 回答 3

1

使用ViewHolder模式。

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

将视图对象保留在视图持有者中

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

ViewHolder 对象将每个组件视图存储在 Layout 的 tag 字段中,因此您可以立即访问它们而无需重复查找它们。首先,您需要创建一个类来保存您的确切视图集。例如:

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

于 2012-07-12T17:17:05.470 回答
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); 

}
于 2012-07-12T17:25:21.533 回答
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);
        }
于 2012-07-12T17:16:11.567 回答