Подтвердить что ты не робот

Android: как обновить содержимое ListView?

My ListView использует расширение BaseAdapter, я не могу правильно его обновить. Когда я обновляюсь, кажется, что старые данные берут верх над новыми данными, пока не произойдет событие прокрутки. Старые строки рисуются поверх новых строк, но старые строки исчезают, когда я начинаю прокрутку.

Я попытался позвонить invalidateViews(), notifyDataSetChanged() и notifyDataSetInvalidated(). Мой код выглядит примерно так:

private void updateData()
{
   List<DataItems> newList = getNewList();

   MyAdapter adapter = new MyAdapter(getContext());
   //my adapter holds an internal list of DataItems
   adapter.setList(newList);
   mList.setAdapter(adapter);
   adapter.notifyDataSetChanged();
   mList.invalidateViews();
}
4b9b3361

Ответ 1

Тем, у кого еще есть проблемы, я решил это так:

List<Item> newItems = databaseHandler.getItems();
ListArrayAdapter.clear();
ListArrayAdapter.addAll(newItems);
ListArrayAdapter.notifyDataSetChanged();
databaseHandler.close();

Сначала я очистил данные от адаптера, а затем добавил новую коллекцию элементов и только затем установил notifyDataSetChanged(); Сначала это было непонятно для меня, поэтому я хотел указать на это. Обратите внимание, что без вызова notifyDataSetChanged() представление не будет обновляться.

Ответ 2

В моем понимании, если вы хотите обновить ListView сразу же после изменения данных, вы должны вызвать notifyDataSetChanged() в RunOnUiThread().

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}

Ответ 3

Вам не нужно создавать новый адаптер для обновления содержимого ListView. Просто сохраните свой адаптер в поле и обновите свой список следующим кодом:

mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();

Чтобы прояснить это, ваша активность должна выглядеть так:

private YourAdapter mAdapter;

protected void onCreate(...) {

    ...

    mAdapter = new YourAdapter(this);
    setListAdapter(mAdapter);

    updateData();
}

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);
    mAdapter.notifyDataSetChanged();
}

Ответ 4

Я тоже пробовал invalidate(), invalidateViews(), notifyDataSetChanged(). Все они могут работать в определенных контекстах, но в моем случае это не помогло.

В моем случае мне пришлось добавить несколько новых строк в список, и он просто не работает. Создание нового адаптера решило проблему.

Во время отладки я понял, что данные были там, но просто не отображаются. Если invalidate() или invalidateViews() не отображает (что и предполагается), я не знаю, что бы это сделал.

Создание нового объекта Adapter для обновления измененных данных не кажется плохой идеей. Это определенно работает. Единственным недостатком может быть время, затрачиваемое на выделение новой памяти для вашего адаптера, но это должно быть хорошо, если система Android достаточно умен и позаботится об этом, чтобы она была эффективной.

Если вы выберете это из уравнения, поток почти такой же, как для вызова notifyDataSetChanged. В этом смысле один и тот же набор адаптивных функций вызывается в любом случае.

Таким образом, мы не теряем много, но получаем много.

Ответ 5

Я думаю, что заправка одного и того же адаптера различными данными будет более или самой лучшей техникой. Поместите этот метод в класс Adapter с правильным аргументом (список данных, который вы хотите отображать в качестве имен в моем случае) Вызовите это, где u обновите данные списка с обновленным списком (имена в моем случае)

public void refill(ArrayList<BeanDatabase> names) {
    list.clear();
    list.addAll(names);
    list.notifyDataSetChanged();
}

Если вы изменяете адаптер или устанавливаете адаптер снова и снова, когда обновляется список, то принудительная ошибка закрытия наверняка вызовет проблемы в какой-то момент. (Ошибка: данные списка были обновлены, но адаптер не уведомляет о представлении списка)

Ответ 6

Я делаю то же самое, используя invalidateViews(), и это работает для меня. Если вы хотите, чтобы он немедленно недействителен, вы можете попробовать вызвать postInvalidate после вызова invalidateViews.

Ответ 7

Обновить содержимое списка ListView по нижнему коду:

private ListView listViewBuddy;
private BuddyAdapter mBuddyAdapter;
private ArrayList<BuddyModel> buddyList = new ArrayList<BuddyModel>();

OnCreate():

listViewBuddy = (ListView)findViewById(R.id.listViewBuddy);
mBuddyAdapter = new BuddyAdapter();
listViewBuddy.setAdapter(mBuddyAdapter);

onDataGet (после вызова веб-службы или из локальной базы данных или из-за нее):

mBuddyAdapter.setData(buddyList);
mBuddyAdapter.notifyDataSetChanged();

BaseAdapter

private class BuddyAdapter extends BaseAdapter { 

    private ArrayList<BuddyModel> mArrayList = new ArrayList<BuddyModel>();
    private LayoutInflater mLayoutInflater= (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    private ViewHolder holder;

    public void setData(ArrayList<BuddyModel> list){
        mArrayList = list;
    }

    @Override
    public int getCount() {
        return mArrayList.size();
    }

    @Override
    public BuddyModel getItem(int position) {
        return mArrayList.get(position);
    }

    @Override
    public long getItemId(int pos) {
        return pos;
    }

    private class ViewHolder {
        private TextView txtBuddyName, txtBuddyBadge;

    }
    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mLayoutInflater.inflate(R.layout.row_buddy, null);
            // bind views
            holder.txtBuddyName = (TextView) convertView.findViewById(R.id.txtBuddyName);
            holder.txtBuddyBadge = (TextView) convertView.findViewById(R.id.txtBuddyBadge);

            // set tag
            convertView.setTag(holder);
        } else {
            // get tag
            holder = (ViewHolder) convertView.getTag();
        }

        holder.txtBuddyName.setText(mArrayList.get(position).getFriendId());

        int badge = mArrayList.get(position).getCount();
        if(badge!=0){
            holder.txtBuddyBadge.setVisibility(View.VISIBLE);
            holder.txtBuddyBadge.setText(""+badge);
        }else{
            holder.txtBuddyBadge.setVisibility(View.GONE);
        }   

        return convertView;
    }
}

Когда вы хотите Обновить список просмотров, просто позвоните ниже кода двух строк:

 mBuddyAdapter.setData(Your_Updated_ArrayList);
 mBuddyAdapter.notifyDataSetChanged();

Готово

Ответ 8

Только это работает для меня каждый раз, обратите внимание, что я не знаю, вызывает ли это какие-либо другие осложнения или проблемы с производительностью:

private void updateListView(){
        listview.setAdapter(adapter);
    }

Ответ 9

Еще один простой способ:

//In your ListViewActivity:
public void refreshListView() {
    listAdapter = new ListAdapter(this);
    setListAdapter(listAdapter);
}