首页 > 解决方案 > 如何在活动启动时在recyclerview中显示已选中的复选框(多对多关系)

问题描述

每个“Note”都以不同的方式“添加”到“Folders”,或者我应该说,每个“Note”都有不同的选中“Folders”。

当我检查“文件夹”时,使用后退按钮返回上一个 Notes 活动,然后打开相同的“Note”以转到“添加到文件夹活动”并将“Note”添加到文件夹,它应该记住之前检查过的“文件夹”并重新检查。

我已经在 onBindViewHolder 和 FolderHolder(RecyclerView Holder) 中实现了该功能。

问题是当我取消选中复选框时,recyclerview 中存在多个“文件夹”,然后向下滚动,然后备份,未选中的文件夹会按原样重新检查自身。

我知道每次滚动和回收视图都会调用 onBindViewHolder,因此检查“文件夹”会在滚动时重新检查。

我想在活动启动时检查之前已经检查过的文件夹,就像现在一样,但没有在 scroll 上重新检查它们

请你能给我一个代码吗?我真的很感激这个!

我的 recyclerview 适配器:

public class FoldersAddToFoldersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final Context context;

    private final ArrayList<Folder> folders;

    private final List<Folder> checkedFolders;

    private final Note note;

    private final FoldersDAO foldersDao;

    private final NotesFoldersJoinDAO notesFoldersJoinDao;

    public FoldersAddToFoldersAdapter(ArrayList<Folder> folders, List<Folder> checkedFolders, Note note, Context context,
                                      FoldersDAO foldersDao, NotesFoldersJoinDAO notesFoldersJoinDao) {
        this.folders = folders;
        this.checkedFolders = checkedFolders;
        this.note = note;
        this.context = context;
        this.foldersDao = foldersDao;
        this.notesFoldersJoinDao = notesFoldersJoinDao;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(R.layout.folder_add_to_folders_layout, parent, false);
        return new FolderHolder(v, this, notesFoldersJoinDao);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        final FolderHolder folderHolder = (FolderHolder) holder;
        final Folder folder = getFolder(position);
        if (folder != null) {
            //[..]

            folderHolder.setData(note, folder);


            // **THIS IS THE CODE WHICH CHECKS THE FOLDERS, WHICH I WAS SAYING ABOUT.** 
            for (Folder checkedFolder : checkedFolders) {
                if (checkedFolder.getId() == folder.getId()) {
                    folder.setChecked(true);
                }
            }
            folderHolder.checkBoxAddToFolders.setChecked(folder.isChecked());
        }
    }

    public void addCheckedFolder(Folder folder) {
        checkedFolders.add(folder);
    }

    public void removeCheckedFolder(Folder folder) {
        checkedFolders.remove(folder);
    }


    public static class FolderHolder extends RecyclerView.ViewHolder {

        CheckBox checkBoxAddToFolders;

        FoldersAddToFoldersAdapter adapter;

        Note note;

        Folder folder;

        NotesFoldersJoinDAO notesFoldersJoinDao;

        public FolderHolder(@NonNull View itemView, FoldersAddToFoldersAdapter adapter, NotesFoldersJoinDAO notesFoldersJoinDao) {
            super(itemView);
            checkBoxAddToFolders = itemView.findViewById(R.id.checkbox_add_to_folders);
            this.notesFoldersJoinDao = notesFoldersJoinDao;
            this.adapter = adapter;


            // THIS IS ALSO IMPORTANT FOR CHECKBOX.
            checkBoxAddToFolders.setOnClickListener(v -> {
                boolean isChecked = checkBoxAddToFolders.isChecked();
                NoteFolderJoin noteFolderJoin = new NoteFolderJoin(note.getId(), folder.getId());
                if (isChecked) {
                    folder.setChecked(true);
                    adapter.addCheckedFolder(folder);
                    notesFoldersJoinDao.insertNoteFolderJoin(noteFolderJoin);
                } else {
                    folder.setChecked(false);
                    adapter.removeCheckedFolder(folder);
                    notesFoldersJoinDao.deleteNoteNoteFolderJoin(noteFolderJoin);
                }
            });

        public void setData(Note note, Folder folder) {
            this.note = note;
            this.folder = folder;
        }
    }
} 

我的 Activity 有 recyclerview:

public class AddToFoldersActivity extends AppCompatActivity {

    public static final String NOTE_EXTRA_KEY = "note_id";

    private RecyclerView foldersListRv;

    private FoldersDAO folderDao;

    private FoldersAddToFoldersAdapter foldersAdapter;

    private Note note;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_to_folders);
        MaterialToolbar topAppBar = findViewById(R.id.top_app_bar_add_to_folders);
        
        foldersListRv = findViewById(R.id.folder_list_add_to_folders);
        folderDao = NotesDB.getInstance(this).foldersDAO();
        
        int smallestScreenWidth = getResources().getConfiguration().smallestScreenWidthDp;
        NotesDAO notesDAO = NotesDB.getInstance(this).notesDAO();

        int id = getIntent().getExtras().getInt(NOTE_EXTRA_KEY, 0);
        note = notesDAO.getNoteById(id);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);

        foldersListRv.setLayoutManager(layoutManager);

        loadFolders();

        topAppBar.setNavigationOnClickListener(view -> finish());
    }

    private void loadFolders () {
        NotesFoldersJoinDAO notesFoldersJoinDao = NotesDB.getInstance(this).notesFoldersJoinDAO();
        List<Folder> folderList = folderDao.getAllFolders();
        List<Folder> checkedFolderList = notesFoldersJoinDao.getFoldersFromNote(note.getId());
        ArrayList<Folder> folders = new ArrayList<>(folderList);
        this.foldersAdapter = new FoldersAddToFoldersAdapter(folders, checkedFolderList, note, this, folderDao, notesFoldersJoinDao);
        this.foldersListRv.setAdapter(foldersAdapter);
    }

我的“文件夹”房间数据库实体:

@Entity(tableName = "folders")
public class Folder {
    @ColumnInfo(name = "folderId")
    @PrimaryKey
    private int id;

    @ColumnInfo(name = "folderName")
    private String folderName;

    //The checked state gets saved as a room db column, in each folder.
    private boolean checked;

    public Folder() {
    }

    public String getFolderName() {
        return folderName;
    }

    public void setFolderName(String folderName) {
        this.folderName = folderName;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    //From this method, it gets and returns the checked state of the checkbox.
    public boolean isChecked() {
        return checked;
    }

    //And from this method, it sets the checked state of the checkbox.
    public void setChecked(boolean checked) {
        this.checked = checked;
    }
}

我当然删除了一些代码,因为它会使这个问题变得太冗长。

标签: javaandroidandroid-studiocheckboxandroid-recyclerview

解决方案


我终于解决了!我移动了:

for (Folder checkedFolder : checkedFolders) {
    if (checkedFolder.getId() == folder.getId()) {
        folder.setChecked(true);
    }
}

onBindViewHolder具有 recyclerview(AddToFoldersActivity) 的 Activity 并对其进行了一些修改以适应:

for (Folder checkedFolder : checkedFolderList) {
    for (Folder folder : folderList) {
        if (checkedFolder.getId() == folder.getId()) {
            folder.setChecked(true);
        }
    }
}

适配器(FoldersAddToFoldersAdapter):

public class FoldersAddToFoldersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final Context context;

    private final ArrayList<Folder> folders;

    private final List<Folder> checkedFolders;

    private final Note note;

    private final FoldersDAO foldersDao;

    private final NotesFoldersJoinDAO notesFoldersJoinDao;

    public FoldersAddToFoldersAdapter(ArrayList<Folder> folders, List<Folder> checkedFolders, Note note, Context context,
                                      FoldersDAO foldersDao, NotesFoldersJoinDAO notesFoldersJoinDao) {
        this.folders = folders;
        this.checkedFolders = checkedFolders;
        this.note = note;
        this.context = context;
        this.foldersDao = foldersDao;
        this.notesFoldersJoinDao = notesFoldersJoinDao;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(R.layout.folder_add_to_folders_layout, parent, false);
        return new FolderHolder(v, this, notesFoldersJoinDao);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        final FolderHolder folderHolder = (FolderHolder) holder;
        final Folder folder = getFolder(position);
        if (folder != null) {
            //[..]

            folderHolder.setData(note, folder);

            /* Moved code from here...
            for (Folder checkedFolder : checkedFolders) {
                if (checkedFolder.getId() == folder.getId()) {
                    folder.setChecked(true);
                }
            }
            */
            folderHolder.checkBoxAddToFolders.setChecked(folder.isChecked());
        }
    }

    public void addCheckedFolder(Folder folder) {
        checkedFolders.add(folder);
    }

    public void removeCheckedFolder(Folder folder) {
        checkedFolders.remove(folder);
    }


    public static class FolderHolder extends RecyclerView.ViewHolder {

        CheckBox checkBoxAddToFolders;

        FoldersAddToFoldersAdapter adapter;

        Note note;

        Folder folder;

        NotesFoldersJoinDAO notesFoldersJoinDao;

        public FolderHolder(@NonNull View itemView, FoldersAddToFoldersAdapter adapter, NotesFoldersJoinDAO notesFoldersJoinDao) {
            super(itemView);
            checkBoxAddToFolders = itemView.findViewById(R.id.checkbox_add_to_folders);
            this.notesFoldersJoinDao = notesFoldersJoinDao;
            this.adapter = adapter;

            checkBoxAddToFolders.setOnClickListener(v -> {
                boolean isChecked = checkBoxAddToFolders.isChecked();
                NoteFolderJoin noteFolderJoin = new NoteFolderJoin(note.getId(), folder.getId());
                if (isChecked) {
                    folder.setChecked(true);
                    adapter.addCheckedFolder(folder);
                    notesFoldersJoinDao.insertNoteFolderJoin(noteFolderJoin);
                } else {
                    folder.setChecked(false);
                    adapter.removeCheckedFolder(folder);
                    notesFoldersJoinDao.deleteNoteNoteFolderJoin(noteFolderJoin);
                }
            });

        public void setData(Note note, Folder folder) {
            this.note = note;
            this.folder = folder;
        }
    }
} 

并将代码移至 Activity(AddToFoldersActivity):

public class AddToFoldersActivity extends AppCompatActivity {

    public static final String NOTE_EXTRA_KEY = "note_id";

    private RecyclerView foldersListRv;

    private FoldersDAO folderDao;

    private FoldersAddToFoldersAdapter foldersAdapter;

    private Note note;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_to_folders);
        MaterialToolbar topAppBar = findViewById(R.id.top_app_bar_add_to_folders);
        
        foldersListRv = findViewById(R.id.folder_list_add_to_folders);
        folderDao = NotesDB.getInstance(this).foldersDAO();
        
        NotesDAO notesDAO = NotesDB.getInstance(this).notesDAO();

        int id = getIntent().getExtras().getInt(NOTE_EXTRA_KEY, 0);
        note = notesDAO.getNoteById(id);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);

        foldersListRv.setLayoutManager(layoutManager);

        //This is where the code really ends up.
        loadFolders();

        topAppBar.setNavigationOnClickListener(view -> finish());
    }

    //The loadFolders() gets called in onCreate().
    private void loadFolders () {
        NotesFoldersJoinDAO notesFoldersJoinDao = NotesDB.getInstance(this).notesFoldersJoinDAO();
        List<Folder> folderList = folderDao.getAllFolders();
        List<Folder> checkedFolderList = notesFoldersJoinDao.getFoldersFromNote(note.getId());
        ArrayList<Folder> folders = new ArrayList<>(folderList);
        
        //The code gets called here.
        checkAlreadyCheckedFolders(checkedFolderList, folderList);
        
        this.foldersAdapter = new FoldersAddToFoldersAdapter(folders, checkedFolderList, note, this, folderDao, notesFoldersJoinDao);
        this.foldersListRv.setAdapter(foldersAdapter);
    }

    //The code moved to here, with a bit of modification and gets called in loadFolders().
    private void checkAlreadyCheckedFolders(List<Folder> checkedFolderList, List<Folder> folderList) {
        for (Folder checkedFolder : checkedFolderList) {
            for (Folder folder : folderList) {
                if (checkedFolder.getId() == folder.getId()) {
                    folder.setChecked(true);
                }
            }
        }
    }

最后是“文件夹”房间数据库实体(表):

@Entity(tableName = "folders")
public class Folder {
    @ColumnInfo(name = "folderId")
    @PrimaryKey
    private int id;

    @ColumnInfo(name = "folderName")
    private String folderName;

    //The checked state gets saved as a room db column, in each folder.
    private boolean checked;

    public Folder() {
    }

    public String getFolderName() {
        return folderName;
    }

    public void setFolderName(String folderName) {
        this.folderName = folderName;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    //From this method, it gets and returns the checked state of the checkbox.
    public boolean isChecked() {
        return checked;
    }

    //And from this method, it sets the checked state of the checkbox.
    public void setChecked(boolean checked) {
        this.checked = checked;
    }
}

这样,复选框检查仅​​在 Activity(AddToFoldersActivity) 启动/创建时运行一次,而不是在每次滚动中,在 onBindViewHolder() 内一次又一次地运行。onBindViewHolder() 在每个滚动条上运行。


推荐阅读