簡體   English   中英

如何在設備旋轉時恢復 Android RecyclerView 列表項中的復選框狀態

[英]How to restore checkBox state in Android RecyclerView list items on Rotation of device

我當前的 Android 應用程序包含一個 RecyclerView,它在列表中的每個項目中都有一個復選框。

我的問題是在屏幕旋轉時復選框總是返回到未選中狀態。

我將更新的列表項存儲在我的活動 ViewModel 中,並將這個保存的列表傳遞回 onCreate 中的適配器

從我的調試日志中,我可以看到列表狀態正確地保存了每個列表項的選中/未選中狀態。

我還注銷了適配器構造函數中的列表,該列表還顯示選中狀態仍然有效。

但是,當onBindViewHolder時,列表項onBindViewHolder選中。

這是我的代碼片段:-

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

        manageViewModel();
        recyclerView = findViewById(R.id.my_rv);

        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        adapter = new MedicationAdapter(viewModel.getList(), this);
        recyclerView.setAdapter(adapter);

   }



protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    viewModel.saveList(adapter.getList());
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
}

我的列表項復選框在 xml 中定義如下:-

<android.support.v7.widget.AppCompatCheckBox
            android:id="@+id/my_checkbox_header"
            android:layout_width="wrap_content"
            android:saveEnabled="false"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:text="" />

在設備旋轉時在 RecyclerView 項目中保持復選框狀態的正確方法是什么?

我的適配器代碼:-

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

        private static final String TAG = "MusicalAdapter";
        private int previousExpandedPosition = -1;
        private int mExpandedPosition = -1;

        private final List<MusicalUI> musicals = new ArrayList<>();
        private final ItemClickListener clickListener;

        MusicalAdapter(final List<MusicalUI> musicals, final ItemClickListener clickListener) {
            this.musicals.clear();
            this.musicals.addAll(musicals);
//AT THIS POINT THE CHECKED VALUES ARE AS EXPECTED

            this.clickListener = clickListener;
        }

        @NonNull
        @Override
        public MusicalAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
            final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.all_disco_item_x, parent, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull final MusicalAdapter.ViewHolder holder, final int position) {
            final MusicalUI musical = musicals.get(position);

            Log.d(TAG, "onBindViewHolder() called with: musical = [" + musical.getChecked());

// AT THI SPOINT THE CHECKED VALUES ARE ALWAYS FALSE!!!!!!!!
            final boolean isExpanded = position == mExpandedPosition;


            for (final MusicalUI musicalx : musicals) {
                Log.d(TAG, "onBindViewHolder(): " + musicalx.getChecked());
            }

            // Header
            holder.discoDetailsHeaderLayout.setVisibility(View.VISIBLE);
            holder.musicalNameHeader.setText(musical.getDiscoName());

            holder.discoSelectedHeader.setOnCheckedChangeListener(null);
            holder.discoSelectedHeader.setChecked(musical.getChecked());
            holder.discoSelectedHeader.setOnCheckedChangeListener((buttonView, isChecked) -> musical.setChecked(isChecked));


            if (isExpanded)
                previousExpandedPosition = position;

            holder.itemView.setOnClickListener(v -> {
                mExpandedPosition = isExpanded ? -1 : position;
                notifyItemChanged(previousExpandedPosition);
                notifyItemChanged(position);
            });

        }

        @Override
        public int getItemCount() {
            return musicals.size();
        }


        MusicalUI getItem(final int position) {
            return musicals.get(position);
        }

        void updateList(final List<MusicalUI> newMusicals) {
            final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(this.musicals, newMusicals));
            diffResult.dispatchUpdatesTo(this);

            this.musicals.clear();
            this.musicals.addAll(newMusicals);
        }

        List<MusicalUI> getList() {
            return musicals;
        }

        /**
         *
         */
        public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
    ...
            }


        }
    }

它會發生變化,因為當輪換發生變化時,您的活動會重新啟動。 您可以編寫大量的代碼來恢復狀態,或者你可以避開重啟。 這是正確的方法

為了使您的活動不會在輪換更改中重新啟動

在 AndroidManifest 中找到您的活動並添加

android:configChanges="orientation"

Android 還建議在大多數情況下避免使用它

它說讓 android 自己處理配置更改

注意:自行處理配置更改會使使用替代資源變得更加困難,因為系統不會自動為您應用它們。 當您必須避免因配置更改而重新啟動時,應將此技術視為最后的手段,並且不推薦用於大多數應用程序。

要聲明您的 Activity 處理配置更改,請編輯清單文件中的相應元素以包含 android:configChanges 屬性,其值代表您要處理的配置。 android:configChanges 屬性的文檔中列出了可能的值。 最常用的值是“orientation”、“screenSize”和“keyboardHidden”。 “orientation”值可防止屏幕方向改變時重新啟動。

更多信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM