Android: 画面の向きの変更時にデータを保持するパターン

More than 1 year has passed since last update.

onSaveInstanceState, onRestoreInstanceStateを使う方法もありますが, 今回はFragmentを使う方法を紹介します.

サンプルコードは https://github.com/satoshun-example/AndroidRetainData にあります.


ユースケース

ネットワークはコストが掛かるので, 1度データを取得したら, 画面回転でアクティビティが再生成されたとしてもデータを使いまわしたい, というケースがあるとします.


やり方

まず, データを保持するFragmentを定義します.

最初にonCreateで, setRetainInstance(true)をコールします.

@Override

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);

refresh();
}

次に, refreshでデータを取得します. ここではRxJava2 + Retrofitを使っています.

void refresh() {

disposables.clear();
disposables.add(provideGithubAPI()
.getRepositories("satoshun")
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
data -> subject.onNext(data),
e -> subject.onError(e)));
}

APIコールをして, 取得したデータをBehaviorSubject(subject)に与えます.

最後にobservableメソッドを定義し, データソース(subject)を他のオブジェクトからアクセス出来るようにします.

Observable<List<Repo>> observable() {

return subject;
}

Fragmentのフルソースコードはここにあります.

次に, Activityの準備をします. ActivityのonCreateでデータFragmentを使うようにするだけです.

@Override

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataFrag = (RetainFragment) getSupportFragmentManager().findFragmentByTag("data");
if (dataFrag == null) {
dataFrag = RetainFragment.newInstance();
getSupportFragmentManager()
.beginTransaction()
.add(dataFrag, "data")
.commit();
}
// ここで, データFragmentからデータを取得する!!
disposables.add(dataFrag.observable()
.subscribe(
data -> {
binding.swipe.setRefreshing(false);
repoAdapter.addRepos(data);
},
e -> {
binding.swipe.setRefreshing(false);
Log.e("onDataSource", e.getMessage());
}));
}

Activityのフルソースコードはここにあります.

これで, データFragmentで取得したデータを使いまわせます!


まとめ

FragmentはUIだけでなく, データオブジェクトとしても有能.