从AsyncTask返回数据到MainActivity的最佳方法

问题描述 投票:0回答:1

我在我的应用程序中使用ASyncTask通过REST API从Web服务(Bitly)获取一些数据(短URL)。

ASyncTask完成后,我想将结果传回我的MainActivity

使用MainActivityonPostExecute方法可将数据返回到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方法中,这也是您所期望的。所以...

  • 将AsyncTask作为非静态方法真的很不好吗? (我的应用程式在AS中显示这个警告似乎可以正常运作,但我显然不想要在我的应用程序中造成内存泄漏。
  • 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; } }

java android android-activity android-asynctask static-methods
1个回答
0
投票

将AsyncTask作为非静态方法真的很不好吗? (我的应用似乎可以在AS中使用此警告,但我显然不希望在我的应用中造成内存泄漏。

© www.soinside.com 2019 - 2024. All rights reserved.