【问题标题】:How to sort the CursorLoader results?如何对 CursorLoader 结果进行排序?
【发布时间】:2014-01-08 07:12:04
【问题描述】:

我使用 CursorLoader 查询结果,这不是我想要在 ListFramgenet 中显示的顺序。如何排序?

我用这个来设置适配器:

    mAdapter = new SimpleCursorAdapter(getActivity(),
            android.R.layout.simple_list_item_2, null,
            new String[] { "name", "distance"},
            new int[] { android.R.id.text1, android.R.id.text2 }, 0);
    setListAdapter(mAdapter);

    // Start out with a progress indicator.
    setListShown(false);

    // Prepare the loader.  Either re-connect with an existing one,
    // or start a new one.
    getLoaderManager().initLoader(0, null,  this);

创建加载器:

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    return new CursorLoader(getActivity(), 
            Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
            MEMBERS_PROJECTION,
            null,
            null,
            null);        

}


public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    mAdapter.changeCursor(data);

    // The list should now be shown.
    if (isResumed()) {
        setListShown(true);
    } else {
        setListShownNoAnimation(true);
    }
}

嗯,查询结果有经纬度。我想计算我的位置和这些结果之间的距离。并按距离 asc 排序。

如何排序?任何答案都会被应用

【问题讨论】:

  • 你不能对已经返回的游标进行排序......你必须告诉 CursorLoader 在创建时为你排序 CursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
  • 看来sortOrder只是一个字符串,我要计算的最终顺序。
  • 您可以通过(x-x0)^2 + (y-y0)^2订购...您也可以退货(x-x0)^2 + (y-y0)^2 AS Distance²(当然,您必须修改ContentProvider)...然后在显示之前您可以在Binder.bindView中计算它() 或 getView() 或类似... someView.setText(Math.sqrt(c.getDouble(c.getColumnIndex("Distance²"))).toString())
  • 显然你需要阅读一些 SQLite 文档:sqlite.org/syntaxdiagrams.html#ordering-term

标签: android simplecursoradapter android-cursorloader


【解决方案1】:

其实很简单:

从此:

new CursorLoader(getActivity(), 
        Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
        MEMBERS_PROJECTION,
        null,
        null,
        null);

到这里:

// You could have them calculated in the projection like this:
String[] projection = { COLUMN1 + " * " + COLUMN2 + " as data", // Whatever your calculations are
COLUMN1, COLUMN2, COLUMN3, etc..  };
new CursorLoader(getActivity(), 
        Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
        projection, 
        null,
        null,
        "data ASC");

记住,如果您的提供程序中有某种方法可以检查 投影并引发异常,您必须在进行测试时将其注释掉,或添加 新列 (用于计算的列)你的官方投影数组。

【讨论】:

  • 虽然我使用了另一种方法来避免这个问题。我想你的答案会更好。谢谢。
  • 所以,答案是你不能
【解决方案2】:

您正在寻找的是提供类似于以下内容的 sortOrder 参数:

(本文开头的 ORDER BY 是隐含的,你没有包含它,为了清楚起见,这里只是简单地包含)

ORDER BY 6366000*acos(cos(lat_a / (180/3.14169))*cos(lng_a / (180/3.14169))*cos(lat_b / (180/3.14169))*cos(lng_b / (180/3.14169)) + t2 + t3) ASC

(为此,我使用了answer here 并内联了它 - 除了我没有打扰 t2 和 t3,因为它无论如何都不会工作)

不幸的是,这在标准 SQLite 中是不可能的 - 没有运算符 sincos - 甚至没有平方根或幂运算符(在看到您关于只需要更简单计算的评论之后)。

你可以add your own functions,但这条路线有点复杂。

根据您拥有的行数,您可以全部阅读然后自行排序。

【讨论】:

  • 你的排序是我想要的,我只是使用 sqrt(^2) 来简化问题。
  • 啊哈。好的,那么您可以考虑添加自己的函数,或者对结果执行计算并填充一个临时的“距离”表(使用主表的主键和与当前位置的距离),加入该表,然后订购按距离。不过,您仍然需要在代码中进行计算,并遍历所有结果 - 尽管您需要的只是 lat 和 long 值,这可能比创建表示每一行的整个对象便宜。
【解决方案3】:

提供您想要排序的列名称作为 CursorLoader() 构造函数的最后一个参数作为字符串。如果要排序的列不止一列,请用逗号分隔。如果要升序而不是降序,请在列名后添加 DESC。在常规 SQL 语法中,您将在“ORDER BY”之后添加的内容非常多。

编辑:在下面回答您的评论。

是和不是。我相信您可以将其用作排序顺序,但 SQLite 没有 sqrt 或 power 函数。但是,您可以定义自己的 SQLite 函数或使用第 3 方扩展。如果您不想走那条路,则必须使用自己的自定义适配器而不是 SimpleCursorAdapter,例如您将获得游标结果,然后在代码中将它们排序到另一个数据结构中,该结构将成为您的适配器的数据源。

【讨论】:

  • 我的表中有两列: x, y 。我想要的顺序是 sqrt( (x-x0)^2 + (y-y0)^2 )。可以直接用SQL排序吗?
  • 注意:你可以去掉 sqrt,因为它是一个不断增长的单调函数。
  • 谢谢,我想尝试实现我自己的适配器,这似乎比定义我自己的SQLite函数更容易。
【解决方案4】:

只需添加ContactsContract.Contacts.SORT_KEY_PRIMARY

【讨论】:

    猜你喜欢
    • 2021-06-29
    • 2021-08-25
    • 2014-09-14
    • 2015-01-12
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 2018-07-25
    • 2013-12-06
    相关资源
    最近更新 更多