Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android中线程加载的Web图像_Android_Image_List_Multithreading_Adapter - Fatal编程技术网

android中线程加载的Web图像

android中线程加载的Web图像,android,image,list,multithreading,adapter,Android,Image,List,Multithreading,Adapter,我在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 Run

我在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();
        }
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);
    }
}
图像以这种方式加载:

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…)时,应用程序有时会强制关闭“只有创建视图的线程才能请求…”。但只是有时候


你知道我该怎么解决这个问题吗?任一选项。

因此,您不应该尝试在其他线程中将图像添加到视图中。我的建议是使用类似以下内容的异步任务:

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();
        }
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);
    }
}
有关异步任务的更多信息,请查看:

当调用getView时,您将获得一个化身ImageView。您应该将此实例传递给sepThread,sepThread应该将此实例传递给mUpdateResults。通过这种方式,位图将精确显示为其下载目的的ImageView。否则,位图将显示给不正确的BuddyIcon实例。您的线程下载图像已经有一段时间了,当它准备好时,BuddyIcon引用了另一个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);
}
当然,正如disretrospect上面所说的,您应该了解这些视图


我制作了一个完整的LazyList示例,并发布了源代码,可能也会有所帮助。

有一个很棒的库友,可以从web下载/缓存图像


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

几周前我遇到了同样的问题,我认为这是由于从web加载的速度,因为当我改变加载方式时,每一张图片都正确显示。现在,我正在下载应用程序开头的图片(仅在请求时),并将其放入数据库,然后将其从数据库获取到listview。在应用程序打开时缓存图片也是值得的。私有静态HashMap-sImageCache;将它们存储在hashmap中,并使用url作为标识符。如果在位图加载完成之前回收与位图相关的视图,在快速滚动期间会发生什么?我不知道这个类,比使用
Thread
s和
Handler
sYeh要干净得多,在列表视图中缓慢加载图像时,这可能很棘手。最好是传入一个对象,该对象包含imageView本身和要加载的图像的url。将这些存储在列表中。然后,当您尝试加载新图像时,请检查此列表中是否存在该视图的任何早期实例,并将其删除。此外,如果你正在做一个快速滚动,我会禁用图像加载,直到滚动速度减慢。让我看看我是否理解这个ok。我制作了一个包含imageview和url的列表。那么,当一个图片加载的时候,我会在列表中签入吗?你的意思是检查相同的URL吗?为什么要删除它们呢?所以每次加载图像时,都要将url和imageview包装在一个对象中,并将其放入列表中。然后检查列表中较早的条目,查看您的新对象.imageView.equals(列表中的旧imageView)是否相等。如果您获得了一个匹配项,那么您可以从列表中删除旧条目,因为它现在的视图已被回收。一旦加载了一个图像,请确保也将其从列表中删除。如何将实例传递给线程?然后回到runnable?我同意这是最好的办法。