MvpViewStateFragment 不在屏幕方向上恢复 ViewState

MvpViewStateFragment not restoring ViewState on screen orientation

我正在使用 Mosby MVP 库开发 Android 应用程序。在一个特定的 Fragment 中,ViewState 已实现但未使用(状态未更改或其他任何内容)。部分视图逻辑由 widgetManager 实现。我正确地改变了状态,但行为很奇怪:在屏幕方向上,createViewState()onNewViewStateInstance() 在 vi​​ewState apply() 之后被调用:这取消了恢复视图状态和相关行为。

你知道为什么会这样吗?

我已经将 ViewState 实现为 RestorableParcelableViewState 但同样的事情发生了。

调试后:循环进行:onSaveInstanceState (fragment)、saveInstanceState (viewstate)、onViewCreated (f)、apply (vs)、[正确行为但随后]、createViewState (f)、onCreate (f)、createPresenter (f),onViewCreated (f),然后一切再次为空并重新启动,就好像刚刚使用空 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();
    }
}

我认为您不小心在 Activity 的每个方向变化中添加了一个新的 DashboardFragment,是吗?

根据您的日志,Fragment.onCreate() 等片段生命周期事件会在原始片段恢复后再次调用。这强烈表明您正在创建一个全新的 DashboardFragment 并将其替换为之前的

你会做这样的事情吗:

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

请检查您是否有这样的"Add fragment if activity starts for the first time"。您也可以向 DashboardFragment.onCreateView() 添加一个断点,然后启动调试器并旋转您的设备。我认为您会看到 DashboardFragment.

有 2 个不同的实例