Java Android工作线程冻结主线程
我正在开发一个应用程序,它实现了一个包含图像的自定义ListView。我能够让listview下载并缓存图像,但我想将下载转移到一个单独的线程上。为此,我创建了一个CachedLogoDownloader类,其目标是异步下载图像并将其保存在内存中,以便稍后由自定义适配器类访问 问题是线程占用了整个UI。即使run()中的代码只是一个“thread.sleep()”,只要出现对徽标图像的请求,UI就会停止。类似地,在run()中放置无限循环会导致程序无限期挂起Java Android工作线程冻结主线程,java,android,multithreading,android-layout,Java,Android,Multithreading,Android Layout,我正在开发一个应用程序,它实现了一个包含图像的自定义ListView。我能够让listview下载并缓存图像,但我想将下载转移到一个单独的线程上。为此,我创建了一个CachedLogoDownloader类,其目标是异步下载图像并将其保存在内存中,以便稍后由自定义适配器类访问 问题是线程占用了整个UI。即使run()中的代码只是一个“thread.sleep()”,只要出现对徽标图像的请求,UI就会停止。类似地,在run()中放置无限循环会导致程序无限期挂起 class CachedLogoDo
class CachedLogoDownloader{
private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();
Context context;
ArrayList<String> FIDs;
Thread runner;
public CachedLogoDownloader(Context inContext){
this.context = inContext;
//list of company logos (by FID) to be downloaded
FIDs = new ArrayList<String>();
//asynchronous downloader thread (single thread for lower-end devices. Shouldn't be much slower to get the images, though)
runner = new Thread(new Runnable() {
public void run() {
for(String FID:FIDs){
Log.d(Cloud.DEBUG_TAG, "Icon Runnable for: " + FID);
Bitmap tempImage = Cloud.lookupIcon(context, FID);
cache.put(FID, tempImage);
FIDs.remove(FID);
}
}
});
}
public Bitmap getLogo(Company aCompany){
String currentFID = aCompany.getFID();
//if the image has already been cached, return the cached image
if(cache.containsKey(currentFID))
{
return cache.get(currentFID);
}
else
{
//add the logo to the list of logos to be downloaded
FIDs.add(currentFID);
//if the downloader thread completed (or hasn't started yet) make it download stuff.
if(!runner.isAlive()){
runner.setPriority(Thread.MIN_PRIORITY);
runner.run();
}
//return null for now (until next time, whent the image will be in the cache!.)
return null;
}
}
class CachedLogoDownloader{
私有HashMap缓存=新建HashMap();
语境;
ArrayList FIDs;
螺纹流道;
公共CachedLogoDownloader(文本上下文){
this.context=inContext;
//要下载的公司徽标列表(通过FID)
FIDs=新的ArrayList();
//异步下载线程(用于低端设备的单线程。但是获取图像的速度应该不会太慢)
runner=新线程(新可运行(){
公开募捐{
用于(字符串FID:FIDs){
Log.d(Cloud.DEBUG_标记,图标可运行:“+FID”);
位图tempImage=Cloud.lookupIcon(上下文,FID);
cache.put(FID、tempImage);
FIDs.移除(FID);
}
}
});
}
公共标识(公司A公司){
字符串currentFID=aCompany.getFID();
//如果图像已经缓存,则返回缓存的图像
if(cache.containsKey(currentFID))
{
返回cache.get(currentFID);
}
其他的
{
//将徽标添加到要下载的徽标列表中
添加FIDs(当前FID);
//如果下载线程已完成(或尚未启动),请让它下载内容。
如果(!runner.isAlive()){
runner.setPriority(Thread.MIN_PRIORITY);
runner.run();
}
//现在返回空值(直到下一次,图像将在缓存中!)
返回null;
}
}
}
runner.run()
这不是启动单独的线程,而是在调用线程上执行run方法的内容。你可能想要
runner.start()
此外,不能多次启动线程,因此
如果(!runner.isAlive()){
此检查可能不是很有用。在需要映像时(或启动应用程序时)启动线程,然后等待它完成工作。如果需要更复杂的逻辑,如线程池或错误处理,则可能应该使用库来异步加载映像。而不是runner.run()您应该使用runner.start(),否则您的thread run()方法实际上在同一个线程中执行。