2012-02-09 35 views
2

您好我有一些关于Looper.prepare()和AsyncTasks的问题。Android Looper.prepare()和AsyncTask

在我的应用程序中,我有一个AsyncTask启动其他AsyncTasks。我有2个AsyncTasks搜索和GetImage。 GetImage任务在搜索任务中执行多次。它工作正常。

不过最近我实现了图像缓存这里描述: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

我实现了这个之后我开始间断性死机

02-09 17:40:43.334:W/System.err的(25652) :java.lang.RuntimeException:无法在未调用Looper.prepare的线程中创建处理程序()

我不知道应该在哪里调用prepare()。下面的代码

Search extends AsyncTask{ 

    @Override 
    protected void doInBackground(){ 
     ArrayList<Object> objs = getDataFromServer(); 
     ArrayList<View> views = new ArrayList<View>(); 
     for(Object o: objs){ 
      //multiple AsyncTasks may be started while creating views 
      views.add(createView(o)); 
     } 
     for(View v: views){ 
      publishProgess(v); 
     } 
    } 
} 

public View createView(Object o){ 

    //create a view 
    ImageView iv = .....; 
    ImageDownloader.getInstance().download(url,iv); 
} 

的ImageDownloader可以在链接中可以看出上面的粗线条它是另一种的AsyncTask下载图像以及。它还包含一个处理程序和Runnable,用于清除每次下载时重置的缓存。我做了一次ImageDownloader的改变,我做了一个单例。

public static ImageDownloader getInstance(){ 
    if(instance == null){ 
     //tried adding it here but it results in occasional 
     //cannot create more than one looper per thread error 
     Looper.prepare(); 
     instance= new ImageDownloader(); 
    } 
    return instance; 
} 

的ImageDownloader下载方法可被称为10的次数,这是为每个下载的创建AysncTask。所以我在过去的几天一直在挠头,希望你们能帮忙。

回答

6

真正发生的是你正试图在需要UI线程运行的后台线程上执行某些操作。

Looper是系统的一部分,可确保事务按顺序完成,并且设备正在响应。

95%的时间,当你得到Looper错误,它意味着你需要将部分代码移动到UI线程中,在Asynctask中,这意味着将它移动到onPostExecuteonProgressUpdate

在你的情况下,它看起来好像你添加视图,这是UI的一部分,因此会导致问题。如果这实际上不是导致问题的原因,那么对堆栈跟踪的检查应该会给你一些线索。请注意,如果您必须拨打Looper.prepare(),我会在您的线索开始时调用它。但是,这通常建议避免需要调用它。

+0

你的意思是我不应该在AysncTask中产生一个AsyncTask而不调用Looper.prepare()或者更好的办法吗?另外,如果我在搜索任务的doInBackground()的开始处调用Looper.prepare(),它将处理从doInBackGround()中产生多个AsyncTasks? – triggs 2012-02-09 19:10:54

+0

我唯一的评论是,我听说android开发人员提到他们想限制异步任务,一次只允许一个,以防止“滥用”。我会建议设计一个更简化的方法来执行您的结果。 – Pyrodante 2012-02-09 19:28:51

+0

@Pyrodante是完全正确的,除非你使用AsyncTask#executeOnExecutor(),你不需要Looper.prepare()。你的问题是从后台进程更新UI,因为已经pryodante解释。 AsyncTask#executeOnExecutor()适用于将线程放入新线程池以避免长时间等待繁忙队列。任何如何使用,建议采取预防措施。你最好先阅读文档。 – 2016-01-02 05:27:28