我对`notifyDataSetChanged`缺少什么?

时间:2013-06-27 10:03:28

标签: java android adapter listadapter

我有一项活动在视图上绘制了一些图标。

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

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

这样外部代码可以调用UI线程并为适配器分配新列表,并通过notifyDataSetChange()

通知更改

然而,新图标不会被绘制,而是在离开并返回活动之后。

我该如何解决这个问题?

我试过了adapter.clear()

和doubled检查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();
    }

}

3 个答案:

答案 0 :(得分:2)

您应该扩展ArrayAdapter而不是BaseAdapter

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

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

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

我在这里找到了一个做得很好的教程:

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

希望它有所帮助!!最好的问候!!

答案 1 :(得分:1)

如果您在获取新通知时遇到太多问题并且在适配器中没有大量数据的情况下执行此操作,那么您可以随时创建新适配器并将其分配给列表list.setAdapter(adapter);强制列表从头开始重新呈现...

问候!

答案 2 :(得分:1)

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

this.values = values;

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

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

否则,每次调用setValues时都需要创建一个新的适配器,并通过指向新的适配器来更新listview。我会尝试链接到我找到它的文章。希望这有效。