代码之家  ›  专栏  ›  技术社区  ›  Ben L.

是否存在Android AsyncTaskQueue或类似产品?

  •  1
  • Ben L.  · 技术社区  · 16 年前

    我在某个地方读到(并观察到)启动线程很慢。我一直假设AsyncTask创建并重用了一个线程,因为它需要在UI线程内部启动。

    从ListAdapter的GetView方法调用以下(匿名)代码以异步加载图像。它工作得很好,直到用户快速移动列表,然后它变为“ janky “。

    final File imageFile = new File(getCacheDir().getPath() + "/img/" + p.image);
    image.setVisibility(View.GONE);
    view.findViewById(R.id.imageLoading).setVisibility(View.VISIBLE);
    (new AsyncTask<Void, Void, Bitmap>() {
        @Override
        protected Bitmap doInBackground(Void... params) {
            try {
                Bitmap image;
                if (!imageFile.exists() || imageFile.length() == 0) {
                    image = BitmapFactory.decodeStream(new URL(
                            "http://example.com/images/"
                                    + p.image).openStream());
                    image.compress(Bitmap.CompressFormat.JPEG, 85,
                            new FileOutputStream(imageFile));
                    image.recycle();
                }
                image = BitmapFactory.decodeFile(imageFile.getPath(),
                    bitmapOptions);
                return image;
            } catch (MalformedURLException ex) {
                // TODO Auto-generated catch block
                ex.printStackTrace();
                return null;
            } catch (IOException ex) {
                // TODO Auto-generated catch block
                ex.printStackTrace();
                return null;
            }
        }
    
        @Override
        protected void onPostExecute(Bitmap image) {
            if (view.getTag() != p) // The view was recycled.
                return;
                view.findViewById(R.id.imageLoading).setVisibility(
                    View.GONE);
            view.findViewById(R.id.image)
                    .setVisibility(View.VISIBLE);
            ((ImageView) view.findViewById(R.id.image))
                    .setImageBitmap(image);
        }
    }).execute();
    

    我认为基于队列的方法会更好地工作,但是我想知道是否有这样的方法,或者我是否应该尝试创建自己的实现。

    2 回复  |  直到 16 年前
        1
  •  1
  •   Francesco Laurita    16 年前

    示例中解释了该键 List13.java

    基本上,您必须跟踪ListView的滚动状态并通知 当适配器准备用刚刚可见的东西做一些缓慢的事情时 项目。

    还要注意,将图像保存到磁盘是一个非常缓慢的过程。使用A 基于内存的缓存状态将大大提高性能 应用。

        2
  •  1
  •   Community Mohan Dere    9 年前
    1. 我可以看到您解码图像并将其压缩回磁盘,然后您再次解码它。我想不是很有效。在解压之后,您可以将流从网络保存到磁盘。那只是一次减压,而不是3次减压。可以节省大量的CPU处理时间。

    2. 我认为AsyncTask为几个映像创建了几个线程。所以有几个图像同时被压缩/解压,几个线程争夺CPU时间,不是很好。据我所知,AsyncTask使用线程池,因此它不会为每个映像启动新的线程。但不管怎么说,几个线程同时不是那么好。我同意排队会更有效。实现本身并不难创建。我使用自己的队列实现,我对此非常满意。

    3. 如果你有你自己的线索,我认为可以给它一个较低的优先级。这将使UI更具响应性。

    4. 您当然需要某种内存缓存,否则UI速度不够快。减压很慢。您不能存储所有图像,只能存储最常用的图像。可以使用SoftReference实现缓存。您可以使用InsampleSize选项使位图变小并占用更少的内存。 Strange out of memory issue while loading an image to a Bitmap object .

    我做了一个完整的Lazylist例子并发布了源代码,可能也会有所帮助。 Lazy load of images in ListView .