首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >“LoaderManager”中“initLoader”和“restartLoader”的区别

“LoaderManager”中“initLoader”和“restartLoader”的区别
EN

Stack Overflow用户
提问于 2018-03-26 02:10:54
回答 2查看 0关注 0票数 0

我完全不明白initLoaderrestartLoader的职能LoaderManager:

  • 他们都有相同的签名。
  • restartLoader如果加载程序不存在,也会创建一个加载程序(“在此管理器中启动一个新的或重新启动一个现有的Loader”)。

这两种方法之间有什么关系吗?打电话restartLoader总是打电话initLoader是吗?我能打电话吗restartLoader不用打电话initLoader是吗?打电话省省吗?initLoader两次刷新数据?我什么时候应该使用其中之一和(重要!)为什么?

EN

回答 2

Stack Overflow用户

发布于 2018-03-26 10:22:58

要回答这个问题,需要深入了解LoaderManager代码。虽然LoaderManager本身的文档不够清楚(或者不存在这个问题),但是LoaderManagerImpl的文档(抽象LoaderManager的一个子类)更有启发性。

装载机

调用以使用Loader初始化特定ID。如果这个ID已经有一个与它相关联的Loader,那么它将保持不变,以前的回调将被新提供的回调替换。如果当前没有ID的加载程序,则创建并启动一个新的加载器。 该函数通常应在组件初始化时使用,以确保创建它所依赖的Loader。这允许它重用已有的装载机数据,例如,当一个活动在配置更改后被重新创建时,它就不需要重新创建它的加载器了。

重新启动装载机

调用以重新创建与特定ID关联的Loader。如果当前有与此ID相关联的加载程序,则将酌情取消/停止/销毁该ID。将创建一个具有给定参数的新Loader,一旦可用,就会将其数据传递给您。...调用此函数后,与此ID关联的任何以前的加载程序都将被视为无效,您将不会从它们收到进一步的数据更新。

基本上有两种情况:

  1. 带有id的加载程序不存在:这两种方法都将创建一个新的加载程序,因此没有区别
  2. 带有id的加载程序已经存在:initLoader将只替换作为参数传递的回调,而不会取消或停止加载程序。对于CursorLoader,这意味着游标保持打开和活动(如果在initLoader调用之前是这样的话)。另一方面,RestartLoader将取消、停止和销毁加载程序(并像游标一样关闭底层数据源),并创建一个新的加载器(如果加载程序是CursorLoader,它还会创建一个新的游标并重新运行查询)。

以下是这两种方法的简化代码:

装载机

代码语言:txt
复制
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;
}

重新启动装载机

代码语言:txt
复制
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...)。

我们必须区分两种情况:

  1. 处理配置更改本身:对于使用setRetainInstance(True)的片段,或者对于清单中使用了相应的Android:configChanges标记的活动,都是这样。这些组件在屏幕旋转后不会接收onCreate调用,所以请记住在另一个回调方法中调用initLoader/restartLoader(例如在onActivityCreated(Bundle)中)。为了能够初始化Loader,需要存储加载程序ID(例如,在列表中)。由于组件是跨配置更改保留的,所以我们只需循环现有加载程序ID并调用initLoader(loaderid。
  2. 不处理配置更改本身:在这种情况下,加载程序可以在onCreate中初始化,但我们需要手动保留加载程序ID,否则就无法进行所需的initLoader/restartLoader调用。如果ID存储在ArrayList中,我们将执行
票数 0
EN

Stack Overflow用户

发布于 2018-03-26 11:55:30

呼叫initLoader当Loader已经创建(例如,在配置更改之后)告诉LoaderManager将Loader的最新数据交付给onLoadFinished马上。如果尚未创建加载程序(例如,当活动/片段第一次启动时),则调用initLoader告诉LoaderManager调用onCreateLoader创建新的装载机。

呼叫restartLoader销毁已存在的Loader(以及与其相关的任何现有数据),并通知LoaderManager调用onCreateLoader来创建新的装载机并启动一个新的负载。

文档也非常清楚地说明了这一点:

  • initLoader确保装载机已初始化并处于活动状态。如果加载程序不存在,则创建一个加载程序,并启动加载程序(如果活动/片段当前已启动)。否则,最后创建的加载程序将被重用。
  • restartLoader在这个管理器中启动一个新的或重新启动一个现有的Loader,注册对它的回调,并且(如果活动/片段当前已经启动)开始加载它。如果先前启动了具有相同id的加载程序,则在新加载程序完成其工作时将自动销毁该加载程序。回调将在旧加载程序销毁之前交付。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100003218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档