你能在Service中使用LoaderManager吗?

40

我有一个使用自定义 Loader 和 Cursor 设置的数据加载系统,在 Activities 和 Fragments 中运行良好,但是在 Service 中找不到 LoaderManager(我无法找到)。 有人知道为什么从 Service 中排除了 LoaderManager 吗?如果没有,是否有绕过此问题的方法?

2个回答

53

有没有人知道为什么LoaderManager被排除在Service之外?

如其他答案所述,LoaderManager 的设计目的是通过管理 ActivitiesFragments 的生命周期来管理 Loaders。由于 Services 没有这些要处理的配置更改,因此不需要使用 LoaderManager

如果不行有什么解决办法吗?

是的,诀窍在于您不需要使用 LoaderManager,您可以直接使用您的 Loader,它将异步加载数据并监视任何底层数据更改,并且比手动查询数据要好得多。

首先,在创建 Service 时创建、注册和启动加载您的 Loader

@Override
public void onCreate() {
    mCursorLoader = new CursorLoader(context, contentUri, projection, selection, selectionArgs, orderBy);
    mCursorLoader.registerListener(LOADER_ID_NETWORK, this);
    mCursorLoader.startLoading();
}

接下来,在您的Service中实现OnLoadCompleteListener<Cursor>来处理加载回调。

@Override
public void onLoadComplete(Loader<Cursor> loader, Cursor data) {
    // Bind data to UI, etc
}

最后,不要忘记在Service被销毁时清理你的Loader

@Override
public void onDestroy() {

    // Stop the cursor loader
    if (mCursorLoader != null) {
        mCursorLoader.unregisterListener(this);
        mCursorLoader.cancelLoad();
        mCursorLoader.stopLoading();
    }
}

1
很有趣。假设我们正在执行onLoadComplete,而光标数据发生了变化。那么onLoadComplete的执行会突然停止,并重新开始处理新的光标吗?我只是想了解如何在服务中迭代光标时优雅地处理数据刷新。 - faizal
据我所见,由于onLoadCompleteService的主线程上调用,任何后续对onLoadComplete的调用都将简单地堆叠并在初始onLoadComplete完成后执行新的Cursor。这几乎与使用LoaderManager从几个后续数据更改中调用onLoadFinished时获得的行为完全相同。 - Steven Byle
@StevenByle 我认为你也应该调用 mCursorLoader.reset() 来关闭 cursor。 根据源代码,'reset()' 将调用 onStopLoading();(等同于 stopLoading),然后关闭 cursor。否则,cursor 不会被关闭。 - MyDogTom
这种方法可能有效,但不能保证服务能在合理的时间内完成请求。 - roberto tomás

18

很遗憾,不行。加载器是为活动和片段设计的,以便干净地处理在活动和片段中发生的配置更改,即旋转设备并重新连接到现有数据。

服务没有任何配置更改,它将保持在后台,直到完成或系统被强制杀死。因此,假设您正在服务中的后台线程上执行代码(无论如何都应该这样做),那么没有使用加载器的理由。只需调用所需的查询数据。

因此,如果您的服务只是IntentService,则可以编写逻辑来在onHandleIntent()方法中查询支持游标的数据。

http://developer.android.com/guide/components/loaders.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接