【问题标题】:what am I missing with `notifyDataSetChanged`?`notifyDataSetChanged` 我缺少什么?
【发布时间】:2013-06-27 10:03:27
【问题描述】:

我有一个在视图上绘制一些图标的活动。

它在onCreate()中设置了一个列表和listAdapter。

我已将分配列表给我的适配器的代码提取到公共方法中。

这样外部代码就可以调用 UI 线程并将新列表分配给适配器,并使其通过notifyDataSetChange() 通知更改

但是新图标并没有被绘制,而是在离开并返回到 Activity 之后。

我该如何解决这个问题?

我已经尝试过 adapter.clear()

并仔细检查了 UI 线程运行此代码。

还有什么?

public class CategoriesActivity extends ActivityBase {
    private Category[] categories;

    SettingValueAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings_values);
        ((TitleBar)findViewById(R.id.theTitleBar)).init(this,DisplayStrings.DS_CATEGORIES);

        adapter = new SettingValueAdapter(this);

        DriveToNativeManager nativeManager = DriveToNativeManager.getInstance();
        nativeManager.getCategories(new CategoriesListener() {

            @Override
            public void onComplete(Category[] aCategories) {
                categories = aCategories;
                refreshListIcons();
            }
        });
        final ListView list = (ListView)findViewById(R.id.settingsValueList);
        list.setAdapter(adapter);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            ..
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        ..
    }

    public void refreshListIcons()  {
        NativeManager nativeManager = AppService.getNativeManager();
        SettingsValue[] values = new SettingsValue[categories.length];
        for (int i = 0; i < categories.length; i++) {
            values[i] = new SettingsValue(categories[i].value, nativeManager.getLanguageString(categories[i].displayString), false);
            values[i].icon = ResManager.GetSkinDrawable(categories[i].iconName + ".bin");
        }
        adapter.setValues(values);
    }   
}




public class SettingValueAdapter extends BaseAdapter {

    private SettingsValue[] values;
    private LayoutInflater inflater;
    public SettingValueAdapter(Context context) {
        inflater = LayoutInflater.from(context);
    }

...

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.settings_item, null);
        }
        SettingsValue item = values[position];
        CheckedTextView name = (CheckedTextView) convertView.findViewById(R.id.itemText);
        ImageView iconView = (ImageView) convertView.findViewById(R.id.itemIcon);
        if (iconView != null && (item != null) && (item.icon != null)) {
            iconView.setImageDrawable(item.icon);
            iconView.setVisibility(View.VISIBLE);
        } else {
            iconView.setVisibility(View.GONE);
        }
        name.setText(item.display);
        name.setChecked(item.isSelected);
        View container = convertView.findViewById(R.id.itemContainer);
        if (position == 0) {
            ..
        return convertView;
    }
    public void setValues(SettingsValue[] values) {
        this.values = values;
        notifyDataSetChanged();
    }

}

【问题讨论】:

  • 即使你说你确定它在 UI 线程中,请尝试将 refreshListIcons() 调用放在 CategoriesActivity.this.runOnUiThread()
  • 没有帮助。我努力了。它甚至会导致崩溃吗?
  • 不应该。编辑您的问题并发布您是如何尝试的以及您在 logcat 中遇到了什么错误。
  • 我的应用程序崩溃了。也许在本机线程中,如何在 java 中有效地跟踪崩溃?在 c 中?
  • 您的问题只是显示新图标,还是调用 notifyDataSetChanged 时根本看不到任何变化?

标签: java android adapter listadapter


【解决方案1】:

您应该扩展ArrayAdapter 而不是BaseAdapter

http://developer.android.com/reference/android/widget/ArrayAdapter.html

这个类适用于数组和集合,它可以正确处理所有关于内部状态的问题。

在这种情况下,在调用 notifyDataSetChanged 之前,在适配器对象本身使用 clear 后跟 addAll。另一种方法是更改​​绑定到Adapter 的数组或集合。

我在这里找到了一个非常好的教程:

http://www.vogella.com/articles/AndroidListView/article.html

希望对你有帮助!!最好的问候!!

【讨论】:

    【解决方案2】:

    这样做很糟糕,如果您在获取新通知时遇到太多问题,并且如果适配器中没有大量数据,您始终可以创建一个新适配器并将其分配给列表list.setAdapter(adapter); 强制列表从头开始重新渲染...

    问候!

    【讨论】:

      【解决方案3】:

      我认为您无法在运行时更新为适配器供电的列表的内存位置。这是不允许的:

      this.values = values;
      

      如果您知道项目的数量不会改变,请使用这段代码:

      public void setValues(SettingsValue[] values) {
          for (int i = 0; i < values.length; i++) {
              this.values[i] = values[i];
          }
          notifyDataSetChanged();
      }
      

      否则,每次调用 setValues 并通过指向新适配器来更新列表视图时,您都需要创建一个新适配器。当我找到它时,我会尝试链接到我读过这篇文章的地方。希望这行得通。

      【讨论】:

        猜你喜欢
        • 2012-10-01
        • 2010-10-29
        • 2011-03-24
        • 1970-01-01
        • 2011-01-29
        • 2014-04-29
        • 2011-07-12
        • 1970-01-01
        相关资源
        最近更新 更多