将 Loader 与 Fragment/Activity 和 UI 小部件一起使用会触发对加载器内容的更新
using Loader with a Fragment/Activity with UI widgets triggering updates to the loaders content
我使用 Loaders API 有一段时间了。我发现它是一个很好的解决方案和最优雅的设计来解决大多数应用程序的一般问题:显示 "processed" 动态内容,对 Fragment
/Activity
的干扰最小 - 加载数据的责任和其背后的所有逻辑都封装在 Loader 中...
当 UI 由从加载程序返回的数据初始化时,问题就开始了,它触发了它初始化时使用的相同数据的更改。
为了更清楚,假设我们的主要 Activity 或 Fragment 显示无穷无尽的 post 列表(如 Facebook 或 Google+ 应用程序)。假设此应用使用某种 AsyncTaskLoader
或 CusorLoader
:
显示 post 列表的 ListView
将在 Activity
生命周期的正确时间使用加载程序数据进行初始化。
现在假设同时收到 GCM 推送,并触发了对数据源的更新。仍然一切都很好:加载程序将使用数据更改更新 activity。
以下扫描变得混乱:
1) 用户点击了 post 之一的 "Like" 按钮
2) 后台任务/服务启动网络操作以更新服务器post状态
3) UI 应该立即更改(适配器通知数据集已更改)而无需等待网络响应,因为用户必须知道发生了什么事情(也可能不是全屏阻塞进度条)
4)网络请求完成(不一定成功)
在接下来的扫描中,各方面都变得非常快失控:
假定由加载程序独家负责更新的相同小部件被迫在本地更新以反映不一定是数据源的 "final" 状态的临时状态(例如 - 如果网络响应由于各种原因而失败......)
现在假设网络操作尚未完成并且仍在运行中,并且出于另一个原因(GCM 推送/其他正在执行的后台操作)加载程序重新加载并通知activity 有新数据。现在已经很不舒服了:有一个新数据,但是 UI 仍然处于我之前描述的模式。我发现自己实现了解决此类冲突的逻辑,并决定 UI 是否需要对加载程序数据源做出反应。
现在将这个问题乘以您可以在 post 上执行的操作数量,以及 post 的数量。
出于这种原因,我的结论是当数据源可以从由该数据初始化的相同 UI 触发的 "writing" 操作发生很大变化时,加载程序是一个非常有问题的解决方案来源。
但是,另一方面,我看不到任何其他解决方案可以在优雅的设计中处理我描述的问题,尽管这是一种非常常见的情况。
我的问题基本上是:
在我描述的这种情况下,是否有关于如何使用加载程序的指南?
是否有更好的解决方案/API 我没有想到的组件或设计可以满足此类要求?
提前致谢,
并非如此Loader 是非常有问题的解决方案。相反,Web 服务调用和推送通知是 异步的 ,以及将这些传送的结果数据集成到现有数据集中的问题(并在 Activity
/ Fragment
生命周期)是一个复杂的情况,框架试图尽可能地简化和概括。这些概括是 LoaderManager
、ContentProvider
和 SyncAdapter
类 及其相关技术。
在没有看到任何现有代码或提出任何其他高级解决方案的情况下,这是我可以敦促您尝试的最简单的事情(如果您还没有尝试过的话):每当网络服务调用完成或收到通知,请致电
Loader.reset();
或
LoaderManager.restartLoader();
并确保将 Adapter
清除为
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// clear your adapters here
listview.setAdapter(null);
viewpager.setAdapter(null);
}
这会将新添加的数据加载到视图中。当异步任务完成时,程序员有责任刷新数据集。
我使用 Loaders API 有一段时间了。我发现它是一个很好的解决方案和最优雅的设计来解决大多数应用程序的一般问题:显示 "processed" 动态内容,对 Fragment
/Activity
的干扰最小 - 加载数据的责任和其背后的所有逻辑都封装在 Loader 中...
当 UI 由从加载程序返回的数据初始化时,问题就开始了,它触发了它初始化时使用的相同数据的更改。
为了更清楚,假设我们的主要 Activity 或 Fragment 显示无穷无尽的 post 列表(如 Facebook 或 Google+ 应用程序)。假设此应用使用某种 AsyncTaskLoader
或 CusorLoader
:
显示 post 列表的 ListView
将在 Activity
生命周期的正确时间使用加载程序数据进行初始化。
现在假设同时收到 GCM 推送,并触发了对数据源的更新。仍然一切都很好:加载程序将使用数据更改更新 activity。
以下扫描变得混乱:
1) 用户点击了 post 之一的 "Like" 按钮
2) 后台任务/服务启动网络操作以更新服务器post状态
3) UI 应该立即更改(适配器通知数据集已更改)而无需等待网络响应,因为用户必须知道发生了什么事情(也可能不是全屏阻塞进度条)
4)网络请求完成(不一定成功)
在接下来的扫描中,各方面都变得非常快失控:
假定由加载程序独家负责更新的相同小部件被迫在本地更新以反映不一定是数据源的 "final" 状态的临时状态(例如 - 如果网络响应由于各种原因而失败......)
现在假设网络操作尚未完成并且仍在运行中,并且出于另一个原因(GCM 推送/其他正在执行的后台操作)加载程序重新加载并通知activity 有新数据。现在已经很不舒服了:有一个新数据,但是 UI 仍然处于我之前描述的模式。我发现自己实现了解决此类冲突的逻辑,并决定 UI 是否需要对加载程序数据源做出反应。
现在将这个问题乘以您可以在 post 上执行的操作数量,以及 post 的数量。
出于这种原因,我的结论是当数据源可以从由该数据初始化的相同 UI 触发的 "writing" 操作发生很大变化时,加载程序是一个非常有问题的解决方案来源。
但是,另一方面,我看不到任何其他解决方案可以在优雅的设计中处理我描述的问题,尽管这是一种非常常见的情况。
我的问题基本上是:
在我描述的这种情况下,是否有关于如何使用加载程序的指南?
是否有更好的解决方案/API 我没有想到的组件或设计可以满足此类要求?
提前致谢,
并非如此Loader 是非常有问题的解决方案。相反,Web 服务调用和推送通知是 异步的 ,以及将这些传送的结果数据集成到现有数据集中的问题(并在 Activity
/ Fragment
生命周期)是一个复杂的情况,框架试图尽可能地简化和概括。这些概括是 LoaderManager
、ContentProvider
和 SyncAdapter
类 及其相关技术。
在没有看到任何现有代码或提出任何其他高级解决方案的情况下,这是我可以敦促您尝试的最简单的事情(如果您还没有尝试过的话):每当网络服务调用完成或收到通知,请致电
Loader.reset();
或
LoaderManager.restartLoader();
并确保将 Adapter
清除为
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// clear your adapters here
listview.setAdapter(null);
viewpager.setAdapter(null);
}
这会将新添加的数据加载到视图中。当异步任务完成时,程序员有责任刷新数据集。