【问题标题】:Array Adapter notifyDataSetChanged() will not work数组适配器 notifyDataSetChanged() 将不起作用
【发布时间】:2012-01-10 17:36:40
【问题描述】:

我在这个问题上浪费了太多时间,所以不得不再问一次。我完全不知道为什么会这样。

我有一个数组适配器 (aAdapter) 和一个数组列表 (aList),我正在尝试放置一个清除按钮来擦除数据库中的条目并清除列表。

我的问题是 NotifyDataSetChanged() 在我的 onlick 方法中不起作用:

public void clearDB(View view) {
    aList.clear();
    aAdapter.notifyDataSetChanged();
    HighScoresDB hsdb = new HighScoresDB(HighScoresActivity.this);
    hsdb.openDB();
    hsdb.clearDB();
    hsdb.closeDB();

}

不过,它适用于其他任何地方。我什至尝试将 clear 和 notifyDataSetChanged() 放在另一个方法中并调用它,但这也不起作用,但是当我从 onCreate 调用它时确实起作用了......

有什么想法吗?

附言正在清除数据库。

【问题讨论】:

  • 你试过notifyDataSetInvalidated()而不是notifyDataSetChanged()吗?
  • 如果您有数据库,我强烈建议您使用 CursorAdapter。太神奇了!您不必执行 notifyDataSetChanged() 它只会知道您已经对数据库进行了更改并自行更新。

标签: android android-listview android-arrayadapter


【解决方案1】:

首先,我发现 Android 适配器实现非常有缺陷。当谈到执行任何定制的事情时,似乎对如何使用它的描述模棱两可,官方文档也没有澄清任何一个。我很高兴被证明是错误的。

我在视图中编辑数据时得到一致结果的方式如下:

  • 对所呈现的底层数据结构的所有更改都应在AsyncTask 中完成,因为您正在更改 UI 线程上的内容并且不希望出现并发问题。

  • 对底层数据结构的操作应该通过调用适配器方法来执行,所以如果你有一个ListAdapter,那么你可以使用列表适配器的addremoveclear。这意味着适配器管理视图通知等。这通常导致必须创建自定义适配器,因为可用的方法是有限的(在 7 之前的 sdk 版本中甚至没有 add all)。您的适配器最终也会充当一个大的fat controller,尽管我知道我们不应该将 android 视为一种 MVC 模式,但它似乎仍然是错误的。

  • 我创建了一些应用程序,在这些应用程序中我绕过适配器调用来操作底层数据结构,并且它一直有效,除非您严格管理视图通知,否则结果最终无法预测。现在我只是通过适配器调用。

因此,尽管我无法解释为什么 notifiyDataSetChanged 不适用于您的 onClick 方法。希望我能提供有用的信息,帮助您让您的应用按预期运行。

【讨论】:

  • 感谢您提供的所有信息,我一定会实施您的一些想法。可悲的是,这是一个大学作业,因为我明天要去度假,所以我的时间不多了,所以我想我现在会尝试一下盲人建议。但是,我将在我交出此文件后将其发布到市场上,因此在此之前会尝试您的一些想法。 :)
  • 我同意,whatsthebeef!!我什至不再使用特定的“文档化功能”,因为我无法保证它们始终有效(即使提供了文档)。事实上,我之前也遇到过 porcupine 的问题,我什至不再使用 notifydatachanged() 了。 :( 我只是制作自己的事件处理程序。真的很伤心。此评论专门针对 Android 适配器,而不是整个 SDK
【解决方案2】:

虽然不漂亮,但您可以重新初始化适配器而不是通知它,但我已经看到有时它是使其工作的唯一方法。

【讨论】:

  • 这也是我能让它自行清洁的唯一方法。
  • 我发现重新初始化适配器是唯一有效的解决方案!谢谢
  • 是的,今天也发生在我身上。根据其他活动的结果,我有 3 种方法,其中一种方法通知适配器不会做任何事情。
【解决方案3】:

所以我处理与此类似的问题的一种方法是基本上像blindstuff所说的那样重新初始化适配器。

    public class Example extends Activity{
        CustomAdapter adapter;
        ArrayList<ArrayList<String>> info = new ArrayList<ArrayList<String>>();
        final ListView list = (ListView) findViewById(R.id.listView_custom);
        adapter = new CustomAdapter(this, diceInfo.get(id));
        list.setAdapter(adapter);

然后在 onclick 监听器中

add.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                info.get(id).add("1,0,0,true");
                adapter = new CustomAdapter(Example.this, info.get(id));
                list.setAdapter(adapter);
            }
        });

这个例子没有初始化所有的东西,但它切中要害。我只是制作了一个新适配器并将其设置为我拥有的列表视图。效果很好。

【讨论】:

    【解决方案4】:

    在对话框中使用时也遇到了适配器的奇怪行为。 一旦适配器更新(或底层结构 - 两种方式),notifiyDataSetChanged 对话框就会消失,而不会出现 LogCat 中的错误或其他跟踪或 Eclipse 的调试。 完全相同的代码,一旦适配器应用于正常活动(ListView)就可以正常工作。

    【讨论】:

      【解决方案5】:

      我猜这个帖子不再活跃了,但供将来参考:

      根据developer.android.com

      [onNotifyDataSetChanged()] 通知附加的观察者底层数据已更改,任何反映数据集的视图都应自行刷新。

      不用让 Adapter 告诉 View 刷新自己,只需使用 adapter.clear() 和 adapter.add() 更新数据,然后通过再次调用 listView.setAdapter(adapter) 强制 ListView 更新。

      【讨论】:

        猜你喜欢
        • 2011-04-26
        • 2015-02-27
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多