带 LoaderManager 的 CursorLoader 如何知道将光标发送到 CursorAdapter?

Posted

技术标签:

【中文标题】带 LoaderManager 的 CursorLoader 如何知道将光标发送到 CursorAdapter?【英文标题】:How does CursorLoader with LoaderManager know to send the cursor to a CursorAdapter? 【发布时间】:2012-06-24 10:01:36 【问题描述】:

我正在浏览我的一些代码,我意识到我实际上并不知道CursorLoaderLoaderManager 组合如何与CursorAdapter 连接一起使用。这是我感到困惑的部分。

agendaAdapter = new MyAgendaAdapter(this, null);

makeProviderBundle(new String[] "_id", "event_name", "start_date", "start_time",
    "end_date", "end_time", "location", "date(?) >= start_date and date(?) <= end_date", 
new String[]getChosenDate(), getChosenDate(), null);

getLoaderManager().initLoader(0, myBundle, MainDisplayActivity.this);
list.setAdapter(agendaAdapter);

那么我的自定义ContentProvider 中的query() 方法如何知道将其发送到特定的CursorAdapter?我只是没有看到联系。我了解其中的所有其他内容,但这个问题是关于什么的。哦,我应该提一下,代码运行良好。

【问题讨论】:

我开始怀疑你问这些问题只是为了跟我开玩笑,因为我知道我忍不住回答(即使我在工作哈哈) idk 你在说什么 :) 但如果你在那里...... 【参考方案1】:

首先,查看this post 和this post 的代码示例,以更深入地了解该过程的工作原理。

现在,回答您的问题...

我的自定义ContentProvider...中的query()方法如何?

首先要记住getContentResolver().query() 不会直接调用内容提供者的query 方法。您正在调用内容解析器的查询方法,该方法解析Uri,确定您希望调用的提供程序,然后然后调用您的提供程序的query 方法.

查询如何发送到特定的CursorAdapter

我将以API Demos 为例向您介绍整个过程。请注意,API 演示使用 ListFragment 而不是 ListActivity(在此问题的上下文中差异并不重要)。


    首先,创建(并设置)CursorAdapter

    mAdapter = new SimpleCursorAdapter(
            getActivity(),
            android.R.layout.simple_list_item_2, 
            null,
            new String[]  Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS ,
            new int[]  android.R.id.text1, android.R.id.text2 , 
            0);
    

    执行此语句后,SimpleCursorAdapter 知道它应该如何将游标数据与您的视图相关联。光标的Contacts.DISPLAY_NAME 列中的任何数据都将与id 为android.R.id.text1 等的视图相关联。

    请注意,您已将 null 游标作为第三个参数传递给构造函数。这非常重要,因为我们还没有查询任何数据(这是LoaderManagerCursorLoader 的工作)。

    接下来,初始化加载器。

    getLoaderManager().initLoader(0, null, this);
    

    这告诉LoaderManager创建并启动对应于id 0Loader

    LoaderManager 调用onCreateLoader(int id, Bundle args)

    onCreateloader 返回Loader&lt;Cursor&gt; 接口的子类(即CursorLoader,在这种情况下)。这个CursorLoader 将执行初始查询,并在数据更改时自行更新。

    如果您的活动/片段有多个加载器,那么您将使用switch(id) 来确定已指示开始加载过程的特定加载器。

    查询到的游标传给onLoadFinished()

    CursorLoader 在步骤 3 中被实例化并返回后,CursorLoader 立即在单独的线程上执行初始查询并返回游标。当CursorLoader 完成查询时,它将新查询的游标返回给LoaderManager,然后将游标传递给onLoadFinished 方法。在文档中,“onLoadFinished 方法在先前创建的加载程序完成加载时被调用。”

    查询到的数据与CursorAdapter相关联

    mAdapter.swapCursor(data);
    

    请注意,onLoadFinished 通常也是您使用查询数据更新活动/片段的 UI 的地方。在这种情况下这不是必需的,因为我们之前称之为setListAdapter(mAdapter)ListFragment 知道如何使用 CursorAdapter(参见步骤 1)......我们需要做的就是将光标传递给适配器 swapCursorListFragment 将负责在我们的屏幕。

如果您有任何问题(或者是否有任何拼写错误等),请告诉我。


TL;DR

包含查询数据的游标与CursorAdapter 中的onLoadFinished 相关联。这通常通过调用mAdapter.swapCursor(data) 来完成。

【讨论】:

在装载机上的出色运行 不要感谢我...感谢 Android 市场上所有糟糕的、开发不佳的应用程序。这就是我觉得有责任过度详细解释这个过程的原因。 :) 嘿@AlexLockwood 快速提问。如果我将 CursorLoader 与 LoaderManager 一起使用,我无需担心关闭数据库或游标是否正确。但是当我像getContentResolver().query()一样直接使用它时呢?在这种情况下,我是否必须明确关闭它们,或者所有这些仍然由类本身处理? 然后,在这些方法中,CursorLoader 将相应地关闭其游标(即在onReset 等中)。换句话说,不是LoaderManager 关闭游标……而是LoaderManager 告诉CursorLoader 关闭游标。 @IgorGanapolsky 我记得和其他一些 Android 开发者讨论过这个问题here。我总是在onActivityCreated() 中初始化加载器。我同意你的观点,谷歌的文档对这一点有点含糊……但我在 onActivityCreated() 中初始化加载器时从未遇到任何问题。

以上是关于带 LoaderManager 的 CursorLoader 如何知道将光标发送到 CursorAdapter?的主要内容,如果未能解决你的问题,请参考以下文章

LoaderManager 的作用域是啥?

Android LoaderManager原理剖析

Android LoaderManager原理详解

LoaderManager与CursorLoader用法

LoaderManager 是做啥的?

安卓:CursorLoader、LoaderManager、SQLite