How to refresh Android listview?

2018-12-31 03:03发布

How to refresh an Android ListView after adding/deleting dynamic data?

25条回答
余生请多指教
2楼-- · 2018-12-31 03:58

Please ignore all the invalidate(), invalidateViews(), requestLayout(), ... answers to this question.

The right thing to do (and luckily also marked as right answer) is to call notifyDataSetChanged() on your Adapter.

Troubleshooting

If calling notifyDataSetChanged() doesn't work all the layout methods won't help either. Believe me the ListView was properly updated. If you fail to find the difference you need to check where the data in your adapter comes from.

If this is just a collection you're keeping in memory check that you actually deleted from or added the item(s) to the collection before calling the notifyDataSetChanged().

If you're working with a database or service backend you'll have to call the method to retrieve the information again (or manipulate the in memory data) before calling the notifyDataSetChanged().

The thing is this notifyDataSetChanged only works if the dataset has changed. So that is the place to look if you don't find changes coming through. Debug if needed.

ArrayAdapter vs BaseAdapter

I did find that working with an adapter that lets you manage the collection, like a BaseAdapter works better. Some adapters like the ArrayAdapter already manage their own collection making it harder to get to the proper collection for updates. It's really just an needless extra layer of difficulty in most cases.

UI Thread

It is true that this has to be called from the UI thread. Other answers have examples on how to achieve this. However this is only required if you're working on this information from outside the UI thread. That is from a service or a non UI thread. In simple cases you'll be updating your data from a button click or another activity/fragment. So still within the UI thread. No need to always pop that runOnUiTrhead in.

Quick Example Project

Can be found at https://github.com/hanscappelle/so-2250770.git. Just clone and open the project in Android Studio (gradle). This project has a MainAcitivity building a ListView with all random data. This list can be refreshed using the action menu.

The adapter implementation I created for this example ModelObject exposes the data collection

public class MyListAdapter extends BaseAdapter {

    /**
     * this is our own collection of data, can be anything we 
     * want it to be as long as we get the abstract methods 
     * implemented using this data and work on this data 
     * (see getter) you should be fine
     */
    private List<ModelObject> mData;

    /**
     * our ctor for this adapter, we'll accept all the things 
     * we need here
     *
     * @param mData
     */
    public MyListAdapter(final Context context, final List<ModelObject> mData) {
        this.mData = mData;
        this.mContext = context;
    }

    public List<ModelObject> getData() {
        return mData;
    }

    // implement all abstract methods here
}

Code from the MainActivity

public class MainActivity extends Activity {

    private MyListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list = (ListView) findViewById(R.id.list);

        // create some dummy data here
        List<ModelObject> objects = getRandomData();
        // and put it into an adapter for the list
        mAdapter = new MyListAdapter(this, objects);
        list.setAdapter(mAdapter);

        // mAdapter is available in the helper methods below and the 
        // data will be updated based on action menu interactions

        // you could also keep the reference to the android ListView 
        // object instead and use the {@link ListView#getAdapter()} 
        // method instead. However you would have to cast that adapter 
        // to your own instance every time
    }

    /**
     * helper to show what happens when all data is new
     */
    private void reloadAllData(){
        // get new modified random data
        List<ModelObject> objects = getRandomData();
        // update data in our adapter
        mAdapter.getData().clear();
        mAdapter.getData().addAll(objects);
        // fire the event
        mAdapter.notifyDataSetChanged();
    }

    /**
     * helper to show how only changing properties of data 
     * elements also works
     */
    private void scrambleChecked(){
        Random random = new Random();
        // update data in our adapter, iterate all objects and 
        // resetting the checked option
        for( ModelObject mo : mAdapter.getData()) {
            mo.setChecked(random.nextBoolean());
        }
        // fire the event
        mAdapter.notifyDataSetChanged();
    }
}

More Information

Another nice post about the power of listViews is found here: http://www.vogella.com/articles/AndroidListView/article.html

查看更多
登录 后发表回答