android asynctask向ui发送回调

Asa*_*evo 146 android android-asynctask

我有以下asynctask类,它不在活动中.在我正在初始化asynctask的活动中,我希望asynctask将回调报告回我的活动.可能吗?或者asynctask是否必须与活动位于同一个类文件中?

protected void onProgressUpdate(Integer... values) 
{
    super.onProgressUpdate(values);
    caller.sometextfield.setText("bla");
}
Run Code Online (Sandbox Code Playgroud)

像这样的东西?

Dmi*_*sev 392

您可以创建一个interface,将其传递给AsyncTask(在构造函数中),然后调用方法onPostExecute()

例如:

你的界面:

public interface OnTaskCompleted{
    void onTaskCompleted();
}
Run Code Online (Sandbox Code Playgroud)

你的活动:

public class YourActivity implements OnTaskCompleted{
    // your Activity
}
Run Code Online (Sandbox Code Playgroud)

而你的AsyncTask:

public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
    private OnTaskCompleted listener;

    public YourTask(OnTaskCompleted listener){
        this.listener=listener;
    }

    // required methods

    protected void onPostExecute(Object o){
        // your stuff
        listener.onTaskCompleted();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

由于这个答案很受欢迎,我想补充一些东西.

如果您是Android开发的新手,那么在AsyncTask不阻止UI线程的情况下,这是一种快速的方法.确实解决了一些问题,班级如何运作并没有错.但是,它带来了一些影响,例如:

  • 内存泄漏的可能性.如果您继续引用Activity它,即使用户离开屏幕(或旋转设备),它也会保留在内存中.
  • AsyncTaskActivity如果Activity已经被破坏,则不会提供结果.你必须添加额外的代码来管理所有这些东西,或者你做两次操作.
  • 解决所有问题的复杂代码 Activity

如果您觉得自己已经足够成熟,可以继续使用Android,那么请看一下这篇文章,我认为这是使用异步操作开发Android应用程序的更好方法.

  • @DmitryZaitsev非常好的建议,我认为这是非私有内部类AsyncTask问题的最佳解决方案:-) (3认同)
  • @DmitryZaitsev 很好的答案。但请告诉我如何根据您的代码在我的活动中调用 Asyntask? (2认同)
  • asynctask不应该在这里使用弱引用吗?由于任务可能会泄漏活动. (2认同)

Ars*_*had 44

我觉得下面的方法非常简单.

我已经声明了一个回调接口

public interface AsyncResponse {
    void processFinish(Object output);
}
Run Code Online (Sandbox Code Playgroud)

然后创建异步任务以响应所有类型的并行请求

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

    //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后单击活动类中的按钮时调用异步任务.

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        Button mbtnPress = (Button) findViewById(R.id.btnPress);

        mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);          
                        mbtnPress.setText((String) output);
                    }
                });
                asyncTask.execute(new Object[] { "Youe request to aynchronous task class is giving here.." });

            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢


Mig*_*uel 6

完成上述答案后,您还可以为每个异步调用自定义回退,以便每次调用通用ASYNC方法都会填充不同的数据,具体取决于您放在那里的onTaskDone内容.

  Main.FragmentCallback FC= new  Main.FragmentCallback(){
            @Override
            public void onTaskDone(String results) {

                localText.setText(results); //example TextView
            }
        };

new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id);
Run Code Online (Sandbox Code Playgroud)

提醒:我在"Main"所在的主要活动上使用了界面,如下所示:

public interface FragmentCallback {
    public void onTaskDone(String results);


}
Run Code Online (Sandbox Code Playgroud)

我的API post执行如下所示:

  @Override
    protected void onPostExecute(String results) {

        Log.i("TASK Result", results);
        mFragmentCallback.onTaskDone(results);

    }
Run Code Online (Sandbox Code Playgroud)

API构造函数如下所示:

 class  API_CALL extends AsyncTask<String,Void,String>  {

    private Main.FragmentCallback mFragmentCallback;
    private Context act;
    private String method;


    public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) {
        act=ctx;
        method=api_method;
        mFragmentCallback = fragmentCallback;


    }
Run Code Online (Sandbox Code Playgroud)

  • 想法很好,但要小心`Main.FragmentCallback`的匿名实现 - 它可能泄漏`Activity`.考虑使用`WeakReference`. (3认同)