使用 LoaderManager 的多个加载器的模式?

Posted

技术标签:

【中文标题】使用 LoaderManager 的多个加载器的模式?【英文标题】:Pattern for multiple Loaders with LoaderManager? 【发布时间】:2012-03-07 10:57:17 【问题描述】:

我正在使用 Fragments 和 LoaderManager。我必须启动未知数量的任务,它们可能会并行运行(否则我只会重用一个且只有一个加载器)。例如,我有一个列表视图,每一行可能都有一个按钮来将该行的内容保存到网络服务器。用户可以同时对多个项目发起保存请求。

private int nextId = 0;

private void onClickListener() 
    Bundle bundle = new Bundle();
    bundle.putNextData(...);
    getLoaderManager().initLoader(nextId++, bundle, this);

我可以尝试自己记账,所以手动创建一个加载器池并在可能的情况下重用它们,看起来它可能已经被 API 实现了?

谢谢

【问题讨论】:

好问题。你设法解决了吗?我认为你应该以某种方式排队你的任务。 【参考方案1】:

我认为您不应该使用 Loader 将数据保存到远程服务器。

改为使用IntentService 或类似的东西来处理“保存”操作队列。这样一来,您与网络服务器的通信可以被批处理、折叠(即,单个项目的多个排队保存可以折叠到一个操作中),并且如果需要,将超出您的活动生命周期。

IntentService(或等效项)处理的保存队列也是使用退避重试失败操作的好方法,因为您可以使用AlarmManager 实现具有指数退避的延迟重试。

【讨论】:

如果我在数据库中有n 类别,我想使用CursorLoader 加载它们。我应该使用什么 ID? 您当然可以使用任意 ID,如果类别是静态的,可能只使用整数 1..n。如果您首先加载类别列表,然后加载每个类别的详细信息,那么您可能需要优化查询。但是假设您没有其他选择,您应该使用稳定的 id 作为 Loader id,而不是例如光标位置。【参考方案2】:

IntentService 或绑定服务始终是解决此问题的好方法。 正如 Roman 指出的那样,请注意,不强烈建议将多个请求排入队列并分别调用它们(很有可能您在无线电连接上做了大量工作 - 在使用数据时 - 这会耗尽您的电池。这里是 @987654321 @关于那个)

我个人建议使用具有请求队列和可用线程池的绑定服务(这种方法可以让您完全控制更复杂的网络操作,例如您的情况)。有更多关于here 方法的详细信息以及here 上的测试用例工作示例。

向我们更新您的进度。

【讨论】:

【参考方案3】:

你的方向是对的,让我帮你一点。

重用确实是个好主意,您不必担心,因为 android 已经为您做到了(实际上是 Java ;)

它称为ThreadPoolExecuter,您可以启动任意数量的任务,并且他只会打开预定义数量的线程。(最佳实践是尝试打开尽可能多的线程,因为可以在设备上运行并行网络连接。根据我的研究,它在 4 - 9 之间)。

如果您尝试两次下载相同的 URL,您可以保护自己并只为它打开一个任务。

【讨论】:

以上是关于使用 LoaderManager 的多个加载器的模式?的主要内容,如果未能解决你的问题,请参考以下文章

用于在多个活动/片段中重用的全局加载器 (LoaderManager)

Loader详解

使用 LoaderManager 加载依赖查询的首选方法

你可以使用服务中的 LoaderManager 吗?

LoaderManager与Loader使用理解

Android-LoaderManager异步加载数据库数据