繁体   English   中英

如何在Android上将图片下载器移到单独的线程中?

[英]How do I move my image downloader into a seperate thread on Android?

我的Android设备上运行了以下代码。 它效果很好,并且可以很好地显示我的列表项。 它也很聪明,因为它仅在ArrayAdapter需要时才下载数据。 但是,在进行缩略图下载的同时,整个列表停顿了,直到完成下载后您才能滚动。 有什么方法可以使它穿线,以便它仍然可以快乐地滚动,也许显示一个用于下载图像的占位符,完成下载,然后显示?

我想我只需要将我的downloadImage类放到它自己的线程中,以便与UI分开执行。 但是如何将其添加到我的代码中是一个谜!

任何帮助,将不胜感激。

private class CatalogAdapter extends ArrayAdapter<SingleQueueResult> {

    private ArrayList<SingleQueueResult> items;

    //Must research what this actually does!
    public CatalogAdapter(Context context, int textViewResourceId, ArrayList<SingleQueueResult> items) {
        super(context, textViewResourceId, items);
        this.items = items;

    }

    /** This overrides the getview of the ArrayAdapter. It should send back our new custom rows for the list */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View v = convertView;
        if (v == null) {
            LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.mylists_rows, null);

        }
        final SingleQueueResult result = items.get(position);
        // Sets the text inside the rows as they are scrolled by!
        if (result != null) {

            TextView title = (TextView)v.findViewById(R.id.mylist_title);
            TextView format = (TextView)v.findViewById(R.id.mylist_format);
            title.setText(result.getTitle());
            format.setText(result.getThumbnail());

            // Download Images
            ImageView myImageView = (ImageView)v.findViewById(R.id.mylist_thumbnail);
            downloadImage(result.getThumbnail(), myImageView);

        }

        return v;
    }
}

// This should run in a seperate thread
public void downloadImage(String imageUrl, ImageView myImageView) {

    try {
        url = new URL(imageUrl);
        URLConnection conn = url.openConnection();
        conn.connect();
        InputStream is = conn.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        Bitmap bm = BitmapFactory.decodeStream(bis);
        bis.close();
        is.close();
        myImageView.setImageBitmap(bm);
    } catch (IOException e) {
        /* Reset to Default image on any error. */
        //this.myImageView.setImageDrawable(getResources().getDrawable(R.drawable.default));
    }
}

这是我在应用程序中使用的内容的简化版本:

// this lives in Application subclass and is reused
public static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();

// the method itself

    public void attachImage(final String fileUrl, final ImageView view) {
        EXECUTOR.execute(new Runnable() {

            @Override
            public void run() {
                final Drawable image = methodThatGetsTheImage(fileUrl);
                if (image != null) {
                    view.post(new Runnable() {

                        @Override
                        public void run() {
                            view.setImageDrawable(drawable);
                        }
                    });
                }
            }
        });
    }

您也可以签出cwac-thumbnail以获得嵌入式解决方案(尽管它比上面的简单解决方案有更多的开销)。 我几乎可以在任何可以下载Web图像的地方使用它,并且都取得了巨大的成功。 您基本上为应用程序设置了一些全局缓存选项,然后将ListAdapter包裹在ThumbnailAdapter中,并在列表中包含android:imageviews的ID列表,然后在适配器的getView方法中对imageviews调用setTag(imageUrl),然后它处理其余的。

是。 您应该尽可能避免在UI线程上运行。 当您使用getView()时,您位于UI线程上。 要做到这一点,请执行以下操作:

new Thread(new Runnable(){

  public void run() {
    // your code here

  }}).start();

然后,当您需要以某种方式修改视图时,请回到UI线程,如下所示:

runOnUiThread(new Runnable(){

  public void run() {
    // your view-modifying code here

  }});

..或使用View.post()机制。

在您的示例中,将发生的情况是该项目将在图像可供显示之前显示在屏幕上。 我建议使用“加载”微调器或其他占位符向用户指示发生了什么。

实际上,您可以多次这样嵌套,尽管您将达到简化设计的目的。 匿名类在内存方面可能是低效的,并且在没有取消机制的情况下触发许多线程可能有其自身的缺点。

由于getView()退出后修改视图的副作用,您可能会遇到一些困难。 某些视图可能需要调用invalidate()才能使更改生效。 还要注意,如果要在getView()中回收视图,则应确保在执行更改视图的代码时,该视图仍用于所应用的内容。 setTag()/ getTag()在这里有用,用于存储数据的某些ID,您以后可以检查以确保View未被回收。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM