0

系统似乎正在回收视图,直到它在我的列表视图中加载正确位置的视图,导致重复的图像和文本几秒钟。任何人都可以帮忙吗?

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View v = convertView;
    Log.d("position",""+position);

    if(v==null){
        LayoutInflater inflater = LayoutInflater.from(mContext);
        v = inflater.inflate(R.layout.layout_appinfo, null);

        holder = new ViewHolder();
        holder.ivAppIcon = (ImageView)v.findViewById(R.id.ivIconApp);
        holder.tvAppName = (TextView)v.findViewById(R.id.tvNameApp);
        holder.progress = (ProgressBar)v.findViewById(R.id.progress_spinner);
        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }
    holder.ivAppIcon.setImageDrawable(null);
    holder.tvAppName.setText(null);
    holder.progress.setVisibility(View.VISIBLE);
    holder.ivAppIcon.setVisibility(View.GONE);

    // Using an AsyncTask to load the slow images in a background thread
    new AsyncTask<ViewHolder, Void, Drawable>() {
        private ViewHolder v;
        private ResolveInfo entry = (ResolveInfo) mListAppInfo.get(position);

        @Override
        protected Drawable doInBackground(ViewHolder... params) {
            v = params[0];
            return entry.loadIcon(mPackManager);
        }

        @Override
        protected void onPostExecute(Drawable result) {
            super.onPostExecute(result);
            // If this item hasn't been recycled already, hide the
            // progress and set and show the image
            v.progress.setVisibility(View.GONE);
            v.ivAppIcon.setVisibility(View.VISIBLE);
            v.ivAppIcon.setImageDrawable(result);
            v.tvAppName.setText(entry.loadLabel(mPackManager));
        }
    }.execute(holder);
    return v;
}

static class ViewHolder {
      TextView tvAppName;
      ImageView ivAppIcon;
      ProgressBar progress;
      //int position;
}

就好像位置设置错误了几秒钟。

4

3 回答 3

6

您可以让 ViewHolder 持有对 AsyncTask 的引用。时convertView != null,您可以调用cancel()ViewHolder 持有的 AsyncTask,因为您知道它正在加载的图像对于这一新行将不正确。在doInBackgrond()and中,在做任何事情之前onPostExecute()先检查一下。if(!isCancelled())

static class ViewHolder {
    TextView tvAppName;
    ImageView ivAppIcon;
    ProgressBar progress;
    AsyncTask task;
}

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        /* inflate new view, make new ViewHolder, etc. */
        ...
    } else {
        holder = (ViewHolder) convertView.getTag();
        holder.task.cancel();
    }

    // always make a new AsyncTask, they cannot be reused
    holder.task = new AsyncTask ...
    holder.execute(...);
    ...
}
于 2013-08-05T02:32:28.220 回答
2

Android 的开发者文档对此有一个很好的部分:

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

如上所述,这个问题是您的 AsyncTask 保持对已被回收的视图的硬引用。

于 2013-08-05T02:35:31.193 回答
0

当您通过适配器提供视图时,您可以立即将当前项目图像视图设置为标准加载图像或不设置任何内容。这将始终“重置”图像,同时将其加载到您的异步任务中。这可能是保持回收视图的性能优势的最佳方法。文本也是如此。

于 2013-08-05T02:32:56.213 回答