まじめに回転対応すると Activity が破棄されたときどうするのかとか考える必要があって面倒ですが、細かいことは置いといて雑に回転対応するのであれば ViewModel を使用すると簡単にできます。
どうやるの?
回転対応前
例えば以下のような形で回転するたびに Toast で何回目の回転か表示する Activity があったとします。
public class MainActivity extends AppCompatActivity {
// この値を回転しても保持したい
int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
count++;
Toast.makeText(this, String.valueOf(count) + "回目!!", Toast.LENGTH_SHORT).show();
}
}
このコードを実行すると何度回転しても「1回目!!」と表示されます。回転されるたびに onCreate() からすべてやり直しになって、count が初期化されてしまうためです。
回転対応後
Google が提供している Architecture Compoennts というものを入れると簡単に回転対応ができます。
app/build.gradle を以下をします。
dependencies {
...
compile 'android.arch.lifecycle:extensions:1.1.1'
...
}
上のライブラリは google のリポジトリにしかないので以下ような感じでプロジェクトルートにある build.gradle にも変更を加える必要があります。
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
}
これで Architecture Components が使えるようになった。あとは先ほどの Activity を以下のように変更するだけです。
public class MainActivity extends AppCompatActivity {
// 保持したい変数を ↓ の ViewModel に突っ込む!
public static class MyModel extends ViewModel {
int count = 0;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ViewModelProviders から上で定義した Model を取り出す
// ここで取り出した model には回転前の値がちゃんと保持されている
MyModel model = ViewModelProviders.of(this).get(MyModel.class);
model.count++;
Toast.makeText(this, String.valueOf(model.count) + "回目!!", Toast.LENGTH_SHORT).show();
}
}
回転後も保持したい変数を ViewModel というののメンバ変数にして、ViewModelProvider からそれを引っ張り出してくるだけで回転対応が完了。簡単!
もちろん Fragment でも同じような感じで対応できます。
ViewModel はちゃんとライフサイクルに応じて解放もしてくれるので、リークの心配も不要です。ただ、View や Context を ViewModel に入れるとリークするので注意が必要です。
注意すべき点として、アプリがバックグラウンドになって、ある程度放置されたときなどに Activity が破棄されることがありますが、そのときは count が初期値(このコードの場合だと 0 )に戻ってしまいます。
ここもちゃんと対応したいのであれば、saveInstanceState, Room などを使用した回転対応が必要になります。