我有一个Activity
ListView
附加了custom adapter
。
我有一个回调,表示已完成下载的可绘制项目。
它被多次调用(每个资源都被下载)。
在我的回调中,我切换到ui-thread,并将一个新数组设置为同一个适配器。
然后我致电adapter.notifyDataSetChanged()
但活动列表未刷新到新图标。
我还需要做什么?
1)致电mListView.requestLayout()
?但我怎么知道什么时候?
因为notifyDataSetChanged
是异步的,我不知道它什么时候完成。
2)覆盖adapter's destroyView
?所以我不会创建一个新的listItem,但使用现有的吗?
我的适配器代码:
公共类SettingValueAdapter扩展了BaseAdapter {
private SettingsValue[] values;
private LayoutInflater inflater;
public SettingValueAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public SettingsValue[] getValues() {
return values;
}
@Override
public int getCount() {
if (values == null) {
return 0;
}
return values.length;
}
@Override
public Object getItem(int arg0) {
return values==null? null : values[arg0];
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
@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) {
if (position == values.length-1) {
container.setBackgroundResource(R.drawable.item_selector_single);
} else {
container.setBackgroundResource(R.drawable.item_selector_top);
}
} else {
if (position == values.length-1) {
container.setBackgroundResource(R.drawable.item_selector_bottom);
} else {
container.setBackgroundResource(R.drawable.item_selector_middle);
}
}
container.setPadding(0, 0, 0, 0);
return convertView;
}
public void setValues(SettingsValue[] values) {
this.values = values;
notifyDataSetChanged();
}
}
MyActivity的代码:
public class CategoriesActivity extends ActivityBase {
private Category[] categories;
SettingValueAdapter adapter;
ListView mListView;
@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;
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);
}
});
mListView = (ListView) findViewById(R.id.settingsValueList);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
Intent intent = new Intent(CategoriesActivity.this,
SearchActivity.class);
intent.putExtra(PublicMacros.SEARCH_CATEGORY,
categories[position].value);
intent.putExtra(PublicMacros.SEARCH_MODE,
PublicMacros.FREE_SEARCH);
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK);
finish();
}
super.onActivityResult(requestCode, resultCode, data);
}
public void refreshListIcons() {
// if (categories != null) {
// 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");
// }
//
if (categories != null) {
SettingsValue[] values = adapter.getValues();
for (int i = 0; i < values.length; i++) {
values[i].icon = ResManager
.GetSkinDrawable(categories[i].iconName + ".bin");
}
adapter.setValues(values);
}
}
}
我从回调中拨打refreshIconsList
。
但是,正如我所说的那样 - 列表不会在运行时刷新,而是仅在存在并重新进入活动后才会刷新。
我试过这个,但没有帮助:
public void refreshListIcons() {
// if (categories != null) {
// 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");
// }
//
runOnUiThread(new Runnable() {
@Override
public void run() {
if (categories != null) {
SettingsValue[] values = adapter.getValues();
for (int i = 0; i < values.length; i++) {
values[i].icon = ResManager
.GetSkinDrawable(categories[i].iconName + ".bin");
}
adapter.setValues(values);
mListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
});
}
答案 0 :(得分:1)
通常使用notifyDataSetChanged()
会有效。由于您的值只是一个数组,因此您使用扩展BaseAdapter
代替ArrayAdapter
(提供add
remove
和clear
的特殊原因底层数组的函数)。我怀疑使用BaseAdapter
并不会以您可能想要的方式通知。如果这不适合您,请尝试在设置新值后使用invalidate()
上的View
刷新子视图。
顺便说一句,如果您计划在此列表中包含许多行以提高速度,我强烈建议您使用“视图持有者模式”。
答案 1 :(得分:1)
试试这个:
public void refreshListIcons(){
runOnUiThread(new Runnable() {
@Override
public void run() {
if (categories != null) {
SettingsValue[] values = adapter.getValues();
for (int i = 0; i < values.length; i++) {
values[i].icon = ResManager
.GetSkinDrawable(categories[i].iconName + ".bin");
}
adapter.addAll(values); // *** ADD THIS LINE***
}
}
});
}
问题是在回调后设置Adapter。 因此,您必须在调用之前初始化适配器并在回调之后添加值