解决方法
后台加载和UI线程的回调onLoadFinished()调用之间的这个中间步骤的主要优点之一
> loadInBackground()
> deliverResult()和
>回调onLoadFinished()
是它为我们提供了一种从AsyncTaskLoader类中快捷整个加载过程的方法.
这可以很好地用于在AsyncTaskLoader中缓存加载结果,并防止在存在缓存数据时发生后台加载.
为什么我们要这样做呢?加载器处理那些可怕的活动生命周期问题(例如,旋转设备),维护状态(如缓存数据)以及在底层数据发生变化时有一种更新方法(CursorLoader),这不是重点吗?
嗯,是的,但这不是整个故事.
考虑这个用例:
您的应用程序(具有AsynTaskLoader的应用程序)已启动并且已经将数据加载到您的UI中.
然后,您切换到您的Twitter应用程序以检查一些新闻并返回到您的应用程序.
没有缓存,返回到您的应用程序后,加载程序将重新加载.
此行为与配置更改后的行为不同,例如旋转您的设备,在这种情况下不会重新加载.
那么,我们如何阻止加载器重新获取数据,以防我们将应用程序发送到后台,然后再返回它?
解
>在AsyncTaskLoader实现中创建缓存成员变量.
>覆盖deliverResult(),以便在调用超类的deliverResult()实现之前首先将获取的数据保存在缓存中.
>在onStartLoading()中检查是否有缓存数据,如果有,请让AsyncTaskLoader提供.否则,开始加载.
这是一个sample app which implements this behaviour的链接.
它只是一个“玩具应用程序”,也是Udacity当前版本“Developing Android Apps” fundamentals course的一部分.而here is the link则是该课程中相应视频处理此问题的部分. (该课程是免费的,但你仍然需要注册wddd).
简而言之,这个应用程序演示的是一个UI,用户可以在其中输入搜索查询以搜索GitHub的repos(通过GitHub API),在TextView中显示生成的搜索URL以及在另一个TextView中从GitHub获取的原始JSON .
整个操作只发生在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(); }
因此,如果您现在在应用程序和其他应用程序之间来回切换,您会发现没有重新加载,因为加载程序将只使用您的缓存数据.