Android 适配器更新不可见行

Android 适配器更新不可见行,android,android-adapter,Android,Android Adapter,如果你复习这个问题,你会看到这个答案。这个答案只适用于可见行。但我必须在不可见行和可见行中添加徽章。@pomber给出了一个提示,但我无法理解 我怎样才能完成这个过程?我需要一个例子。您不应该试图直接修改listview的子元素。相反,请修改适配器,以便根据某些条件显示徽章 然后,修改适配器的基础数据并在适配器和listview上调用notifyDatasetChanged将重新绘制自身 例如,考虑你的适配器被歌曲对象列表支持。在getView中,如果Song get itemposition.

如果你复习这个问题,你会看到这个答案。这个答案只适用于可见行。但我必须在不可见行和可见行中添加徽章。@pomber给出了一个提示,但我无法理解


我怎样才能完成这个过程?我需要一个例子。

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

然后,修改适配器的基础数据并在适配器和listview上调用notifyDatasetChanged将重新绘制自身

例如,考虑你的适配器被歌曲对象列表支持。在getView中,如果Song get itemposition.IsFavorited返回true,则可以显示徽章

要显示列表中第n首歌曲的徽章,您需要修改列表songs.getn.favorite和call adapter.notifyDatasetChanged

使用更详细但不完全完整的示例进行编辑。请注意评论和待办事项:

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我已经更新了一个几乎完整的示例,希望这有助于您理解概念,请阅读代码中的注释。@TolgayToklar这有帮助吗?如果您对此示例有任何疑问,请随时提问