2012-02-09 18 views
2

こんにちは私はLooper.prepare()とAsyncTasksに関するいくつかの質問があります。Android Looper.prepare()とAsyncTask

私のアプリでは、他のAsyncTasksを開始しているAsyncTaskがあります。私は2つのAsyncTasks SearchとGetImageを持っていました。 GetImageタスクは、検索タスク内で複数回実行されます。それはうまく動作します。ここで説明するように

しかし、最近私は、画像のキャッシュを実装:私はこれを実装した後 http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

は私が入門断続的にクラッシュし

2月9日17:40:43.334:をSystem.err/W(25652) :java.lang.RuntimeException:Looper.prepare()を呼び出していないスレッド内でハンドラを作成できません

私はprepare()を呼び出すべきかわかりません。それは、画像のaswellをダウンロードするには、別のAsyncTaskがある。ここ

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は、上記のリンクで見ることができるコードの大まかな概要です。また、ダウンロードが発生するたびにリセットされるキャッシュをパージするためのHandlerとRunnableも含まれています。私はImageDownloaderに1つの変更を加えました。私はそれをシングルトンにしました。

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のダウンロード方法はダウンロードごとにAysncTaskを作成している時間の10年代、呼び出すことができます。だから、私はここ数日、頭を掻き回しています。皆さんが助けてくれることを願っています。

答えて

6

実際には、UIスレッドを実行する必要があるバックグラウンドスレッドで何かを実行しようとしています。

Looperは、トランザクションが順番に実行され、デバイスが応答するようにシステムの一部です。

Looperエラーが発生した時の95%は、コードの一部をUIスレッドに移動する必要があることを意味し、AsynctaskではonPostExecuteまたはonProgressUpdateのいずれかに移動します。

あなたのケースでは、UIの一部であるビューを追加しているように見えるため、問題が発生します。それが問題の原因となっていない場合は、スタックトレースを調べると手がかりが得られるはずです。

Looper.prepare()を呼び出す必要がある場合は、スレッドの先頭で呼び出す必要があります。ただし、これを呼び出す必要がないようにすることが一般的に推奨されます。

+0

あなたはLooper.prepare()を呼び出さずにAysncTask内からAsyncTaskを生成するべきではない、というのはいいですか?また、検索タスクでdoInBackground()の開始時にLooper.prepare()を呼び出すと、doInBackGround()から複数のAsyncTaskが生成されますか? – triggs

+0

私の唯一のコメントは、アンドロイドの開発スタッフが、非同期タスクを「濫用」を防ぐために一度に1つしか許可しないように制限したいと言っていると聞いています。私はあなたの結果を実行するためのより合理的な方法を工夫することをお勧めします。 – Pyrodante

+0

@Pyrodanteは完全に正しいですが、AsyncTask#executeOnExecutor()を使用しない限り、Looper.prepare()は必要ありません。あなたの問題は、すでにpryodanteが説明しているように、バックグラウンドプロセスからUIを更新することです。 AsyncTask#executeOnExecutor()は、新しいスレッドプールにスレッドを入れて、ビジー状態のキューを長く待たないようにするのに適しています。それを使用する方法については、予防措置が推奨されます。最初に文書を読む方がよいでしょう。 –

関連する問題