質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

1回答

609閲覧

android studioでのデータ保存がうまくいかない。

ottosay

総合スコア4

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2023/12/21 13:54

実現したいこと

画面遷移をし直してもデータが残っているようにしたい。

前提

現在、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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2023/12/21 16:59

「うまくいかない」では何が起きているのか全く分かりません。 アプリが落ちるのでしょうか。 書き込みがされないのでしょうか、読み込みが失敗しているのでしょうか。 書き込みで GradesData をどのようなキー・値を実際に書き込んでいるか、読み込みでどのようなキー・値を読んでいるか等は調査されていますでしょうか。 todo の時と同じ構造でしたら、ダイアログで保存する必要は無い(アダプタの set/add で保存される)はずですが、何故保存するコードがあるのでしょう。
guest

回答1

0

うまくいかない

// データ数を保存 editor.putInt("gradedataSize", gradedataList.size());
// データ数の読み込み int dataSize = preferences.getInt("gradedataListSize", 0);

保存する時のキーと読み込む時のキーが違っています。
このように同じ文字列を使う(使わなければいけない)場合は定数 ( private static final String ABC = "~"; みたいなの) を作って使うようにすると、書き損じ等でのバグの発生を予防出来ます。( FragmentResult 関係や args 関係で色々定義しているのはそのためです。)

SQLiteを使った時とどちらが簡単に作れるか

そもそも SharedPreference はアプリの設定(画面の色とか音の種類・音量とか)を保存するためのもので、アプリのデータを保存するためのものではありません。
言わばムリヤリ使っている状態ですので、「どちらが簡単か」と比較出来るものではありません。
そして、データベースの世界はプログラムの世界とはまた違うものです。
データ構造であるとか SQL、RDB (リレーショナルデータベース) の考え方等を勉強されると良いと思います。
ネットに Android で SQLite 入門のような記事もあると思いますので、サンプルプログラム等あったらやって見られては如何でしょうか。

投稿2023/12/21 15:37

編集2023/12/22 01:22
jimbe

総合スコア13336

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ottosay

2023/12/21 16:16

SQLiteは気になった程度で聞きました。 回答して頂きありがとうございます!
jimbe

2023/12/21 16:34 編集

データベースとしては他に Realm(MongoDB) というのもありますし、 SQLite を用いたライブラリとして Room というのもあります。 Room は Google 製なので公式では推されているようです。
ottosay

2023/12/21 18:23

キーが違っていたんですね。 教えていただきありがとうございます! 編集してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問