问题标签 [android-loader]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
android - 使用 getLoaderResultSynchronously 对 AsyncTaskLoader 进行单元测试
我正在尝试为执行一些 API 调用的 REST 客户端创建单元测试。客户端在实时应用程序中运行良好,但我无法让它在测试用例中运行。
显然, LoaderTestCase.getLoaderResultSynchronously() 可以在这里使用(至少根据Android参考,但它不会接受我的加载器。代码:
这会产生类型 LoaderTestCase 中的错误 getLoaderResultSynchronously(Loader) 不适用于参数 (RESTLoader)。
RESTLoader 扩展了 AsyncLoader。注意我用的是supportlibrary,可能里面的Loader不兼容?文档没有提供这方面的信息。
我尝试了几种方法来解决这个问题,但似乎都不起作用:
- 向加载程序注册了一个侦听器。但是,回调永远不会触发
- 使用 CountdownLatch(也与侦听器一起使用)。同样,没有触发/倒计时超时。
- 玩弄类型模板(),但没有成功。
- SO上的类似解决方案,尽管再次未能达到听众。
有人知道为什么 getLoaderResultSynchronously 不会接受加载器吗?或者另一种测试加载器的干净方法,包括测试返回数据的方法?我可以在单独的情况下测试处理返回数据,但我也想测试实际数据。
真挚地,
android - 使用 LoaderManager 的多个加载器,没有得到正确的加载器
我有两个加载器,一个用于填充绑定返回的数据到 2 TextViews
,另一个用于填充ListView
. 如何确保为每种情况加载正确的装载机?我在WR_VIEW
似乎没有创建或加载第一个加载程序(案例)的位置出现错误,因此onLoadFinished()
它返回“未找到此类列错误”,因为它正在访问不调用该列的第二个加载程序。
在我的onCreate
方法中,我为列表视图设置了适配器:
创建我的 2 个不同CursorLoader
的 s:
将数据绑定到我的TextViews
此处和:swapCursor
ListView
重置加载器:
android - AsyncTaskLoader 第三个任务消失
我正在尝试实现一个列表/详细信息工作流程,其中点击列表项会导致详细信息部分加载与新选择的行相关的数据。我正在尝试使用 anAsyncTaskLoader
来完成此操作。我遇到了一个问题,如果我连续足够快地点击三个列表项,实际上只会发生两个负载,而第三个会丢失。
我编写了一个示例活动来演示这种行为。当点击按钮三次时,该loadInBackground()
方法只会被调用两次。我在某个地方错过了一个电话吗?
android - AsyncTaskLoader with Dialogs,可行吗?
我开始了一个新应用程序,我想使用最新的 android 模式和指南,其中之一是使用 Loaders (AsyncTaskLoader) 而不是 AsyncTasks,我正在尝试查看 Loaders 是否应该真正取代你所有的 AsyncTasks “任务“ IE
假设您要基于 REST 调用构建应用程序,其中一个调用负责登录用户。因此,当您单击提交(在片段按钮上)时,会出现一个对话框,直到响应返回,如果我是正确的,除非您使用处理程序,否则 AsyncTaskLoader onLoadFinished 不会让您关闭对话框,并且很好地使用它,使解决方案看起来有点老套,因为你需要显示错误对话框,比如用户名或密码错误时,你可能会收到一堆对处理程序的调用。
我使用 AsyncTask 快速完成了此操作,一切正常,现在我将所有代码移至 AsyncTaskLoader答案。
我很感激你花时间。
android - 在 onLoadFinished 方法中启动 Activity
我有DialogFragment
一个Loader
.
对话框提示用户从应用程序中注销。
当用户选择注销时,我会触发Loader
它清除首选项和数据库,然后我完成 current Activity
。
完成Loader
后我想Activity
用登录屏幕开始一个新的,但我遇到了两个问题:
getActivity()
方法返回null
- 我无法运行新
Activity
的,因为我没有了Activity
context
您对此有任何解决方案吗?
android - AsyncTaskLoader onLoadFinished 有一个挂起的任务和配置更改
我正在尝试使用AsyncTaskLoader
在后台加载数据来填充详细视图以响应选择的列表项。我已经让它大部分工作了,但我仍然有一个问题。如果我在列表中选择第二个项目,然后在第一个选定项目的加载完成之前旋转设备,那么onLoadFinished()
调用将报告正在停止的活动而不是新活动。当只选择一个项目然后旋转时,这很好用。
这是我正在使用的代码。活动:
列表片段:
结果片段:
我已经能够使用普通AsyncTask
的 s 来完成这项工作,但我正在尝试了解更多关于Loader
s 的信息,因为它们会自动处理配置更改。
编辑:我想我可能已经通过查看LoaderManager的来源找到了问题。当initLoader
在配置更改后调用时,LoaderInfo
对象的mCallbacks
字段更新为新活动作为 的实现LoaderCallbacks
,正如我所期望的那样。
但是,当有一个挂起的加载器时,主LoaderInfo
对象也有mPendingLoader
一个引用 a 的字段LoaderCallbacks
,并且这个对象永远不会随着mCallbacks
字段中的新活动而更新。我希望看到代码看起来像这样:
似乎正因为如此,挂起的加载程序调用onLoadFinished
了旧的活动实例。如果我在此方法中设置断点并使用调试器进行我觉得缺少的调用,那么一切都会按我的预期工作。
新问题是:我是否发现了错误,或者这是预期的行为?
android - 自定义 CursorLoader 和支持 ListView 的 CursorAdapter 之间的数据不同步
背景:
我有一个CursorLoader
直接使用 SQLite 数据库而不是使用ContentProvider
. 此加载程序与ListFragment
由CursorAdapter
. 到现在为止还挺好。
为简化起见,我们假设 UI 上有一个删除按钮。当用户单击它时,我从数据库中删除一行,并调用onContentChanged()
我的加载器。此外,在onLoadFinished()
回调时,我调用notifyDatasetChanged()
我的适配器以刷新 UI。
问题:
当删除命令快速连续发生时,意味着快速连续onContentChanged()
调用,bindView()
最终将使用 stale data。这意味着一行已被删除,但 ListView 仍在尝试显示该行。这会导致光标异常。
我究竟做错了什么?
代码:
这是一个自定义 CursorLoader(基于Diane Hackborn 女士的建议)
我班级的一个片段ListFragment
,显示了LoaderManager
回调;以及refresh()
每当用户添加/删除记录时我调用的方法。
MyCursorAdapter
只是一个普通的,newView()
被覆盖以返回新膨胀的行布局 XML 并bindView()
使用Cursor
将列绑定到View
行布局中的 s。
编辑 1
在深入研究了这一点之后,我认为这里的根本问题是CursorAdapter
处理底层Cursor
. 我试图了解它是如何工作的。
采取以下场景以更好地理解。
- 假设
CursorLoader
已经完成加载并且它返回Cursor
现在有 5 行的 a。 - 开始显示这些
Adapter
行。它移动Cursor
到下一个位置并调用getView()
- 此时,即使在呈现列表视图的过程中,也会从数据库中删除一行(例如,_id = 2)。
- 这就是问题所在-
CursorAdapter
已将 移动Cursor
到与已删除行相对应的位置。该bindView()
方法仍然尝试使用 this 访问该行的列Cursor
,这是无效的并且我们得到异常。
问题:
- 这种理解正确吗?我对上面的第 4 点特别感兴趣,我假设当一行被删除时,
Cursor
除非我要求,否则它不会被刷新。 - 假设这是正确的,我如何要求我
CursorAdapter
丢弃/中止它ListView
正在进行的渲染,并要求它使用新的Cursor
(通过Loader#onContentChanged()
and返回Adapter#notifyDatasetChanged()
)来代替?
PS向版主提出的问题:是否应该将此编辑移至单独的问题?
编辑 2
根据各种答案的建议,我对 s 如何工作的理解似乎存在根本性错误Loader
。事实证明:
Fragment
or根本Adapter
不应该直接操作。Loader
- 应该监视数据的
Loader
所有变化,并且只要数据变化就应该提供Adapter
新Cursor
的onLoadFinished()
。
有了这种理解,我尝试了以下更改。- 没有任何操作Loader
。refresh 方法现在什么都不做。
Loader
另外,为了调试和内部发生的事情ContentObserver
,我想出了这个:
这是我的片段Fragment
和LoaderCallback
现在,每当数据库发生变化(添加/删除行)时,应该调用的onChange()
方法 - 对吗?ContentObserver
我没有看到这种情况发生。我的ListView
从未表现出任何变化。我看到任何变化的唯一一次是如果我明确地调用onContentChanged()
.Loader
这里出了什么问题?
编辑 3
好的,所以我重写了我Loader
的直接从AsyncTaskLoader
. 我仍然没有看到我的数据库更改被刷新,也没有看到我在数据库中插入/删除一行时被调用的onContentChanged()
方法:-(Loader
只是为了澄清一些事情:
我使用了代码
CursorLoader
并只修改了一行返回Cursor
.ContentProvider
在这里,我用我的代码替换了对的调用DbManager
(它反过来用于DatabaseHelper
执行查询并返回Cursor
)。Cursor cursor = AppGlobals.INSTANCE.getDbManager().getAllCameras();
我对数据库的插入/更新/删除是从其他地方发生的,而不是通过
Loader
. 在大多数情况下,数据库操作发生在后台Service
,在少数情况下,从Activity
. 我直接使用我的DbManager
类来执行这些操作。
我仍然没有得到的是 -谁告诉我Loader
一行已被添加/删除/修改?换句话说,在哪里被ForceLoadContentObserver#onChange()
调用?在我的加载器中,我在以下位置注册了我的观察者Cursor
:
这意味着当它发生变化时有责任Cursor
通知它。mObserver
但是,然后 AFAIK,“光标”不是“实时”对象,它会在数据库中修改数据时更新它指向的数据。
这是我的 Loader 的最新版本:
android - 为什么我的装载机被破坏了?
我有一个使用加载器的片段。Fragment 实现了 LoaderManager.LoaderCallbacks。在onCreate()
片段中,我做了一个setRetainInstance(true)
,以便片段不会在配置更改(如方向更改)时被破坏。这按预期工作,并且onDestroy()
不调用片段的 。但是,当我旋转设备时,我的加载器被破坏了。每次我旋转设备时,都会创建一个新的加载器。我检查了内存转储并验证了这一点。
- 为什么会这样
- 我怎样才能避免这种情况?
编辑:为避免混淆:局部变量加载器在这里不相关。这只是检查我之前创建的加载程序是否存在。即使使用下面的更新代码(删除了局部变量),加载程序也会被破坏。
以下是一些相关代码:
android - ContentProvider、Loader 和 ProgressBar
我有一个ContentProvider
从 sqlite 数据库中获取数据并通过Loader
. 它由Service
运行 anAsyncTask
从服务器下载数据并在ContentProvider
. 我希望这很清楚,但可以肯定的是:
ListFragment
ContentProvider
从via获取数据Loader
,ContentProvider
更新为Service
.
现在,当我第一次启动应用程序时我的本地 sqlite 数据库为空时,它显示它没有事件,即使它们当前正在通过Service
. 我宁愿ProgressBar
在这一刻展示(无限旋转的轮子,而不是酒吧)。但是,如果我ProgressBar
在没有来自数据库的结果时显示,即使在这种特定情况下从服务器获取数据之后,当外部数据库中没有记录时它也会存在(在我的情况下它经常发生)。所以:
当我第一次下载数据时,
Service
我想显示一个 ProgressBar,直到ContentProvider
给出非空结果或完成它的Service
工作。当
ContentProvider
什么都不返回并Service
完成它的工作(并获取空结果)时,我希望应用程序显示“未找到结果”。
我的问题可能是:如何通知ListFragment
它Service
仍在运行或它完成了 ts 工作。我的意思是 - 我不应该Fragment
在Service
. 这违背了 的想法ContentProviders
,不是吗?又怎样?
注意:我真的不知道哪个代码片段在这里会有所帮助,所以如果您觉得需要查看一些特定的片段,请在评论中告诉我。谢谢!
android - 菊花链式 Android 加载器是不是一个坏主意?
我需要从 2 个在线来源获取数据,并希望在我这样做时显示每个来源的进度。收集数据后,我可以填充列表视图。
我当前的实现是 MyActivity 实现了 LoaderCallbacks,后者又创建了 MyDataLoader 的一个实例(一个扩展 AsyncTaskLoader 的类)。在 MyDataLoader 的 loadInBackground 方法中,它从所有来源获取数据并填充 Sqlite 数据库。然后可以在整个过程中使用此数据库。
问题是我没有给用户任何关于我们在这个过程中的位置的反馈。
所以我想以某种方式使用 getLoaderManager().initLoader 以菊花链方式连接加载器来创建我的加载器,然后一次遍历加载器管理器中的加载器。当每个加载器完成并返回到 onLoadFinished 时,我有机会设置 progressDialog 的文本以指示进度。
这是一个坏主意吗?有没有更简单更好的方法?