我想要在屏幕上加载一块图像。所有图像都是我下载并存储在SD-CARD上的文件。
到目前为止,我找到了两种方法,首先是在活动开始时将它们加载到主线程上(我得到了大约70张图片,加载它们需要大约2.1秒)。
另一种方式是我现在正在测试的。将它们加载到分离的线程上,同时我可以为用户显示加载动画。目前我在ThreadPoolExecutor的实施时间为4.3秒。我是在10个线程上完成的。
最后一种方法,(这是我唯一没有测试的方法)是使用精灵表。
我无法使用应用程序缓存,因为在我的应用程序中我有很多屏幕,每个屏幕都有自己的图像集。
您如何看待,加载大量图像的最快方式是什么?您知道哪些加速技术可以帮助我?
答案 0 :(得分:9)
不要加载主线程。如果你阻止主线程,延迟2.1秒就会被ANR(应用程序无响应)错误杀死。
在单独的线程中加载。不要创建10个线程,只需创建一个AsyncTask,然后在doInBackground中依次加载所有图片。
在AsyncTask中加载应该花费(几乎)与在主线程中加载相同的时间。不要放太多花哨的动画,这样主线程就不会消耗太多的CPU时间。
答案 1 :(得分:2)
一种选择是使用WeakReference使用create image cache,这样当系统遇到内存不足的情况时,图像将从内存中删除。这样,您可以将图像保留在内存中,只有当它们不在内存中时才需要从SD卡加载。因此,您当前的活动将始终保持对位图所需的硬参考,并且图像缓存将保留对位图的弱引用。
以下是有关弱引用的更多信息:
StackOverflow post discussing using weak reference for cache
答案 2 :(得分:0)
实现此目的的一种方法是实现一种监听器/观察者。
从您的UI线程中,启动将加载图像的其他线程。加载图像后,线程将调用activity类中实现的回调方法来更新相应的图像视图。
而不是android asynch任务,我会去寻找我的线程(pooled / Executors)。我将在加载它们之前获取所有可能的图像路径,并将它们分派给加载图像的线程。在回调中我知道在哪里更新图像。
或者您也可以检查Loader在您的情况下的表现。
答案 3 :(得分:0)
显然,你不应该在UI线程中留下2s长的操作。
我认为ThreadPoolExecutor是一个godd解决方案,但在池中创建多个线程并不是最佳选择。在后台线程就足够了。我敢打赌,只要改变它,你就会有更好的表现。
我不建议直接在活动中使用AsyncTask
,因为it is fragile to config change。
我不建议使用精灵。在内存有限的移动设备上增加一个图像的大小非常危险。特别是对于精灵,你必须得到Bitmap
的部分,因此在内存中有一个完整的位图。
现在我没有发现你的具体问题,我认为你是Lazy loading of images in a listview,因为问题非常相似。