6

HTTP経由でデータを取得する必要がある多くのアクティビティでアプリを開発しています。データを取得したら、onPostExecute() コールバック メソッドで処理します。

これは、非同期タスクをインライン クラスとして定義すると問題なく動作しますが、複数のアクティビティで同じ処理を実行したいので、外部クラスとして定義しました。

問題は、外部クラスを使用して、データを戻す手段として呼び出し元のクラスに「イベント」を通知する方法です。C# でこれを行う方法は知っていますが、Java は初めてで、これを達成する方法がわかりません。

4

5 に答える 5

4

Listener が技術的に正しいのは事実ですが、私はそれが複雑すぎるか、または十分に複雑ではないと主張します。

より簡単な解決策は次のとおりです。

class Foo {
   class Bar extends AsyncTask<Void, Void, Result> {

      public void onPostExecute(Result res) {
         doSomething(res);
      }
   }

   public void doSomething(Result res) {
      /// process result
   }

   public void startTask() {
       new Bar().execute();
   }
}

以下と同等です。

class Bar extends AsyncTask<Void, Void, Result> {
     private final Foo foo;
     public Bar(Foo foo) { this.foo = foo; }

     public void onPostExecute(Result res) {
       foo.doSomething(res);
     }
}


class Foo {
   public void doSomething(Result res) {
      /// process result
   }

   public void startTask() {
       new Bar(this).execute();
   }
}

...これはあなたが尋ねたものです:内部クラスを引き出すと、暗黙のポインターが失われます。明示的にして渡すだけです。

悪いニュースは、このソリューションによってあらゆる種類のメモリ リークとライフサイクルの問題が発生することです。プログラムがさらに大きくなる前に、AsyncTask の代わりに IntentService の使用を検討し、Handler または Activity.runOnUiThread を使用して結果を UI スレッドに戻すことを強くお勧めします。

于 2013-01-21T22:52:07.443 に答える
3

1 つのアプローチ:

という名前の親抽象クラスを定義しますParentActivity(もちろん Activity を拡張します)。と呼ばれる抽象メソッドを含むようにするonAsyncCallback();

タスクを使用する各クラスでそのクラスを拡張し、メソッドを実装します。

AsyncTask コンストラクターで、ParentActivity.

例えば

ParentActivity activity;
public MyTask (ParentActivity myActivity)
{
 this.activity = myActivity;
}

で完了したらonPostExecute()、次のようにします。

activity.onAsyncCallback(data);

これはインターフェイスでも機能し、コンストラクターがリスナーインスタンスで受け入れられることを除いて、同じことを行います。

于 2013-01-21T21:54:52.920 に答える
2

クリーンな方法でやりたい場合は、次のアプローチを試してください

最初に、すべての非同期呼び出し名を含む列挙型を作成します

public enum TaskType {
    USER_LOGIN(1), GET_PRODUCTS(2), GET_EMPLOYEE(3);

    int value;

    private TaskType(int value) {
        this.value = value;
    }
}

次に、インターフェイスを作成します

public interface AsyncTaskListener {
    public void onTaskCompleted(String result, TaskType taskType);
}

GetAsyncTask を呼び出す予定のアクティビティにこのインターフェイスを実装します。

 public class LoginActivity extends Activity implements AsyncTaskListener {

 protected void onCreate(Bundle savedInstanceState) {
     String url = ".....";
     new GetAsyncTask(LoginActivity.this, LoginActivity.this, TaskType.USER_LOGIN).execute(url);
 }
    ...
    public void onTaskCompleted(String result, TaskType taskType) {
       if(taskType == TaskType.USER_LOGIN){
       //your login result handling here
       }
}

最後に、これはあなたの AsyncTask です

public class GetAsyncTask extends AsyncTask<String, Void, String> {
    String outputStr;
    ProgressDialog dialog;
    Context context;
    AsyncTaskListener taskListener;
    TaskType taskType;

    public GetAsyncTask(Context context, AsyncTaskListener taskListener, TaskType taskType){
        this.context = context;
        this.taskListener = taskListener;
        this.taskType = taskType;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
    }
    @Override
    protected String doInBackground(String... params) {
        String urlString = params[0];

        try {

            URL url = new URL(urlString);
            HttpURLConnection conn
                    = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            if (conn.getResponseCode() != 200) {
                throw new IOException(conn.getResponseMessage());
            }

            // Buffer the result into a string
            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = rd.readLine()) != null) {
                sb.append(line);
            }
            rd.close();
            conn.disconnect();
            String jsonStr = sb.toString();
            outputStr = jsonStr;
        } catch (SocketTimeoutException e) {
            outputStr = "timeout";
        }catch(Exception e){
            e.printStackTrace();
            outputStr = "error";
        }

        return outputStr;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        taskListener.onTaskCompleted(result, taskType);
        dialog.dismiss();
    }

}
于 2014-12-18T01:39:58.387 に答える
1

リスナーパターンを使用します。ここを見てくださいTaskListenerこのリスナーを使用するタスクタスクを呼び出すフラグメント

于 2013-01-21T21:58:28.950 に答える