MVP和RxJava - 在Android上处理屏幕旋转

6

我正在使用类似于google-samples仓库的MVP和RxJava。

我想问如何正确处理屏幕方向的变化。

2个回答

8

还有一种策略可以保存演示者状态和Observable的状态:保留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时,会将保留的Fragment添加到后退栈中,并在生命周期事件上从后退栈中恢复它。保留的Fragment没有任何视图,它只是在配置更改期间持有Presenter的容器。请注意,启用从后退栈完全恢复相同的片段(及其内容)的主要调用:

setRetainInstance(true)

如果您关注内存泄漏:每次恢复Presenter时,Presenter的视图也会被恢复:

mPresenter.attachView(this);

因此,先前的Activity引用被新的引用所替代。

有关如何处理配置更改的更多信息,请参见此处


1

我通过在Presenter中封装视图状态到特定的ViewState类中来处理,这样很容易进行测试。

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;
    }
}

从视图状态中获取/设置值在Presenter中,这有助于保持更新,并使Presenter无状态化。
public class HomePresenter implements HomeContract.Presenter {

    private HomeViewState viewState;

    HomeViewState getViewState() {
        return viewState;
    }

    @Override
    public void loadComic() {
       loadComic(viewState.getComicNumber());
    }
    ...
}

在Activity中,作为View的应该调用保存和恢复。
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保存到Bundle中是否可行? - MobileDev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接