我完全不明白initLoader
而restartLoader
的职能LoaderManager
:
restartLoader
如果加载程序不存在,也会创建一个加载程序(“在此管理器中启动一个新的或重新启动一个现有的Loader”)。这两种方法之间有什么关系吗?打电话restartLoader
总是打电话initLoader
是吗?我能打电话吗restartLoader
不用打电话initLoader
是吗?打电话省省吗?initLoader
两次刷新数据?我什么时候应该使用其中之一和(重要!)为什么?
发布于 2018-03-26 10:22:58
要回答这个问题,需要深入了解LoaderManager代码。虽然LoaderManager本身的文档不够清楚(或者不存在这个问题),但是LoaderManagerImpl的文档(抽象LoaderManager的一个子类)更有启发性。
装载机
调用以使用Loader初始化特定ID。如果这个ID已经有一个与它相关联的Loader,那么它将保持不变,以前的回调将被新提供的回调替换。如果当前没有ID的加载程序,则创建并启动一个新的加载器。 该函数通常应在组件初始化时使用,以确保创建它所依赖的Loader。这允许它重用已有的装载机数据,例如,当一个活动在配置更改后被重新创建时,它就不需要重新创建它的加载器了。
重新启动装载机
调用以重新创建与特定ID关联的Loader。如果当前有与此ID相关联的加载程序,则将酌情取消/停止/销毁该ID。将创建一个具有给定参数的新Loader,一旦可用,就会将其数据传递给您。...调用此函数后,与此ID关联的任何以前的加载程序都将被视为无效,您将不会从它们收到进一步的数据更新。
基本上有两种情况:
以下是这两种方法的简化代码:
装载机
LoaderInfo info = mLoaders.get(id);
if (info == null) {
// Loader doesn't already exist -> create new one
info = createAndInstallLoader(id, args, LoaderManager.LoaderCallbacks<Object>)callback);
} else {
// Loader exists -> only replace callbacks
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}
重新启动装载机
LoaderInfo info = mLoaders.get(id);
if (info != null) {
LoaderInfo inactive = mInactiveLoaders.get(id);
if (inactive != null) {
// does a lot of stuff to deal with already inactive loaders
} else {
// Keep track of the previous instance of this loader so we can destroy
// it when the new one completes.
info.mLoader.abandon();
mInactiveLoaders.put(id, info);
}
}
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
我们可以看到,如果加载程序不存在(info==NULL),这两个方法将创建一个新的加载器(info=createAndInstallLoader(...))。如果加载程序已经存在,则initLoader只替换回调(info.mCallback=...),而restartLoader则禁用旧加载程序(在新加载程序完成其工作时将销毁它),然后创建一个新加载程序。
因此,现在很清楚何时使用initLoader,何时使用restartLoader,以及为什么使用这两种方法是有意义的。如果不存在,则创建一个新的,如果一个已经存在,则被重用。除非需要新的加载程序,否则我们总是使用此方法,因为要运行的查询已经更改(不是底层数据,而是实际查询,如CursorLoader的SQL语句中的查询),在这种情况下,我们将调用restartLoader。
活动/片段生命周期与使用一种或另一种方法的决定无关(也不需要像Simon建议的那样使用一击标记来跟踪调用)!这一决定完全是基于对新装载机的“需求”。如果我们想运行相同的查询,我们使用initLoader,如果我们想运行不同的查询,我们使用restartLoader。我们总是可以使用RestartLoader,但这将是低效的。在屏幕旋转之后,或者如果用户离开应用程序,稍后返回到相同的活动,我们通常希望显示相同的查询结果,因此RestartLoader将不必要地重新创建加载程序,并排除底层(可能昂贵的)查询结果。
理解加载的数据与加载数据的“查询”之间的区别非常重要。假设我们使用CursorLoader查询订单表。如果向该表添加了新的订单,CursorLoader将使用onContentChanged()通知UI更新并显示新的顺序(在本例中无需使用restartLoader)。如果我们只想显示打开的订单,我们需要一个新的查询,我们将使用restartLoader返回一个新的CursorLoader,反映新的查询。
这两种方法之间有什么关系吗?
他们共享代码来创建一个新的Loader,但是当加载程序已经存在时,它们会执行不同的操作。
调用restartLoader总是调用initLoader吗?
不从来没有。
我可以调用restartLoader而不必调用initLoader吗?
是
调用initLoader两次刷新数据安全吗?
两次调用initLoader是安全的,但是不会刷新任何数据。
我什么时候应该使用其中之一和(重要!)为什么?
在我上面的解释之后,(希望)这应该是清楚的。
配置变化
LoaderManager在配置更改(包括方向更改)中保留其状态,因此您可能认为我们没有什么可做的了。再想想..。
首先,LoaderManager不会保留回调,所以如果什么都不做,就不会收到对诸如onLoadFined()之类的回调方法的调用,这很可能会破坏应用程序。因此,我们必须至少调用initLoader来恢复回调方法(当然,重新启动Loader也是可能的)。大
如果调用时调用方处于其启动状态,并且请求的加载程序已经存在并生成了其数据,则将立即(在此函数中)调用onLoadFined(Loader,D)
这意味着,如果我们在更改方向后调用initLoader,我们将立即得到onLoadFined调用,因为数据已经加载(假设在更改之前是这样的)。虽然这听起来很直接,但可能会很棘手(难道我们都喜欢Android...)。
我们必须区分两种情况:
https://stackoverflow.com/questions/-100003218
复制相似问题