将AsyncTask作为非静态方法真的很不好吗? (我的应用似乎可以在AS中使用此警告,但我显然不希望在我的应用中造成内存泄漏。
我在我的应用程序中使用ASyncTask
通过REST API从Web服务(Bitly)获取一些数据(短URL)。
ASyncTask
完成后,我想将结果传回我的MainActivity
。
使用MainActivity
的onPostExecute
方法可将数据返回到AsyncTask
。>
我已经阅读并阅读了有关如何执行此操作的信息,似乎有两种通用方法。
最初,我使用的是'WeakReference'方法,其中,在AsyncTask
类的开始,您会如下创建对MainActivity
的弱引用:
private class testFullURLreachable extends AsyncTask<Void, Void, String> { private WeakReference<MainActivity> mainActivityWeakReference; myASyncTask(MainActivity activity) { mainActivityWeakReference = new WeakReference<>(activity); } {etc etc}
通过这种方法,您的
AsyncTask
类位于您的MainActivity
类之外,因此很多事情需要通过弱引用进行引用。
这很好(除非我怀疑-可能是错误地-偶尔使用此NPE可能是导致这种错误的原因,但后来我发现了另一种处理方法。
第二种方法涉及将ASyncTask
类移到MainActivity
类的内部。
这样,我可以直接访问MainActivity
类中可访问的所有内容,包括MainActivity
中定义的UI元素和方法。这也意味着我可以访问字符串等资源,并且可以生成toasts
来告知用户正在发生的事情。
在这种情况下,可以删除上面的整个WeakReference
代码,并且可以将AsyncTask
类设为私有。
然后,我也可以直接在onPostExecute
中进行此类操作,或者将其保存在MainActivity
中的方法中,我可以直接从onPostExecute
进行调用:short_progress_bar.setIndeterminate(false);short_progress_bar.setVisibility(View.INVISIBLE);
if (!shortURL.equals("")) { // Set the link URL to the new short URL short_link_url.setText(shortURL); } else { CommonFuncs.showMessage(getApplicationContext(), getString(R.string.unable_to_shorten_link)); short_link_url.setHint(R.string.unable_to_shorten_link); }
(请注意,
CommonFuncs.showMessage()
是我自己在toast函数周围的包装器,以使其易于调用。)>但是,然后,Android Studio发出警告,“
AsyncTask
类应该是静态的,否则可能会发生泄漏”。
如果将方法设为静态,则会收到警告,因为我想从MainActivity
调用的方法来自onPostExecute
,因此该方法是非静态的。
如果我将MainActivity
中的方法设为静态方法,则它将无法访问字符串资源和任何其他非静态方法-顺其自然!”
如果您只是将代码从MainActivity
中的方法移到onPostExecute
方法中,这也是您所期望的。所以...
WeakReference
方法实际上是更正确,更安全的方法吗?WeakReference
方法,如何创建需要在UI线程和访问字符串上运行的类似toasts
的内容MainActivity
中的资源等?我读过一些有关创建interface
的内容,但有点迷茫,无法再次找到它。同样,这会不会像MainActivity
那样依赖WeakReference
,这是一件坏事吗?
我真的在寻找最佳实践指南,该指南如何将数据从MainActivity
中安全地传送回AsyncTask
和UI线程,并且不会冒内存泄漏的危险。
我在我的应用程序中使用ASyncTask通过REST API从Web服务(Bitly)获取一些数据(短URL)。当ASyncTask完成时,我想将结果传递回我的MainActivity。得到...
将AsyncTask作为非静态方法真的很不好吗? (我的应用似乎可以在AS中使用此警告,但我显然不希望在我的应用中造成内存泄漏。
是,您的视图和上下文将泄漏。
足够的旋转,您的应用将崩溃。
WeakReference方法实际上是更正确,更安全的方法吗?
这是在死猪身上涂的口红,在这种情况下,WeakReference更像是一个hack,而不是一个解决方案,绝对不是正确的解决方案。
您正在寻找的是一种来自something
的事件总线,它比Activity寿命长。您可以为此使用保留的片段*或Android体系结构组件ViewModel。而且您可能需要引入观察者模式(但不一定是LiveData)。
如果使用WeakReference方法,如何创建敬酒之类的东西需要在UI线程上运行并从MainActivity访问字符串资源等?
不要在doInBackground()
中执行此类操作。
我真的是在寻找最佳实践指南,以了解如何从AsyncTask将一些数据返回MainActivity和UI线程,这是安全的,不会冒内存泄漏的危险。最简单的方法是使用this library(或编写自己做的事情,由您自己决定),将
EventEmitter
放入ViewModel
,然后在其中订阅/取消订阅此EventEmitter您的活动。
public class MyViewModel: ViewModel() {
private final EventEmitter<String> testFullUrlReachableEmitter = new EventEmitter<>();
public final EventSource<String> getTestFullUrlReachable() {
return testFullUrlReachableEmitter;
}
public void checkReachable() {
new testFullURLreachable().execute()
}
private class testFullURLreachable extends AsyncTask<Void, Void, String> {
...
@Override
public void onPostExecute(String result) {
testFullUrlReachableEmitter.emit(result);
}
}
}
并且在您的活动/片段中
private MyViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); viewModel = ViewModelProviders.of(this).get(MyViewModel.class); // ... } private EventSource.NotificationToken subscription; @Override protected void onStart() { super.onStart(); subscription = viewModel.getTestFullUrlReachable().startListening((result) -> { // do `onPostExecute` things here }); } @Override protected void onStop() { super.onStop(); if(subscription != null) { subscription.stopListening(); subscription = null; } }
将AsyncTask作为非静态方法真的很不好吗? (我的应用似乎可以在AS中使用此警告,但我显然不希望在我的应用中造成内存泄漏。