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发送回调[重复]的主要内容,如果未能解决你的问题,请参考以下文章