1

アプリケーションの汎用タスク マネージャー クラスとして機能することを目的とした、AsyncTask を拡張するクラスがあります。

問題:進行状況ダイアログが表示されるが、決して閉じられないという奇妙な動作が発生します。

  • ここに置かれた場合、任意の Log.d("","") ステートメントが起動するため、onPostExecute() がすべてのタスク インスタンスに対して呼び出されると確信しています。トースト メッセージもこのメソッド内から表示されますが、できません。静的ダイアログを閉じます。

  • AsyncTask(s) が UI スレッドにアクセスできるのは [onPreExecute() と onPostExecute()] の 2 か所だけであることを理解しているので、runOnUiThread() でダイアログを閉じようとする必要はないと思います。

  • executeTask() へのすべての呼び出しは、さまざまなアクティビティのさまざまな onCreate() メソッドから行われ、UI 要素の一部を設定する前にネットワーク経由でデータを取得する必要があり、常に現在のアクティビティのコンテキストをタスクに渡します。

  • 関連するタスクが完了するまでアクティビティを切り替えないので、アクティビティ コンテキスト オブジェクトはまだ有効であると思います (これを仮定するのは間違っていますか??) デバッグ中にそれらのいずれかが null であることを発見したことはありません。

  • これはタイミングの問題でしょうか?また、ほとんどの場合、アクティビティが表示される前にすべてのタスクが完了していることを DDMS が示していることも確認しました。onCreate() で使用new Handler().postDelayed(runnable_which_calls_these_tasks,10);し、foo_X() に遅延コードを追加すると、アクティビティは遅延なく表示されますが、ダイアログはdismiss() しません。

この問題に関するかなりの数の記事を読みましたが、どこが間違っているのか正確にはわかりません. すべてのアクティビティ クラスのように各タスクを定義したくありません。private inner class Task1 extends AsyncTask<> また、(これが唯一の解決策でない限り) このディスカッションで述べたように、すべてのアクティビティ参照をアプリケーション オブジェクトにロードしたくありません。私は何かが足りないのですか?.

私はこれに1週間費やしましたが、まったく無知です:(誰かが私を導き、何が欠けているかを教えてくれれば素晴らしいことです.
クラス定義は次のとおりです:[明確にするために、無関係なアプリケーション固有のコードをいくつか削除しました]

public class NetworkTask extends AsyncTask<Void, Integer, Boolean> {  

private  Context UIcontext;  
private int operationType;  
private static ProgressDialog dialog;
private static int taskCount;


private NetworkTask(int operationType Context context){  
    this.UIcontext = context; 
    this.operationType = operationType;
    if (taskCount++ == 0)  
        dialog = ProgressDialog.show(context,"","Loading...");

}  

public static Boolean executeTask(int operationType, Context context) {
    return new NetworkTask(operationType, context).execute().get(); 
}

@Override  
protected void onPreExecute(){  
    super.onPreExecute();  
    if (taskCount == 1)  
        dialog.show();  
}  

@Override
protected Boolean doInBackground(Void... arg0) {  
switch(operationType){  
    case TYPE_1:  
        foo1();  
        break;  
    case TYPE_2:  
        foo2();  
        break;  
    case TYPE_3:  
        foo3();  
        break;  
    case TYPE_4:  
        foo4();  
        break;  
}  

@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(result);
    taskCount--;
    if (dialog.isShowing() && taskCount == 0){
            dialog.dismiss();
    }else {
        Toast.makeText(UIcontext, "Task#"+ operationType+", m done, but there are "+taskCount+" more", 5).show();
    }
}

}

4

1 に答える 1

2

編集:

謎が解けました - これは私を少し悩ませていました。いくつかの問題がありました:

  1. ダイアログが表示されなかった主な問題はNetworkTask.get(). これは、NetworkTask 全体が完了するのを待つブロッキング呼び出しです。その間、UI スレッドがブロックされるため、何も描画されません (他の UI 要素も応答しません)。削除get():

    public static Boolean executeTask(int operationType, Context context){
        new NetworkTask(operationType, context).execute();
        return true; // return whatever
    } 
    
  2. show()on ProgressDialog が 2 回呼び出されます。これは、2 つのダイアログを次々に表示します。show()内側を取り外しますonPreExecute()

  3. ProgressDialog はモーダルです。完了するまで UI の変更を防ぎます。Toast.makeText()前に呼び出されdialog.dismiss()ますが、ダイアログが画面への描画をブロックしているため、それらはキューに入れられ、ダイアログが閉じられた後に表示されます。

  4. super.onPostExecute(result)およびsuper.onPreExecute()冗長であるため、削除できます。

問題がある場合は、作業コード全体を投稿できます。

于 2010-11-15T16:45:24.750 に答える