如何刷新一个Android列表视图后添加/删除动态数据?


当前回答

我不能得到notifyDataSetChanged()来更新我的SimpleAdapter,所以我试着先删除所有的视图,使用removeAllViews()附加到父布局,然后添加ListView,这是有效的,允许我更新UI:

LinearLayout results = (LinearLayout)findViewById(R.id.results);
ListView lv = new ListView(this);
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row, 
                new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } );

for (...) { 
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", name);
    map.put("dept", dept);
    list.add(map);
}

lv.setAdapter(adapter);
results.removeAllViews();     
results.addView(lv);

其他回答

如果我在这里谈论我的场景,上面的答案都不会起作用,因为我有一个显示db值列表的活动,同时还有一个删除按钮,当按下删除按钮时,我想从列表中删除该项。

最酷的是,我没有使用回收器视图,而是使用了一个简单的列表视图,该列表视图在适配器类中初始化。因此,调用notifyDataSetChanged()不会在适配器类内部执行任何操作,甚至不会在初始化了适配器对象的活动类中执行任何操作,因为delete方法位于适配器类中。

因此,解决方案是在适配器类getView方法中从适配器中删除对象(仅删除特定对象,但如果您想删除所有对象,则调用clear())。

为了让你们了解我的代码是什么样的,

public class WordAdapter extends ArrayAdapter<Word> {
  Context context;

  public WordAdapter(Activity context, ArrayList<Word> words) {}
    //.......

    @NonNull
    @Override
    public View getView(final int position, View convertView, ViewGroup group) {
      //.......
     ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
     deleteBt.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (vocabDb.deleteWord(currentWord.id)) {
                //.....
             } else{
                //.....
             }
             remove(getItem(position)); // <---- here is the trick ---<
             //clear() // if you want to clear everything
         }
    });
 //....

注意:这里remove()和getItem()方法继承自Adapter类。

Remove() -删除所单击的特定项 getItem(position) -用于获取项目(在这里,这是我的Word对象 我已经添加到列表)从点击的位置。

这就是我如何在活动类中将适配器设置为listview,

    ArrayList<Word> wordList = new ArrayList();
    WordAdapter adapter = new WordAdapter(this, wordList);

    ListView list_view = (ListView) findViewById(R.id.activity_view_words);
    list_view.setAdapter(adapter);

我认为这取决于你对刷新的定义。您的意思是应该刷新GUI显示,还是应该刷新子视图,以便您可以通过编程调用getChildAt(int)并获得与适配器中内容对应的视图?

如果希望刷新GUI显示,则调用适配器上的notifyDataSetChanged()。下次重绘时,GUI将被刷新。

如果您希望能够调用getChildAt(int)并获得反映适配器中的内容的视图,则调用layoutChildren()。这将导致从适配器数据重构子视图。

如果你想从一个服务中更新UI listview,那么在你的Main活动中使适配器静态,并这样做:

@Override
public void onDestroy() {
    if (MainActivity.isInFront == true) {
        if (MainActivity.adapter != null) {
            MainActivity.adapter.notifyDataSetChanged();
        }

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    

在其他选项是onWindowFocusChanged方法,但肯定它敏感,需要一些额外的编码谁感兴趣

 override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)

       // some controls needed
        programList = usersDBHelper.readProgram(model.title!!)
        notesAdapter = DailyAdapter(this, programList)
        notesAdapter.notifyDataSetChanged()
        listview_act_daily.adapter = notesAdapter
    }

如果你按照android指南,使用ContentProviders从数据库中获取数据,并使用CursorLoader和CursorAdapters在ListView中显示它,那么你对相关数据的所有更改将自动反映在ListView中。

你的getContext () .getContentResolver()。notifyChange (uri, null);在ContentProvider中的游标上进行调整就足以反映这些变化。不需要额外的工作。

但是当你不使用这些时,你需要告诉适配器数据集什么时候发生变化。此外,您还需要重新填充/重新加载数据集(例如列表),然后您需要在适配器上调用notifyDataSetChanged()。

如果数据集中没有变化,notifyDataSetChanged()将不起作用。 下面是在docs-方法上面的注释

/**
 * Notifies the attached observers that the underlying data has been changed
 * and any View reflecting the data set should refresh itself.
 */