2017-02-21 7 views
1

Mosby MVP 라이브러리를 사용하는 Android 앱에서 작업하고 있습니다. 하나의 특정 Fragment에서 ViewState가 구현되었지만 사용되지 않았습니다 (상태가 변경되지 않았거나 아무것도 아닙니다). 일부 뷰 로직은 widgetManager에 의해 구현됩니다. 상태를 올바르게 변경했지만 동작이 이상하게 나타났습니다. 화면 방향에서 및 onNewViewStateInstance()이 호출되면 viewState apply() 다음에 호출되며 viewstate 및 관련 동작을 취소합니다.MvpViewStateFragment가 화면 방향에서 ViewState를 복원하지 않습니다.

왜 이런 일이 발생하는지 알고 있습니까?

ViewState를 RestorableParcelableViewState으로 구현했지만 동일한 문제가 발생합니다.

디버깅 후 : onSaveInstanceState (조각), saveInstanceState (viewstate), onViewCreated (f), apply (vs), [올바른 동작은 아니지만], createViewState (f), onCreate (f), createPresenter f), onViewCreated (f) 그리고 거기에 모든 것이 다시 null이고 프래그먼트가 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(); 
    } 
} 

viewstate가 :

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

사용중인 mosby 버전은 무엇입니까? 그 프로젝트가 오픈 소스에서 작업하고 있으므로 구체적인 코드를 살펴볼 수 있습니까? – sockeqwe

+0

2.0.0 그러나 개선없이 2.0.1로 변경하려고했습니다. 아니요, 오픈 소스가 아닙니다. 당신이 찾고있는 것을 알고 있다면, 나에게 묻기를 망설이지 말고, 아직 해결되지 않았습니다. – Kapouter

답변

1

내가 실수 각각의 새로운 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(); 
     } 
    } 
} 

확인하시기 바랍니다 :

당신이 그런 짓을합니까. 또한 DashboardFragment.onCreateView()에 중단 점을 추가 한 다음 디버거를 시작하고 장치를 회전 할 수 있습니다. 나는 당신이 DashboardFragment의 2 개의 다른 경우가 있다는 것을 볼 것이라고 생각합니다.

+0

체크 표시를하면 조각이 작업에서 복원되고 다시 만들어지지 않습니다. 그러나 실제로, 실제로 일어나는 일에서 조각이 다시 만들어집니다. 나는 왜 또는 어떻게 ... 모스비와 연결되어 있지 않을지 모른다. – Kapouter

+0

Mosby가 내부적으로'FragmentManager' 등을 사용하지 않았기 때문에 모스비가 원인이 아니라는 것을 확신합니다. 확실히 Fragments를 어떻게 든 추가하지 않습니다. – sockeqwe

+0

정보 주셔서 감사합니다 :) – Kapouter