问题描述
我正在使用Mosby MVP库开发一个Android应用.在一个特定的Fragment中,ViewState已实现但未使用(状态未更改或其他任何东西).一些视图逻辑是由widgetManager实现的.我正确地更改了状态,但是行为却很奇怪:在屏幕方向上,在viewState apply()
之后调用createViewState()
和onNewViewStateInstance()
:这取消了恢复视图状态和相关行为的操作.
I'm working on an Android app using Mosby MVP library. In one specific Fragment, the ViewState was implemented but not used (the state wasn't changed or anything). Some of the view logic is implemented by widgetManager. I made the state change correctly but the behavior is weird : on screen orientation, createViewState()
and onNewViewStateInstance()
are called after the viewState apply()
: which cancels restoring the viewstate and related behaviors.
你知道为什么会这样吗?
Do you have any idea why this is happening ?
我已经将ViewState实现为RestorableParcelableViewState
,但是发生了同样的事情.
I've implemented the ViewState as a RestorableParcelableViewState
but the same thing happens.
调试后:循环进行:onSaveInstanceState(片段),saveInstanceState(视图状态),onViewCreated(f),应用(vs),[正确的行为,然后],createViewState(f),onCreate(f),createPresenter(f ),onViewCreated(f),一切都再次为null,然后重新启动,就好像该片段是使用null savedInstanceState创建的.
After debugging : the cycle goes : onSaveInstanceState (fragment), saveInstanceState (viewstate), onViewCreated (f), apply (vs), [correct behavior but then], createViewState (f), onCreate (f), createPresenter (f), onViewCreated (f) and there everything is null again and restarts as if the fragment just got created with a null savedInstanceState.
这是片段的核心:
public class DashboardFragment extends AuthViewStateFragment<DashboardView,
DashboardPresenter> implements WidgetHolderView, FragmentSupportBack, DashboardView {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
protected void injectDependencies() { // called in onViewCreated
super.injectDependencies();
presenter = new DashboardPresenter(dataService, getContext());
}
@Override
public ViewState createViewState() {
return new DashboardViewState();
}
@Override
public void onNewViewStateInstance() {
widgetManager.bindToWidgetHolderView(this, dashboardType, dashboardId);
presenter.onNewInstance();
}
@Override
public DashboardPresenter createPresenter() {
return presenter;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
@Override
public void showLoading() {
((DashboardViewState) viewState).showSpinnerLoading();
loadingView.setVisibility(View.VISIBLE);
}
@Override
public void showContent() {
((DashboardViewState) viewState).showSpinner();
adapter.notifyDataSetChanged();
loadingView.setVisibility(View.GONE);
}
@Override
public void showError(String error) {
((DashboardViewState) viewState).showSpinnerError(new Throwable(error));
errorView.setVisibility(View.VISIBLE);
loadingView.setVisibility(View.GONE);
}
@Override
public void scrollList(List<Widget> widgets) {
((DashboardViewState) viewState).showSpinner();
((DashboardViewState) viewState).setData(widgets, widgetManager.getFeeder());
// scroll to widget
}
@Override
public void onStart() {
super.onStart();
adapter.resubscribeWidgetToFeeder();
}
@Override
public void onStop() {
adapter.unsubscribeWidgetFromFeeder();
super.onStop();
}
@Override
public void onDestroyView() {
adapter.flushReferencesToWidgetViews();
super.onDestroyView();
}
@Override
public void showSpinnerError(Throwable error) {
((DashboardViewState) viewState).showSpinnerError(new Throwable(error));
// show error
}
@Override
public void showSpinnerLoading() {
((DashboardViewState) viewState).showSpinnerLoading();
// Display loading icon for the spinner
}
@Override
public void setDashboardList(List<Dashboard> dashboardList) {
// Set DashboardList
this.dashboardList = dashboardList;
((MainActivity)getActivity()).setDashboardList(dashboardList);
}
@Override
public void showSpinner() {
((DashboardViewState) viewState).showSpinner();
// show spinner
spinner.setOnItemSelectedListener(selectedListener);
setSelectedDatacenter(DatacenetrUtils.datacenterId);
}
@Override
public void setData(List<Widget> widgets, Feeder feeder) {
widgetManager.setWidgets(widgets);
widgetManager.setFeeder(feeder);
adapter.setFeeder(widgetManager.getFeeder());
adapter.notifyDataSetChanged();
}
}
视图状态:
class DashboardViewState implements ViewState<DashboardView> {
private int state = LOADING;
private Throwable t;
private List<Widget> widgets;
private Feeder feeder;
@Override
public void apply(DashboardView view, boolean retained) {
switch (state) {
case LOADING:
view.showSpinnerLoading();
break;
case CONTENT:
view.showSpinner();
view.setData(widgets, feeder);
break;
case ERROR:
view.showSpinnerError(t);
break;
}
}
public void showSpinnerLoading() {
state = LOADING;
}
public void showSpinner() {
state = CONTENT;
}
public void setData(List<Widget> widgets, Feeder feeder) {
setWidgets(widgets);
setFeeder(feeder);
}
public void setWidgets(List<Widget> widgets) {
this.widgets = widgets;
}
public void setFeeder(Feeder feeder) {
this.feeder = feeder;
}
public void showSpinnerError(Throwable t) {
this.t = t;
state = ERROR;
}
}
演示者:
public class DashboardPresenter
extends Mvp2RxPresenter<DashboardView, List<Dashboard>> {
private final DataService dataService;
private final Context context;
public DashboardPresenter(DataService dataService, Context context) {
this.dataService = dataService;
this.context = context;
}
public void onNewInstance() {
if (isViewAttached())
getView().showSpinnerLoading();
if (isViewAttached()) getView().showSpinnerLoading();
subscribe(dataService.getDatacenters()
.concatMap(Observable::from)
.map(this::datacenterToDashboard)
.startWith(dataService.getCurrentUser()
.map(user -> {
Dashboard dashboard = new Dashboard (context.getString(R.string.dashboard_personalDashboard));
return dashboard;
}))
.toList()
, 0);
}
@Override
protected void onNext(List<Dashboard> data, int pr) {
if (isViewAttached()) {
getView().setDashboardList(data);
}
}
@Override
protected void onError(Throwable e, int pr) {
if (isViewAttached()) getView().showSpinnerError(e);
}
@Override
protected void onCompleted(int pr) {
if (isViewAttached()) getView().showSpinner();
}
}
推荐答案
我认为您不小心在活动"中的每个方向更改上添加了新的DashboardFragment
,不是吗?
I think you are accidentally adding a new DashboardFragment
on each orientation change in your Activity, don't you?
根据您的日志,在还原原始片段之后,将再次调用诸如Fragment.onCreate()
之类的片段生命周期事件.这强烈表明您正在创建一个全新的DashboardFragment
并将其替换为上一个.
According to your logs fragment lifecycle events like Fragment.onCreate()
are called again after the original fragment has been restored. This strongly indicates that you are creating an entirely new DashboardFragment
and replace it with the previous one.
您是否做过类似的事情:
Do you do something like:
class MyActivity extends Activity {
public void onCreate(Bundle saved){
super.onCreate(saved);
if (saved == null) )
// Ensures that you only add one fragment the very first time the Activity starts
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, new DashboardFragment())
.commit();
}
}
}
请检查您是否有这样的如果活动首次开始则添加片段".您也可以在DashboardFragment.onCreateView()
处添加断点,然后启动调试器并旋转设备.我认为您会看到DashboardFragment
的两个不同实例.
Please check if you have such a "Add fragment if activity starts for the first time". Also you can add a break point to DashboardFragment.onCreateView()
and then start the debugger and rotate your device. I think that you will see that there are 2 different instances of DashboardFragment
.
这篇关于MvpViewStateFragment无法在屏幕方向上还原ViewState的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!