MVP 和 RxJava - 在 Android 上处理方向变化
MVP and RxJava - Handling Orientation Changes on Android
我正在使用类似于 google-samples 存储库的 MVP 和 RxJava。
我想问一下如何正确处理屏幕方向变化。
我是在presenter中将视图的状态封装在特定的ViewStateclass中处理的,测试起来很方便。
public interface BaseViewState {
void saveState(@NonNull Bundle outState);
void restoreState(@Nullable Bundle savedInstanceState);
}
class HomeViewState implements BaseViewState {
static final long NONE_NUM = -1;
static final String STATE_COMIC_NUM = "state_comic_num";
private long comicNum = NONE_NUM;
@Inject
HomeViewState() {
}
@Override
public void saveState(@NonNull Bundle outState) {
outState.putLong(STATE_COMIC_NUM, comicNum);
}
@Override
public void restoreState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
comicNum = savedInstanceState.getLong(STATE_COMIC_NUM, NONE_NUM);
}
}
long getComicNumber() {
return comicNum;
}
void setComicNum(long comicNum) {
this.comicNum = comicNum;
}
}
get/set 来自 presenter 中 viewState 的值,这有助于保持更新,以及 presenter 无状态。
public class HomePresenter implements HomeContract.Presenter {
private HomeViewState viewState;
HomeViewState getViewState() {
return viewState;
}
@Override
public void loadComic() {
loadComic(viewState.getComicNumber());
}
...
}
在 Activity 中,因为视图应启动保存和恢复调用。
public class MainActivity extends BaseActivity implements HomeContract.View {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
homePresenter.getViewState().restoreState(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
homePresenter.getViewState().saveState(outState);
}
...
}
还有另一种策略可以保存演示者状态以及 Observable
的状态:retain Fragment
。这样你就省略了将数据保存到 Bundle
中的标准 Android 方法(它只允许保存简单变量而不是网络请求的状态。)
Activity
:
public class MainActivity extends AppCompatActivity implements MainActivityView {
private static final String TAG_RETAIN_FRAGMENT = "retain_fragment";
MainActivityPresenter mPresenter;
private MainActivityRetainFragment mRetainFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
initRetainFragment();
initPresenter();
}
private void initRetainFragment() {
FragmentManager fm = getSupportFragmentManager();
mRetainFragment = (MainActivityRetainFragment) fm.findFragmentByTag(TAG_RETAIN_FRAGMENT);
if (mRetainFragment == null) {
mRetainFragment = new MainActivityRetainFragment();
fm.beginTransaction().add(mRetainFragment, TAG_RETAIN_FRAGMENT).commit();
}
}
private void initPresenter() {
mPresenter = mRetainFragment.getPresenter();
mRetainFragment.retainPresenter(null);
if (mPresenter == null) {
mPresenter = new MainActivityPresenter();
}
mPresenter.attachView(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!isFinishing()) {
mRetainFragment.retainPresenter(mPresenter);
return;
}
mPresenter.detachView();
mPresenter = null;
}
}
保留Fragment
:
public class MainActivityRetainFragment extends Fragment {
private MainActivityPresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void retainPresenter(MainActivityPresenter presenter) {
this.presenter = presenter;
}
public MainActivityPresenter getPresenter() {
return presenter;
}
}
注意 activity 生命周期事件的处理方式。创建 Activity
时,将保留 Fragment
添加到后台堆栈,并在生命周期事件中从后台堆栈恢复。 retain Fragment
没有任何视图,它只是配置更改期间演示者的持有者。注意主要的调用,它可以从 backstack 中恢复完全相同的片段(及其内容):
setRetainInstance(true)
如果您担心内存泄漏:每次恢复演示者时都会恢复演示者的视图:
mPresenter.attachView(this);
所以之前的 Activity
引用被新的替换了。
这里有更多关于这种配置更改处理的信息here
我正在使用类似于 google-samples 存储库的 MVP 和 RxJava。
我想问一下如何正确处理屏幕方向变化。
我是在presenter中将视图的状态封装在特定的ViewStateclass中处理的,测试起来很方便。
public interface BaseViewState {
void saveState(@NonNull Bundle outState);
void restoreState(@Nullable Bundle savedInstanceState);
}
class HomeViewState implements BaseViewState {
static final long NONE_NUM = -1;
static final String STATE_COMIC_NUM = "state_comic_num";
private long comicNum = NONE_NUM;
@Inject
HomeViewState() {
}
@Override
public void saveState(@NonNull Bundle outState) {
outState.putLong(STATE_COMIC_NUM, comicNum);
}
@Override
public void restoreState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
comicNum = savedInstanceState.getLong(STATE_COMIC_NUM, NONE_NUM);
}
}
long getComicNumber() {
return comicNum;
}
void setComicNum(long comicNum) {
this.comicNum = comicNum;
}
}
get/set 来自 presenter 中 viewState 的值,这有助于保持更新,以及 presenter 无状态。
public class HomePresenter implements HomeContract.Presenter {
private HomeViewState viewState;
HomeViewState getViewState() {
return viewState;
}
@Override
public void loadComic() {
loadComic(viewState.getComicNumber());
}
...
}
在 Activity 中,因为视图应启动保存和恢复调用。
public class MainActivity extends BaseActivity implements HomeContract.View {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
homePresenter.getViewState().restoreState(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
homePresenter.getViewState().saveState(outState);
}
...
}
还有另一种策略可以保存演示者状态以及 Observable
的状态:retain Fragment
。这样你就省略了将数据保存到 Bundle
中的标准 Android 方法(它只允许保存简单变量而不是网络请求的状态。)
Activity
:
public class MainActivity extends AppCompatActivity implements MainActivityView {
private static final String TAG_RETAIN_FRAGMENT = "retain_fragment";
MainActivityPresenter mPresenter;
private MainActivityRetainFragment mRetainFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
initRetainFragment();
initPresenter();
}
private void initRetainFragment() {
FragmentManager fm = getSupportFragmentManager();
mRetainFragment = (MainActivityRetainFragment) fm.findFragmentByTag(TAG_RETAIN_FRAGMENT);
if (mRetainFragment == null) {
mRetainFragment = new MainActivityRetainFragment();
fm.beginTransaction().add(mRetainFragment, TAG_RETAIN_FRAGMENT).commit();
}
}
private void initPresenter() {
mPresenter = mRetainFragment.getPresenter();
mRetainFragment.retainPresenter(null);
if (mPresenter == null) {
mPresenter = new MainActivityPresenter();
}
mPresenter.attachView(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!isFinishing()) {
mRetainFragment.retainPresenter(mPresenter);
return;
}
mPresenter.detachView();
mPresenter = null;
}
}
保留Fragment
:
public class MainActivityRetainFragment extends Fragment {
private MainActivityPresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void retainPresenter(MainActivityPresenter presenter) {
this.presenter = presenter;
}
public MainActivityPresenter getPresenter() {
return presenter;
}
}
注意 activity 生命周期事件的处理方式。创建 Activity
时,将保留 Fragment
添加到后台堆栈,并在生命周期事件中从后台堆栈恢复。 retain Fragment
没有任何视图,它只是配置更改期间演示者的持有者。注意主要的调用,它可以从 backstack 中恢复完全相同的片段(及其内容):
setRetainInstance(true)
如果您担心内存泄漏:每次恢复演示者时都会恢复演示者的视图:
mPresenter.attachView(this);
所以之前的 Activity
引用被新的替换了。
这里有更多关于这种配置更改处理的信息here