【電卓アプリを作るvol.7】アプリ終了時の状態を保存
前回まで・・・
計算結果に端数が出た場合に、
それを丸めて表示する静的メソッドを実装しました。
今回は、
計算中に電話がかかってきて、
戻ったら全てクリアーされていたという、
悲しいことが起こらないように、
終了時の状態を保存し、
再開したときにロードする機能を実装していきます。
何を保存するべきか
電卓を開いたときに、
どのような情報があれば、
同じ状態を再現できるでしょうか?
最後に見ていたものと、再開直後が違っていたら、
不安になってACを押してしまうでしょう。
なので、
①ディスプレイに表示されている文字列
は欠かせません。
見たままを保存します。
単純に、StringBuilder.toString()で得られる文字列を保存します。
電卓には状態があると前途しました。
状態によって呼び分けられるメソッドが変わってきます。
②現在の状態
を保存します。
現在の状態を知るためのメソッド、
int getStateValue()をすでに用意していますので、
それによって得られた定数も保存します。
状態が右辺入力中なら、
③左辺の情報が無いと計算できません。
④演算子も同様です。
定数計算のために、
⑤右辺の値も必要です。
今回はメモリー機能やグランドトータル機能は実装していませんので、
これら5つの情報を保存すれば、
どの状況も再現が可能です。
再現するには
アプリのオンポーズ時にこれらを保存し、
オンレジューム時に、
Calcクラスのインスタンスのフィールドに、
上記の情報を格納します。
stateに状態に応じたクラスのインスタンス、
value1に左辺の値をdoubleで、
value2に右辺の値を同じくdouble、
enzanshiは、演算子を示す定数、
stringBuilderに、最後に見ていたのと同じ文字列を入れます。
Calc内に、これら5情報を保持するクラスを作ります
コンストラクターも用意します。
public class CalcHolder{ public int state; public String dispString; public double leftValu,rightValue; public int enzanshi; public CalcHolder(int state,String dispString, double leftValue, double rightValue, int enzanshi) { this.state = state; this.dispString = dispString; this.leftValu = leftValue; this.rightValue = rightValue; this.enzanshi = enzanshi; } }
同じくCalc内に、セーブ用とロード用のパブリックなメソッドを定義します。
セーブ用のgetHolderでは、CalcHolderのインスタンスを返し、
ロード用のsetHolderは、CalcHolderのインスタンスを渡すことによって、
前回の状態に復帰します。
public CalcHolder getHolder(){ return new CalcHolder(state.getStateValue(this),stringBuilder.toString(), value1,value2,enzanshi); } public void setHolder(CalcHolder holder){ switch (holder.state){ case State.STATE_A: changeState(StateA.getInstance()); break; case State.STATE_B: changeState(StateB.getInstance()); break; case State.STATE_C: changeState(StateC.getInstance()); break; case State.STATE_D: changeState(StateD.getInstance()); break; } this.value1 = holder.leftValu; this.value2 = holder.rightValue; this.enzanshi = holder.enzanshi; set(holder.dispString); callback.onTextChanged(stringBuilder.toString()); }
メインアクティビティのonPauseとonResumeに保存・復帰の処理を記述します。
Gsonを利用しますので、Gsonライブラリーを読み込んで置きます。
(Gsonについての関連記事)
@Override protected void onPause() { super.onPause(); Calc.CalcHolder holder = calc.getHolder(); Gson gson = new Gson(); String js = gson.toJson(holder, Calc.CalcHolder.class); getSharedPreferences("pref",MODE_PRIVATE).edit().putString("holder",js).apply(); } @Override protected void onResume() { super.onResume(); final String NULL = "null"; Gson gson = new Gson(); String js = getSharedPreferences("pref",MODE_PRIVATE).getString("holder",NULL); if (js.equals(NULL)){ calc.allClear(); // 初回起動 } else { calc.setHolder(gson.fromJson(js, Calc.CalcHolder.class)); } }
正しく動作するか確かめてみてください。
マニフェストでアプリをポートレイトにしていなければ、
端末の向きを変えてみて、数字がリセットされないことでも確認できます。
ちなみに、onResume内の「初回起動」とコメントアウトした部分は、
そのまま、ダウンロード後の第一回目の起動なので、
サンキューメッセージ等を表示するのもいいかもしれません。