Web图像在Android的线程加载线程、图像、加载、Web

2023-09-06 14:18:05 作者:并不觉得夏琳有多贱

我有一个ListActivity扩展BaseAdapter:

I have an extended BaseAdapter in a ListActivity:

private static class RequestAdapter extends BaseAdapter {

和一些处理程序和可运行在它定义

and some handlers and runnables defined in it

// 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功能,我得到这样的看法:

In the getView function of the Adapter, I'm getting the view like this:

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();
        }

和图像加载越来越是这样的:

and the image is getting loaded this way:

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();

现在,我遇到的问题是,如果有需要,显示同样的画面更多的项目,不是所有的这些照片显示得到。当你上下滚动列表,也许你最终填补所有的人。

Now, the problem I'm having is that if there are more items that need to display the same picture, not all of those pictures get displayed. When you scroll up and down the list maybe you end up filling all of them.

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

When I tried the commented out line (holder.avatar.setImageBitmap...) the app sometimes force closes with "only the thread that created the view can request...". But only sometimes.

任何想法,我怎么能解决这个问题?任一选项。

Any idea how I can fix this? Either option.

推荐答案

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

When getView is called you've got a avatar ImageView. You should pass this instance to sepThread, and sepThread should pass this instance to mUpdateResults. This way the bitmap will be displayed exactly to ImageView it was downloaded for. Otherwise bitmap is displayed to some budddyIcon instance that is incorrect. Your thread was downloading image for some time and when it's ready budddyIcon references another ImageView because another getView has already been called.

应该是这个样子的:

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);
}

当然,作为disretrospect上面说,你应该知道回收convertViews的。

And of course you should be aware of recycled convertViews as disretrospect says above.

我做LazyList的一个完整的例子,并张贴源,也可能是有帮助的http://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012.

I made a complete example of LazyList and posted the source, may also be helpful http://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012.