2012-04-01 57 views
129

我有以下asynctask类不在活动内。在活动中,我正在初始化asynctask,并且我希望asyncTask将回调报告回我的活动。 这可能吗?或者,asynctask必须与活动在同一个类文件中?android asynctask发送回调给UI

protected void onProgressUpdate(Integer... values) 
{ 
    super.onProgressUpdate(values); 
    caller.sometextfield.setText("bla"); 
} 

是这样的吗?

回答

365

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

例如:

你的接口:

public interface OnTaskCompleted{ 
    void onTaskCompleted(); 
} 

你的活动:

public class YourActivity implements OnTaskCompleted{ 
    // your Activity 
} 

An d您的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(); 
    } 
} 

编辑

由于这个答案变得十分流行,我想添加一些东西。

如果您是Android开发人员的新手,AsyncTask是一种快速生成工作而不会阻塞UI线程的方式。它确实解决了一些问题,班级的工作方式并没有错。但是,它带来一些暗示,如:

  • 内存泄漏的可能性。如果您继续参考Activity,即使在用户离开屏幕(或旋转设备)后,它仍会保留在内存中。
  • AsyncTask如果Activity已被销毁,则不会向Activity发送结果。你必须添加额外的代码来管理所有这些东西,或者做两次操作。
  • 费解的代码。当你觉得你成熟到能与Android移动上,看看this article我认为它,它确实在Activity

的一切,是一个更好的方式去开发Android应用与异步操作。

+0

应该在清单文件中写入asyntask类吗? – 2012-04-01 11:44:47

+1

@AsafNevo不,不应该 – 2012-04-01 11:58:49

+0

@Dmitry,除了onTaskCompleted以外,还有什么其他的监听器状态?那么onPreExecute呢? – rxlky 2013-03-24 00:14:46

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); 

提醒:我用的主要活动多数民众赞成在 “主” 说到界面,就像这样:

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


} 

我的API后执行这个样子的:

@Override 
    protected void onPostExecute(String results) { 

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

    } 

的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; 


    } 
+3

想法很好,但要小心使用'Main.FragmentCallback'的匿名实现 - 它可能会泄漏'Activity',考虑使用'WeakReference' – 2014-06-20 07:47:47

+0

正是为什么这个问题被问到以上答案的机器人如果活动被破坏,而Asynctask作为其匿名内部类别运行时有泄漏活动暗含参考 – user1530779 2015-07-07 08:07:32

37

我觉得下面的方法很简单。

我已宣布为回调

public interface AsyncResponse { 
    void processFinish(Object output); 
} 

然后创建异步任务的接口,用于响应所有类型的并行请求

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); 
    } 

} 

然后点击活动类的按钮时调用的异步任务的。

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.." }); 

      } 
     }); 
    } 
} 

感谢

+0

内存泄漏情况 – user1530779 2015-07-07 08:07:54

+0

我一直在寻找确切的解决方案,并找到了这个线程,但我不明白背后的原因以上全部。在这种情况下,asynctask在MainActivity中执行,其中访问UI不是问题。通过更新asynctask的onPostExecute()方法中的UI,可以实现同样的效果,而无需使用特殊的接口。要解决的问题是从另一个非活动类发起异步任务,并从那里更新UI。 – 2015-07-17 05:09:30

+0

跟你一样..这是像我这样的初学者的最佳答案] – 707 2016-11-13 11:37:08

2

我会重复别人说了什么,而只是试图使其更简单...

首先,刚刚创建的接口类

public interface PostTaskListener<K> { 
    // K is the type of the result object of the async task 
    void onPostTask(K result); 
} 

二,通过包含具体类来创建使用接口的AsyncTask(可以是您的活动或片段的内部静态类)。在该示例中,PostTaskListener使用String参数化,这意味着它需要一个String类作为异步任务的结果。

public static class LoadData extends AsyncTask<Void, Void, String> { 

    private PostTaskListener<String> postTaskListener; 

    protected LoadData(PostTaskListener<String> postTaskListener){ 
     this.postTaskListener = postTaskListener; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     super.onPostExecute(result); 

     if (result != null && postTaskListener != null) 
      postTaskListener.onPostTask(result); 
    } 
} 

最后,你的逻辑结合起来的部分。在您的活动/片段中,创建PostTaskListener并将其传递给异步任务。这里是一个例子:

... 
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() { 
    @Override 
    public void onPostTask(String result) { 
     //Your post execution task code 
    } 
} 

// Create the async task and pass it the post task listener. 
new LoadData(postTaskListener); 

完成!