2

我在 ListActivity 中有一个扩展的 BaseAdapter:

private static class RequestAdapter extends BaseAdapter {

以及其中定义的一些处理程序和可运行对象

// Need handler for callbacks to the UI thread
    final Handler mHandler = new Handler();

    // Create runnable for posting
    final Runnable mUpdateResults = new Runnable() {
        public void run() {
            loadAvatar();
        }
    };

    protected static void loadAvatar() {
        // TODO Auto-generated method stub
        //ava.setImageBitmap(getImageBitmap("URL"+pic));
        buddyIcon.setImageBitmap(avatar);
    }

在适配器的 getView 函数中,我得到这样的视图:

if (convertView == null) {
            convertView = mInflater.inflate(R.layout.messageitem, null);

            // Creates a ViewHolder and store references to the two children views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.username = (TextView) convertView.findViewById(R.id.username);
            holder.date = (TextView) convertView.findViewById(R.id.dateValue);
            holder.time = (TextView) convertView.findViewById(R.id.timeValue);
            holder.notType = (TextView) convertView.findViewById(R.id.notType);
            holder.newMsg = (ImageView) convertView.findViewById(R.id.newMsg);
            holder.realUsername = (TextView) convertView.findViewById(R.id.realUsername);
            holder.replied = (ImageView) convertView.findViewById(R.id.replied);
            holder.msgID = (TextView) convertView.findViewById(R.id.msgID_fr);
            holder.avatar = (ImageView) convertView.findViewById(R.id.buddyIcon);
            holder.msgPreview = (TextView) convertView.findViewById(R.id.msgPreview);


            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }

并且图像正在以这种方式加载:

Thread sepThread = new Thread() {
                    public void run() {
                        String ava;
                        ava = request[8].replace(".", "_micro.");
                        Log.e("ava thread",ava+", username: "+request[0]);
                        avatar = getImageBitmap(URL+ava);
                        buddyIcon = holder.avatar;
                        mHandler.post(mUpdateResults);
                        //holder.avatar.setImageBitmap(getImageBitmap(URL+ava));
                    }
                };
                sepThread.start();

现在,我遇到的问题是,如果有更多项目需要显示同一张图片,则并非所有这些图片都会显示。当您向上和向下滚动列表时,您可能最终会填满所有列表。

当我尝试注释掉的行(holder.avatar.setImageBitmap ...)时,应用程序有时会强制关闭“只有创建视图的线程才能请求......”。但只是有时。

知道如何解决这个问题吗?任一种选择。

4

3 回答 3

1

所以你不应该尝试将图像添加到另一个线程的视图中。我的建议是使用类似这样的 AsyncTask:

class GetImageTask extends AsyncTask<String, int[], Bitmap> {

    @Override
    protected Bitmap doInBackground(String... params) {
      Bitmap bitmap = null;

      // Get your image bitmap here

      return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap bitmapResult) {
      super.onPostExecute(bitmapResult);
      // Add your image to your view
      holder.avatar.setImageBitmap(bitmapResult);
    }
}

您调用 AsyncTask 如下:

new GetImageTask().execute(param1, param2, etc);

有关 AsyncTask 的更多信息,请查看:http: //developer.android.com/reference/android/os/AsyncTask.html

于 2010-06-02T11:52:31.640 回答
1

当 getView 被调用时,你有一个头像 ImageView。您应该将此实例传递给 sepThread,而 sepThread 应将此实例传递给 mUpdateResults。这样,位图将准确地显示到为其下载的 ImageView。否则位图会显示给一些不正确的 budddyIcon 实例。您的线程正在下载图像一段时间,当它准备好时 budddyIcon 引用另一个 ImageView 因为另一个 getView 已经被调用。

应该看起来像这样:

public View getView(...){
  //skip
  (new SepThread(holder.avatar)).start();
}

public class SepThread extends Thread() {
    ImageView imageView;
    public SepThread(ImageVIew iv){
      imageView=iv;
    }
    public void run() {
        //skip
        Bitmap avatar = getImageBitmap(URL+ava);
        mHandler.post(new UpdateResults(imageView, avatar));
    }
};

class UpdateResults extends Runnable() {
  ImageView imageView;
  Bitmap bitmap;
  public UpdateResults(ImageView iv, Bitmap b){
    imageView=iv;
    bitmap=b;
  }
  public void run() {
      loadAvatar(imageView, bitmap);
  }
};

protected static void loadAvatar(ImageView iv, Bitmap b) {
    iv.setImageBitmap(b);
}

当然,您应该注意上面回溯所说的回收的 convertViews。

我做了一个 LazyList 的完整示例并发布了源代码,也可能对ListView 中的图像延迟加载有所帮助。

于 2010-06-02T14:14:31.897 回答
1

有这个很棒的库家伙可以从网上下载/缓存图像 https://github.com/koush/UrlImageViewHelper

只需输入 imageview 和 url,就完成了 =)

于 2011-05-06T21:51:45.623 回答