2012-02-09 51 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