AsyncTaskLoader.deliverResult()实际上做了什么?

时间:2014-08-11 01:11:54

标签: android asynctaskloader

我试图理解AsyncTaskLoaders的一些细节。对于其他人来说,这可能是显而易见的,但是我无法找到一个明确的示例或定义来演示和夸大当您覆盖deliverResult()方法时会发生什么。实际交付的是什么?它如何与调用对象交互?我可以看到super.deliverResult的使用,它传递了类中的私有对象。因此,加载程序是否自动知道与"交付的结果"相关联的内容。我完全糊涂了。

4 个答案:

答案 0 :(得分:24)

我似乎有点迟到了,但无论如何......

后台加载和UI线程的回调onLoadFinished()被调用之间的这个中间步骤的主要优点之一

  1. loadInBackground()
  2. deliverResult()
  3. 回调onLoadFinished()
  4. 它为我们提供了一种从AsyncTaskLoader类中快捷整个加载过程的方法。 这可以很好地用于缓存AsyncTaskLoader中的加载结果,可以防止在缓存数据时发生后台加载

    为什么我们要这样做?加载程序处理那些可怕的活动生命周期问题(例如,旋转设备),维护状态(比如缓存数据)以及在基础数据更改时有一种更新方法(CursorLoader),这不是重点吗? 嗯,是的,但这不是整个故事。

    考虑这个用例
    您的应用程序(具有AsynTaskLoader的应用程序)已启动并且已经将数据加载到您的UI中。 然后,您切换到您的Twitter应用程序以检查一些新闻并返回到您的应用程序。 不缓存,在返回到您的应用后,加载程序将执行重新加载。 此行为与配置更改后的行为不同,例如旋转你的设备,在这种情况下不会重新加载。

    那么,我们如何阻止加载器重新获取数据,以防我们将应用程序发送到后台,然后再返回它?

    解决方案

    1. AsyncTaskLoader实施中创建缓存成员变量。
    2. 覆盖 deliverResult(),以便在调用superclass的deliverResult()实现之前先将提取的数据保存在缓存中。
    3. onStartLoading() 中检查是否有缓存数据,如果有,请让AsyncTaskLoader提供。否则,开始加载。
    4. 这是指向sample app which implements this behaviour的链接。 它只是一个“玩具应用程序”,也是Udacity当前版本"Developing Android Apps" fundamentals course的一部分。并here is the link在该课程中处理此问题的相应视频。 (该课程是免费的,但您仍需要注册Udacity)。

      简而言之,这个应用程序演示的是一个UI,用户可以在其中输入搜索查询以搜索GitHub的repos(通过GitHub API),在TextView中显示生成的搜索URL以及从GitHub获取的原始JSON在另一个TextView中 整个动作仅在MainActivity.java中发生,此处的相关部分位于AsyncTaskLoader内,作为匿名内部类实现:

      • 对于第1步,只需在AsyncTaskLoader实施中引入一个成员变量,该实施用作数据缓存

        /* This String will contain the raw JSON
           from the results of our Github search */
        String mGithubJson;
        
      • 对于第2步,覆盖 deliverResult()以缓存加载结果。
        loadInBackground()完成后,会将其返回值传递给deliverResult()。 无论如何它都是这样做的,但是现在我们已经覆盖了deliverResult(),我们可以直接进入存储到我们创建的缓存成员变量中这么好的远见。 最后,我们使用super.deliverResult()链接到deliverResult()的超类实现,它将结果传递给在UI线程上运行的回调方法onLoadFinished()

        @Override
        public void deliverResult(String githubJson) {
            mGithubJson = githubJson;
            super.deliverResult(githubJson);
        }
        
      • 对于第3步,检查 onStartLoading()是否我们是否有缓存数据
        如果我们 还没有缓存数据,只需强制加载以调用forceLoad()开始。 但是如果我们已经缓存了数据,只需调用deliverResult(yourCachedDataGoesHere)并将缓存的数据作为参数传入。

        if (mGithubJson != null) {
            deliverResult(mGithubJson);
        } else {
            forceLoad();
        }
        

        因此,如果您现在在应用程序和其他应用程序之间来回切换,您会发现没有重新加载,因为加载程序只会使用您的缓存数据。

答案 1 :(得分:5)

假设当数据在后台加载时,此时用户按下HOME按钮并存在应用程序,当用户返回应用程序时,加载已完成。我们已经有了数据,然后AsyncTaskLoader会调用deliverResult()方法,将数据传递给onLoadFinished()方法进行显示。

当用户返回应用时,onStartLoading()之前正在调用loadInBackground()。在这种方法中,我们可以检查我们的数据是否为空,如果不为空,我们会调用deliverResult()并将结果发送到onLoaderFinished(),这样就可以防止重新加载数据。

当我们按HOME存在应用程序然后返回时,它将不会创建新的Loader,而旧的加载程序将尝试加载数据。

The order of each method

答案 2 :(得分:0)

我能找到的唯一答案是基于this链接中的解密。

  

"注册听众在收到Loader的结果时   完成一个负载。对于每个Loaders,LoaderManager   注册一个OnLoadCompleteListener,它将转发Loader   通过调用将结果传递给客户   onLoadFinished(装载程序加载程序,D结果)。装载机应该交付   结果给这些注册的听众打电话   Loader#deliverResult(D result)。"

当您拥有AsyncTask的侦听器并希望将结果发送回它们时,似乎会使用

deliverResult。我会说它并不常见。 Android documentation更具描述性:

  

"将加载结果发送给已注册的侦听器。应该只   由子类调用。必须从流程的主要部门调用   线程。

     

参数

     

数据:加载的结果"

答案 3 :(得分:-1)

在doInbackground完成后,

deliverResult可以正常工作。它将结果D(由doInBackground返回)发送到调用线程。您可能希望覆盖它以清除数据,但您可以在doInBackground中进行清理,而不会覆盖deliverResult。