android asynctask向ui发送回调[重复]

Posted

技术标签:

【中文标题】android asynctask向ui发送回调[重复]【英文标题】:android asynctask sending callbacks to ui [duplicate] 【发布时间】:2012-04-15 08:40:32 【问题描述】:

我有以下不在活动内的 asynctask 类。在活动中,我正在初始化异步任务,并且我希望异步任务将回调报告回我的活动。 可能吗?或者 asynctask 是否必须与活动在同一个类文件中?

protected void onProgressUpdate(Integer... values) 

    super.onProgressUpdate(values);
    caller.sometextfield.setText("bla");

这样的?

【问题讨论】:

我不知道这个。有时,这可能会对你有所帮助AsyncTask Example 【参考方案1】:

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

例如:

你的界面:

public interface OnTaskCompleted
    void onTaskCompleted();

您的活动:

public class YourActivity implements OnTaskCompleted
    // your Activity

还有你的 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,即使在用户离开屏幕(或旋转设备)后,它也会保留在内存中。 如果Activity 已经被销毁,AsyncTask 不会将结果传递给Activity。您必须添加额外的代码来管理所有这些东西,否则您需要进行两次操作。 在Activity 中执行所有操作的复杂代码

当您觉得自己已经成熟到可以继续使用 Android 时,请查看 this article,我认为这是使用异步操作开发 Android 应用的更好方法。

【讨论】:

@DmitryZaitsev 非常好的建议,我认为这是解决非私有内部类 AsyncTask 问题的最佳解决方案 :-) @DmitryZaitsev 很好的答案。但请告诉我现在如何根据您的代码在我的活动中调用 Asyntask? 我正在尝试这个新的 HttpCallsAsyncTask(context, null, null, //Object OF the Interface).execute();在这种情况下如何传递接口对象?并且建议我必须传递接口对象,因为您已经声明了具有接口对象的默认构造函数。请帮忙 这里的异步任务不应该使用弱引用吗?因为任务可能会泄漏活动,否则。 @JacksOnF1re 一方面是 - 当然应该。另一方面,我认为这会使答案变得非常复杂,因为我认为它主要是由 Android 新手阅读的。最后,我不认为AsyncTask 是一件好事。使用它有很多问题,所以我认为它不值得任何“改进”。即使您添加WeakReferece,您仍然会遇到生命周期的其他问题。【参考方案2】:

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

我已经声明了回调接口

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

            
        );
    

谢谢

【讨论】:

又出现内存泄漏情况 我一直在寻找确切的解决方案并找到了这个线程,但我不明白上述所有操作背后的原因。在这种情况下,异步任务在 MainActivity 中执行,访问 UI 不是问题。同样可以通过更新 asynctask 的 onPostExecute() 方法中的 UI 来完成,而无需为此使用特殊接口。最好解决的问题是从另一个非活动类触发异步任务并从那里更新 UI。 和你一样..这是像我这样的初学者的最佳答案] @user1530779 为什么这是内存泄漏情况? @user3764893 如果 Activity 实现了接口并在 AsyncTask 完成之前被销毁(即由于方向更改),则 AsyncTask 持有对该 Activity 的强引用。这导致垃圾收集器不收集活动对象。我建议的解决方案非常简单:在活动的 onDestroy() 方法中将委托引用设置为 null。【参考方案3】:

在完成上述答案后,您还可以为您执行的每个异步调用自定义回退,以便对通用 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);

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

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;


    

【讨论】:

这个想法不错,但要小心Main.FragmentCallback 的匿名实现——它可能会泄露Activity。考虑使用WeakReference 究竟为什么这个问题被问到上面的回答如果在 Asynctask 作为其匿名内部类运行时活动被破坏,则泄漏活动,该类对您的活动的引用是隐式引用【参考方案4】:

我会重复其他人所说的,但会尽量让它更简单......

首先,创建接口类

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

完成!

【讨论】:

以上是关于android asynctask向ui发送回调[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Android中的AsyncTask和接口回调使用详解

Android 多线程 AsyncTask 完成后台任务并反馈给UI

AsyncTask Android - 设计模式和返回值

Android中AsyncTask的使用

示例:使用AsyncTask的Android双向网络套接字

201709013工作日记--Android异步通信AsyncTask