実現したいこと
画面遷移をし直してもデータが残っているようにしたい。
前提
現在、SharedPreferencesを使って画面遷移をし直したあとでもデータが残る状態を作りたいのですが、うまくいきません。
SQLiteを使った時とどちらが簡単に作れるかなども聞きたいです。
発生している問題・エラーメッセージ
画面遷移をし直したら、追加したデータが再度表示されない。
該当のソースコード
SubListFragment.java
private static class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> { private List<GradeData> gradedataList; private final FragmentActivity activity; private BiConsumer<Integer, GradeData> rowClickListener; Adapter(FragmentActivity activity) { this.gradedataList = new ArrayList<>(); this.activity = activity; // データの復元 loadDataFromSharedPreferences(gradedataList); } void setRowClickListener(BiConsumer<Integer, GradeData> l) { rowClickListener = l; } void add(GradeData gradedata) { gradedataList.add(gradedata); notifyItemInserted(gradedataList.size() - 1); saveDataToSharedPreferences(gradedataList); } void set(int position, GradeData gradedata) { gradedataList.set(position, gradedata); notifyItemChanged(position); saveDataToSharedPreferences(gradedataList); } private void saveDataToSharedPreferences(List<GradeData> gradedataList) { // SharedPreferencesの取得 SharedPreferences preferences = activity.getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); // データ数を保存 editor.putInt("gradedataSize", gradedataList.size()); // 各データを保存 for (int i = 0; i < gradedataList.size(); i++) { GradeData gradedata = gradedataList.get(i); editor.putString("subjectName_" + i, gradedata.subjectName); editor.putInt("elementSize_" + i, gradedata.getElementSetSize()); // 各要素のデータを保存 for (GradeData.Type type : GradeData.Type.values()) { GradeData.Element element = gradedata.getElement(type); editor.putBoolean("elementValid_" + i + "_" + type.name(), element.valid); editor.putInt("elementWeight_" + i + "_" + type.name(), element.weight); editor.putInt("elementAchieved_" + i + "_" + type.name(), element.achieved); } } // 保存を確定 editor.apply(); } private void loadDataFromSharedPreferences(List<GradeData> gradedataList) { // SharedPreferencesの取得 SharedPreferences preferences = activity.getPreferences(Context.MODE_PRIVATE); // データ数の読み込み int dataSize = preferences.getInt("gradedataListSize", 0); // リストをクリアして新しいデータを読み込む gradedataList.clear(); for (int i = 0; i < dataSize; i++) { GradeData gradedata = new GradeData(); gradedata.subjectName = preferences.getString("subjectName_" + i, ""); gradedata.setElementSize(preferences.getInt("elementSize_" + i, 0)); // 各要素のデータを読み込み for (GradeData.Type type : GradeData.Type.values()) { GradeData.Element element = gradedata.getElement(type); element.valid = preferences.getBoolean("elementValid_" + i + "_" + type.name(), false); element.weight = preferences.getInt("elementWeight_" + i + "_" + type.name(), 0); element.achieved = preferences.getInt("elementAchieved_" + i + "_" + type.name(), 0); } gradedataList.add(gradedata); } } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new ViewHolder(parent); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { holder.bind(gradedataList.get(position)); } @Override public int getItemCount() { return gradedataList.size(); } class ViewHolder extends RecyclerView.ViewHolder { private final TextView text1, text2; private GradeData gradedata; ViewHolder(@NonNull ViewGroup parent) { super(LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2, parent, false)); itemView.setOnClickListener(v -> { if(rowClickListener != null) rowClickListener.accept(getAdapterPosition(), gradedata); }); text1 = itemView.findViewById(android.R.id.text1); text2 = itemView.findViewById(android.R.id.text2); } void bind(GradeData gradedata) { this.gradedata = gradedata; text1.setText(gradedata.subjectName); text2.setText(gradedata.getPercentage() + " %"); } } } }
SubDialogFragment.java
public class SubDialogFragment extends DialogFragment { static final String RESULT_KEY_POSITION = "position"; static final String RESULT_KEY_GRADES = "grades"; private static final String ARGS_REQUESTKEY = "requestkey"; private static final String ARGS_POSITION = "position"; private static final String ARGS_GRADES = "grades"; static SubDialogFragment getInstance(String requestKey, int position, GradeData gradedata) { if(requestKey == null) throw new NullPointerException("requestKey is NULL"); SubDialogFragment f = new SubDialogFragment(); Bundle args = new Bundle(); args.putString(ARGS_REQUESTKEY, requestKey); args.putInt(ARGS_POSITION, position); args.putSerializable(ARGS_GRADES, gradedata); f.setArguments(args); return f; } private void saveGradeData(GradeData gradedata) { SharedPreferences preferences = requireActivity().getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); // gradedataからSharedPreferencesに必要なデータを保存 editor.putString("subjectName", gradedata.subjectName); // 各要素のデータを保存 for (GradeData.Type type : GradeData.Type.values()) { GradeData.Element element = gradedata.getElement(type); String prefix = type.name(); // 一意性のためにタイプの名前をプレフィックスとして使用 editor.putBoolean(prefix + "_valid", element.valid); editor.putInt(prefix + "_weight", element.weight); editor.putInt(prefix + "_achieved", element.achieved); } editor.apply(); } private GradeData gradedata; @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { Bundle args = getArguments(); String requestKey = args.getString(ARGS_REQUESTKEY); if(requestKey == null) throw new NullPointerException("requestKey is NULL"); int position = args.getInt(ARGS_POSITION, -1); gradedata = (GradeData)args.getSerializable(ARGS_GRADES); if(gradedata == null) gradedata = new GradeData(); View view = LayoutInflater.from(requireContext()).inflate(R.layout.fragment_sub_item_dialog, null); EditText nameEdit = view.findViewById(R.id.subject_edit); nameEdit.setText(gradedata.subjectName); nameEdit.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { /*no process*/ } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { /*no process*/ } @Override public void afterTextChanged(Editable s) { gradedata.subjectName = s.toString(); } }); GradeData.Type[] types = GradeData.Type.values(); setElementView(view, R.id.check_1, R.id.element_1, types[0]); setElementView(view, R.id.check_2, R.id.element_2, types[1]); setElementView(view, R.id.check_3, R.id.element_3, types[2]); setElementView(view, R.id.check_4, R.id.element_4, types[3]); setElementView(view, R.id.check_5, R.id.element_5, types[4]); return new AlertDialog.Builder(requireContext()) .setTitle("成績") .setView(view) .setPositiveButton("OK", (v,w) -> { Bundle result = new Bundle(); result.putInt(RESULT_KEY_POSITION, position); result.putSerializable(RESULT_KEY_GRADES, gradedata); // SharedPreferencesにデータ書き込み saveGradeData(gradedata); getParentFragmentManager().setFragmentResult(requestKey, result); }) .setNegativeButton("Cancel", null) .create(); } void setElementView(View view, @IdRes int checkId, @IdRes int elementId, GradeData.Type type) { GradeData.Element e = gradedata.getElement(type); CheckBox check = view.findViewById(checkId); check.setChecked(e.valid); SubElementView elementView = view.findViewById(elementId); elementView.set(type, e); elementView.setEnabled(e.valid); elementView.setChangeListener(v -> { gradedata.setElementWeight(type, v.getWeight()); gradedata.setElementAchieved(type, v.getAchieved()); }); check.setOnCheckedChangeListener((v,b) -> { gradedata.setElementValid(type, b); elementView.setEnabled(b); }); } }
試したこと
SharedPreferencesを使っているがうまくいかなかった。
コードが長いので、省略している部分があります。
補足情報(FW/ツールのバージョンなど)
android studio
