我试图理解AsyncTaskLoaders的一些细节。对于其他人来说,这可能是显而易见的,但是我无法找到一个明确的示例或定义来演示和夸大当您覆盖deliverResult()
方法时会发生什么。实际交付的是什么?它如何与调用对象交互?我可以看到super.deliverResult
的使用,它传递了类中的私有对象。因此,加载程序是否自动知道与"交付的结果"相关联的内容。我完全糊涂了。
答案 0 :(得分:24)
我似乎有点迟到了,但无论如何......
后台加载和UI线程的回调onLoadFinished()
被调用之间的这个中间步骤的主要优点之一
loadInBackground()
deliverResult()
和onLoadFinished()
它为我们提供了一种从AsyncTaskLoader
类中快捷整个加载过程的方法。
这可以很好地用于缓存AsyncTaskLoader中的加载结果,可以防止在缓存数据时发生后台加载。
为什么我们要这样做?加载程序处理那些可怕的活动生命周期问题(例如,旋转设备),维护状态(比如缓存数据)以及在基础数据更改时有一种更新方法(CursorLoader),这不是重点吗? 嗯,是的,但这不是整个故事。
考虑这个用例:
您的应用程序(具有AsynTaskLoader的应用程序)已启动并且已经将数据加载到您的UI中。
然后,您切换到您的Twitter应用程序以检查一些新闻并返回到您的应用程序。
不缓存,在返回到您的应用后,加载程序将执行重新加载。
此行为与配置更改后的行为不同,例如旋转你的设备,在这种情况下不会重新加载。
那么,我们如何阻止加载器重新获取数据,以防我们将应用程序发送到后台,然后再返回它?
AsyncTaskLoader
实施中创建缓存成员变量。deliverResult()
,以便在调用superclass的deliverResult()实现之前先将提取的数据保存在缓存中。onStartLoading()
中检查是否有缓存数据,如果有,请让AsyncTaskLoader提供。否则,开始加载。这是指向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,而旧的加载程序将尝试加载数据。
答案 2 :(得分:0)
我能找到的唯一答案是基于this链接中的解密。
当您拥有AsyncTask的侦听器并希望将结果发送回它们时,似乎会使用"注册听众在收到Loader的结果时 完成一个负载。对于每个Loaders,LoaderManager 注册一个OnLoadCompleteListener,它将转发Loader 通过调用将结果传递给客户 onLoadFinished(装载程序加载程序,D结果)。装载机应该交付 结果给这些注册的听众打电话 Loader#deliverResult(D result)。"
deliverResult。我会说它并不常见。 Android documentation更具描述性:
"将加载结果发送给已注册的侦听器。应该只 由子类调用。必须从流程的主要部门调用 线程。
参数
数据:加载的结果"
答案 3 :(得分:-1)
deliverResult可以正常工作。它将结果D(由doInBackground返回)发送到调用线程。您可能希望覆盖它以清除数据,但您可以在doInBackground中进行清理,而不会覆盖deliverResult。