系统似乎正在回收视图,直到它在我的列表视图中加载正确位置的视图,导致重复的图像和文本几秒钟。有人可以帮忙吗?
@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;
}
这几乎就好像位置设置错了几秒钟。
答案 0 :(得分:6)
您可以让ViewHolder保存对AsyncTask的引用。当convertView != null
时,您可以在ViewHolder持有的AsyncTask上调用cancel()
,因为您知道它正在加载的图像对于这个新行不正确。在doInBackgrond()
和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(...);
...
}
答案 1 :(得分:2)
Android的开发者文档有一个很好的部分:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
如上所述,这个问题是您的AsyncTask对已经被回收的视图保持了硬性引用。
答案 2 :(得分:0)
当您通过适配器提供视图时,可以将当前项目图像视图设置为标准加载图像,或立即设置任何内容。这将始终“重置”图像,同时它将加载到您的异步任务上。这可能是保持循环视图的性能优势的最佳方法。同样适用于文本。