Post on 11-Apr-2017
About this talk
● Progress dialog
● Technically○ Show/Dismiss by BehaviorSubject (RxJava 1.x)○ ViewModel lifecycle management with Dagger2
● Preview app○ https://github.com/tsuyoyo/shibuya_apk_13
Major troubles by progress dialog...
● Dismiss at orientation change
● Remains on screen
● Suddenly crashes in the background(since 3.0/HoneyComb)
java.lang.IllegalStateException:
Can not perform this action after onSaveInstanceState
How can we beat them?
● android:configChanges="orientation"
● No care (e.g. call API again)
● Try to manage state○ Activity#onSaveInstanceState○ Activity#onRetainCustomNonConfigurationInstance
1. Something independent on Activity lifecycle
2. Always view can revive
3. Dialog? (not DialogFragment)
Implementation idea (1) : BehaviorSubject
onNext(true);
BehaviorSubject<Boolean>
Observer B
onNext(false);
Observer C
Observer A
Implementation idea (2) : Lifecycle of ViewModel
● Use Dagger2, provided by component
● Scope?○ longer than Activity & shorter than Application
● Custom scope!!○ Referred : Dependency injection with Dagger 2 - Custom scopes
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
Custom scope
● Looks just annotation, no effect
● Application class holds the component, releases it at end of screen
@Scope@Retention(RetentionPolicy.RUNTIME)@interface ViewModelScope {}
Custom scopepublic class MyApplication extends Application {
private MyComponent component;
public MyComponent getMyComponent() { if (component == null) { component = DaggerMyComponent.builder().build(); } return component; }
public void releaseMyComponent() { component = null; }
}
Custom scopepublic class MainActivity extends AppCompatActivity {
@Inject MyViewModel myViewModel;
@Override protected void onCreate(Bundle savedInstanceState) {
… ((MyApplication) getApplication()).getMyComponent().inject(this); bindViewModel(); }
@Override public void finish() { super.finish(); ((MyApplication) getApplication()).releaseMyComponent(); }
Summary
● Simple way to beat messy caused by ProgressDialog
● BehaviorSubject & CustomScope
● For detail○ https://github.com/tsuyoyo/shibuya_apk_13
Implementation idea (1) : BehaviorSubjectprivate MyFakeApi api;private BehaviorSubject<Boolean> isLoading = BehaviorSubject.create(false);...public Observable<Boolean> isLoading() { return isLoading.asObservable(); }… api.call(). .doOnSubscribe( () -> isLoading.onNext(true) ) .doOnUnsubscribe( () -> isLoading.onNext(false) ) .subscribe( /** do something */ )...
private void bindViewModel() {…myViewModel.isLoading() .observeOn(AndroidSchedulers.mainThread()) .subscribe(isLoading -> /** show/dismiss progress dialog */)
ViewModel
View