【问题标题】:Android : Expandable ListView Adapter from Database / ContentProvider / ContentResolverAndroid:来自 Database / ContentProvider / ContentResolver 的可扩展 ListView 适配器
【发布时间】:2026-02-03 00:45:02
【问题描述】:

我正在尝试构建一个可扩展的 ListView。

我有一个包含 3 个表的数据库,目前我需要从中提取内容(并更新一些内容)。此外,我使用自己的内容提供程序和活动的内容解析器与我的数据库进行交互。将来,我将添加一些 SOAP 调用以将我的语言环境数据库同步到远程数据库,关于 Virgil Dobjanschi 的 Rest 设计模式(或者至少,我会尝试......)。

我的第一个问题是:我应该为我的 ELV 使用哪个适配器?

我从 BaseExpandableListAdapter 开始,但我注意到我总是必须自己进行查询才能提取和更新数据。例如:

        EditText et;

        et = (EditText) convertView.findViewById(R.id.explist_qty);
        et.setOnClickListener(mController);

        Cursor cursor = _context.getContentResolver().query(
                MyContentProvider.getUri(QuantityTable.TABLE_QUANTITY), 
                new String[]{ QuantityTable.COLUMN_QUANTITY }, 
                QuantityTable.COLUMN_STOCK_ID +"=="+groupPosition, null, null);
        String qty = cursor.getString(cursor.getColumnIndexOrThrow((QuantityTable.COLUMN_QUANTITY)));

        et.setText(qty);

我认为这不是正确的选择,因为我需要一个光标来处理所有事情。这就是我寻找 CursorTreeAdapter 的原因,但我在某处红了它经常用来避免制作内容提供者/解析器模式。现在我肯定迷路了,我需要你的帮助。

有关信息,我的 ELV 将 TextView 显示为标题,并将一些 EditTexts / Buttons 显示为子项。我需要按钮来更新 EditText 和 2 个数据库(使用我的 Content Provider 进行区域设置,使用 SOAP 调用进行远程设置)。

我的第二个问题来了:我怎样才能让我的观点刷新自己关于 locale DB 的看法?

我已经听说过 Observer/Observable 设计模式,但我不确定它是否可以用数据库完成,我可能错了。

我正在学习 Android,所以对于像我这样的菜鸟来说,了解一切是如何进行的以及有哪些好的做法有点困难。

谢谢大家。

【问题讨论】:

    标签: android database adapter android-contentprovider expandablelistview


    【解决方案1】:

    我找到了一个完全符合我想要的解决方案。

    ELV 的适配器显然是一个 CursorTreeAdapter,它在使用数据库时是完美的。多亏了光标加载器,我才喂了适配器。我正在使用活动加载器管理器并初始化加载器。我的 Activity 实现了 LoaderManager.LoaderCallbacks,所以我有 3 个方法 onCreateLoader()、onLoadFinished() 和 onLoaderReset()。

    在 onCreateLoader() 中,由于我的 Content Resolver 链接到自定义 Content Provider,我进行了查询,并将其附加到侦听特定 URI 的自定义 CursorLoader(我返回)。如果表有任何更改,我的内容提供程序会通知此 URI,因此 CursorLoader 知道它必须重新加载自己。

    onLoadFinished() 简单地将当前光标设置为适配器,而 onLoaderReset() 简单地将 null 设置为适配器。

    这样,一切都在后台线程中运行,没有 UI 冻结,并且每次需要时都会自动刷新内容。

    里面有很多工作,很难用几行来解释。有几千行代码,所以我不能在那里复制/粘贴。如果它可以帮助某人,我只是回来提供我的解决方案。不要犹豫,请我解释一下,我会尽力回答。

    【讨论】:

    • 您能否通过您的解决方案帮助我,我遇到了 simplecursortreeadapter 的问题。我有自定义列表视图适配器,它扩展了简单的光标树适配器。所有数据都是从数据库中填充的,我在每个列表视图项上都有按钮,当我尝试使用按钮单击修改数据时,再次加载列表视图,有没有办法修改数据而不会导致重新创建所有列表.
    • 我不确定这在使用游标时是否可行。我也在刷新整个列表,但大多数时候这不是问题,因为我没有很多数据要显示。如果您有大量数据,也许您可​​以看到为您的列表视图添加“加载更多”系统。这样,您将只显示第一行,并在用户向下滚动列表时动态加载下一行。刷新它应该会更好,因为它只显示几行而不是所有行。看看*.com/questions/4330565/…
    • 您好,感谢您的回答,几天后,在stackoverlow上搜索,我想出了下面的解决方案}
    【解决方案2】:
    @Override
        protected Cursor getChildrenCursor(Cursor groupCursor) {
            final int productSubCategoryId = groupCursor.getInt(groupCursor.getColumnIndex(DbVar.ID));
            Cursor childCursor = null;
            try {
                final String sortOrder = DbVar.PRODUCT_NAME + " COLLATE LOCALIZED ASC";
                final CursorLoader cursorLoader = new CursorLoader(
                        shoppingListFragment.getActivity(),
                        PGContentProvider.CONTENT_URI_SHOPPING_LIST_TABLE,
                        ShoppingListTable.FIELD_LIST,
                        "(" + DbVar.PRODUCT_SUB_CATEGORY_ID + "=?)",
                        new String[]{ productSubCategoryId + ""}, sortOrder);
                cursorLoader.registerListener(0, this);
                childCursor = cursorLoader.loadInBackground();
                childCursor.moveToFirst();
    
            } catch (final Exception e) {
                e.printStackTrace();
            }
    
            return childCursor;
    

    【讨论】:

      最近更新 更多