sockeqwe / mosby

A Model-View-Presenter / Model-View-Intent library for modern Android apps
http://hannesdorfmann.com/mosby/
Apache License 2.0
5.49k stars 841 forks source link

How use ViewState in Activity when rotate screen? #286

Closed alexei-28 closed 6 years ago

alexei-28 commented 6 years ago

app/build.gradle:

implementation 'com.hannesdorfmann.mosby3:mvp:3.1.0'
implementation 'com.hannesdorfmann.mosby3:viewstate:3.1.0'

I have activity that show pdf file. Also on top and bottom show 2 containers with icons. When click on pdf then both containers are hide. When click again then both containers show again. And so on.

When containers are not visible and I rotate phone than containers show. But they MUST be hide. So to solve this problem I must use ViewState. Method that show/hide container in activity are: showTopAndBottomContainer()/hideTopAndBottomContainer() Here code:

public interface OfferDetailsView extends MvpView {
    public void showTopAndBottomContainer();
    public void hideTopAndBottomContainer();
}

public interface OfferDetailsPdfMvp {
     interface View extends OfferDetailsView {
        public void openLocalPdfFile(File file, int pageNumber);
    }
    interface Presenter<V extends MvpView> extends OfferDetailsPresenter<V> {
        public void onPageScrolled(int page, int pageCount);
    }
}

Here my custom activity:

public class OfferDetailsPdfActivity extends MvpViewStateActivity<OfferDetailsPdfMvp.View, OfferDetailsPdfPresenterImplMvp, OfferDetailsPdfViewState>
implements OnPageChangeListener, OfferDetailsPdfMvp.View {

@NonNull
    @Override
    public OfferDetailsPdfPresenterImplMvp createPresenter() {
        presenter = new OfferDetailsPdfPresenterImplMvp(this, offerId);
        return presenter;
}

@OnClick(R.id.pdfView)
    public void onClickPdfView() {
        presenter.onClickScreen(offerDetailsToolBarMainContainer.getVisibility() == View.VISIBLE);
    }

@Override
    public void showTopAndBottomContainer() {
        offerDetailsToolBarMainContainer.setVisibility(View.VISIBLE);
        offerBottomContainer.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideTopAndBottomContainer() {
        offerDetailsToolBarMainContainer.setVisibility(View.GONE);
        offerBottomContainer.setVisibility(View.GONE);
    }

    @NonNull
    @Override
    public OfferDetailsPdfViewState createViewState() {
        return new OfferDetailsPdfViewState();
    }

    @Override
    public void onNewViewStateInstance() {
        presenter.viewIsReady();
    }
}

Here my presenter: (I show only method that call when click on pdf)

public class OfferDetailsPdfPresenterImplMvp extends MvpBasePresenter<OfferDetailsPdfMvp.View> implements OfferDetailsPdfMvp.Presenter<OfferDetailsPdfMvp.View> {

@Override
    public void onClickScreen(boolean isVisibleTopContainer) {
        if (isVisibleTopContainer) {
            ifViewAttached(OfferDetailsView::hideTopAndBottomContainer);
        } else {
            ifViewAttached(OfferDetailsView::showTopAndBottomContainer);
        }
}
}

Here my custom ViewState:

public class OfferDetailsPdfViewState implements RestorableViewState<OfferDetailsPdfMvp.View> {
    private boolean isshowTopAndBottomContainer;
    private final static String iS_SHOW_TOP_AND_BOTTOM_CONTAINER = OfferDetailsPdfViewState.class.getName() + "_iS_SHOW_TOP_AND_BOTTOM_CONTAINER";

    public void setIsshowTopAndBottomContainer(boolean isshowTopAndBottomContainer) {
        this.isshowTopAndBottomContainer = isshowTopAndBottomContainer;
    }

    @Override
    public void saveInstanceState(@NonNull Bundle out) {
        out.putBoolean(iS_SHOW_TOP_AND_BOTTOM_CONTAINER, isshowTopAndBottomContainer);
    }

    @Override
    public RestorableViewState<OfferDetailsPdfMvp.View> restoreInstanceState(Bundle in) {
        return this;
    }

    @Override
    public void apply(OfferDetailsPdfMvp.View view, boolean retained) {
        if (isshowTopAndBottomContainer) {
            view.showTopAndBottomContainer();
        } else {
            view.hideTopAndBottomContainer();
        }
    }
}

OK. Method apply() is success call. The question is : How I need restore state in the Activity when rotate phone? What I need to edit in my activity?

sockeqwe commented 6 years ago

So basically, whenever you call a method of your View Interface like view.showTopAndBottomContainer(), the implementation of that method has to set the view state accordingly.

For example:

class OfferDetailsViewPdfActivity ... {

   @Override
    public void hideTopAndBottomContainer() {
        getViewState(). setIsshowTopAndBottomContainer(false);
        offerDetailsToolBarMainContainer.setVisibility(View.GONE);
        offerBottomContainer.setVisibility(View.GONE);
    }
}

Also, in your ViewState you have to read the data from your bundle. I assume isshowTopAndBottomContainer = bundle.getBoolean(iS_SHOW_TOP_AND_BOTTOM_CONTAINER)

Hope that helps. For more information take a look at the documentation: http://hannesdorfmann.com/mosby