如何在android中回调后刷新listView(带适配器)

时间:2013-06-30 11:51:02

标签: android adapter android-arrayadapter

我有一个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();
            }
        }
        });
    }

2 个答案:

答案 0 :(得分:1)

通常使用notifyDataSetChanged()会有效。由于您的值只是一个数组,因此您使用扩展BaseAdapter代替ArrayAdapter(提供add removeclear的特殊原因底层数组的函数)。我怀疑使用BaseAdapter并不会以您可能想要的方式通知。如果这不适合您,请尝试在设置新值后使用invalidate()上的View刷新子视图。

顺便说一句,如果您计划在此列表中包含许多行以提高速度,我强烈建议您使用“视图持有者模式”。

答案 1 :(得分:1)

试试这个:

  • mListView.setAdapter(适配器);在活动中的onCreate()上。
  • 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。 因此,您必须在调用之前初始化适配器并在回调之后添加值