【问题标题】:Adapter update not visible rows适配器更新不可见行
【发布时间】:2014-10-28 12:28:43
【问题描述】:

如果您查看此问题Update adapter from different method,您将看到此答案https://stackoverflow.com/a/25632407/1270400此答案仅适用于可见行。但我必须将徽章添加到不可见和可见行。@pomber 给了一个提示,但我不能明白了。

我该如何做这个过程?我需要一个例子。

【问题讨论】:

    标签: android android-adapter


    【解决方案1】:

    您不应该尝试直接修改列表视图的子元素。相反,请修改适配器,以便根据某些条件显示徽章。

    然后,修改适配器的底层数据(并在适配器上调用notifyDatasetChanged()),列表视图将重绘自身。

    例如,将您的适配器视为由 Song 对象列表支持。在getView() 中,如果((Song) get item(position)).isFavourited() 返回true,您可以显示徽章。

    要显示列表中第 n 首歌曲的标记,您需要修改列表 (songs.get(n).favourite()) 并调用 adapter.notifyDatasetChanged()


    使用更详细但并非详尽完整的示例进行编辑。注意 cmets 和 TODO:

    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ListAdapter;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Test  {
    
        public static void test() {
            List<Song> songsList = new ArrayList<Song>();
            songsList.add(new Song("Generic Song Title", false));
            songsList.add(new Song("Another Song Title", false));
            songsList.add(new Song("A Third Song Title", false));
            Songs songs = new Songs(songsList);
    
            ListAdapter songsAdapter = new SongsAdapter(songs);
            // TODO: ListView.setAdapter(songsAdapter)
    
            /*
            When you want to change the visibility on a badge of a given song,
            do NOT modify the view by trying to access it from the ListView
            using ListView.getChildAt(int).
    
            Update the data, and give it to your adapter, as follows:
             */
            List<Song> anotherSongsListWithFavourites = new ArrayList<Song>();
            songsList.add(new Song("Generic Song Title", false));
            songsList.add(new Song("Another Song Title", true));
            songsList.add(new Song("A Third Song Title", true));
            Songs modifiedSongs = new Songs(anotherSongsListWithFavourites);
            ((SongsAdapter) songsAdapter).updateSongs(modifiedSongs);
        }
    
        public static void test2_updateExistingSongCollection() {
            List<Song> songsList = new ArrayList<Song>();
            songsList.add(new Song("Generic Song Title", false));
            songsList.add(new Song("Another Song Title", false));
            songsList.add(new Song("A Third Song Title", false));
            Songs songs = new Songs(songsList);
    
            ListAdapter songsAdapter = new SongsAdapter(songs);
            // TODO: ListView.setAdapter(songsAdapter)
    
            /*
            Now we update the existing Songs object. The adapter's reference is 
            still pointing to it, so that data will change too, but the adapter
            won't know. This means the data will not immediately update on screen,
            unless the user scrolls up/down OR unless we tell the adapter to
            call `notifyDatasetChanged()` which we'd have to expose another method
            for because it's a `protected` method (not shown).
             */
            songs.get(0).isFavourite = true;
        }
    
        private static class Song {
    
            public final String songName;
            // not final because we're grossly modifying this for the example in test2
            public boolean isFavourite;
    
            private Song(String songName, boolean isFavourite) {
                this.songName = songName;
                this.isFavourite = isFavourite;
            }
    
        }
    
        private static class Songs {
    
            private final List<Song> songs;
    
            public Songs(List<Song> songs) {
                this.songs = songs;
            }
    
            public Song get(int position) {
                return songs.get(position);
            }
    
            public int size() {
                return songs.size();
            }
    
        }
    
        private static class SongsAdapter extends BaseAdapter {
    
            private Songs songs;
    
            private SongsAdapter(Songs songs) {
                this.songs = songs;
            }
    
            /*
                Update the dataset, and then pass the new data to the adapter.
                You could update an individual song, but I wouldn't recommmend it.
                This adapter's responsibility is to take a Songs object map each one
                to a View - it shouldn't have to deal with MODIFYING the dataset.
    
                Note, the `notifyDataSetChanged()`. This tells the ListView to ask
                the adapter for new views (with updated data).
             */
            public void updateSongs(Songs songs) {
                this.songs = songs;
                notifyDataSetChanged();
            }
    
            @Override
            public int getCount() {
                return songs.size();
            }
    
            @Override
            public Song getItem(int position) {
                return songs.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                // we won't support stable IDs for this example
                return 0;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = convertView;
                if (view == null) {
                    view = createNewView();
                }
                update(view, songs.get(position));
                return view;
            }
    
            private View createNewView() {
                // TODO: create a new instance of your view and return it
                return null;
            }
    
            private void update(View view, Song song) {
                // TODO: update the rest of the view
                if (song.isFavourite) {
                    // TODO: show badge on view
                } else {
                    // TODO: hide the badge on view
                }
            }
    
        }
    
    }
    

    【讨论】:

    • 谢谢 我理解了算法。但是我需要一些示例代码。你能举一个这个算法的例子吗?
    • 并非如此。我不知道你会在什么情况下出示徽章。我看不到您如何获取数据 (getItem()),因此无法对其进行修改。明天我会尝试添加一个人为的例子。
    • 我会等你的榜样。
    • @TolgayToklar 我已经更新了一个几乎完整的示例,希望这可以帮助您理解这个概念,请阅读代码中的 cmets。
    • @TolgayToklar 这有帮助吗?如果您有任何问题(关于此示例),请随时提问
    猜你喜欢
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2014-03-25
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多