Google Architecture生命周期组件未调用片段生命周期事件

时间:2018-08-23 15:28:03

标签: android android-fragments android-architecture-components

这是我第一次尝试使用带有Fragments的Google Lifecycle Architecture组件。我的应用程序将MVP与BaseViewModel结合使用,以在整个配置更改中持久保存Presenter。

在“我的活动”中,所有活动生命周期事件均由“生命周期”组件按预期提供给演示者;但是,Fragment Presenters的生命周期事件均未调用。

代码时间!

BaseViewModel.java

public final class BaseViewModel<V extends BaseContract.View, P extends BaseContract.Presenter<V>>
        extends ViewModel {

    private P presenter;

    private static final String TAG = "[" + BaseViewModel.class.getSimpleName() + "] ";

    void setPresenter(P presenter) {
        Log.d(APP_TAG, TAG + "setPresenter presenter: " + presenter);
        if (this.presenter == null) {
            this.presenter = presenter;
        }
    }

    P getPresenter() {
        Log.d(APP_TAG, TAG + "getPresenter presenter: " + presenter);

        return this.presenter;
    }

    @Override
    protected void onCleared() {
        Log.d(APP_TAG, TAG + "onCleared ");
        super.onCleared();
        presenter.onPresenterDestroy();
        presenter = null;
    }
}

BaseFragment.java

public abstract class BaseFragment<V extends BaseContract.View, R extends BaseContract.Repository, P extends BaseContract.Presenter<V>>
        extends Fragment implements BaseContract.View {

    private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
    protected P presenter;

    @SuppressWarnings("unchecked")
    @CallSuper
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //Initializes the ViewModel
        BaseViewModel<V, P> viewModel = ViewModelProviders.of(this).get(BaseViewModel.class);

        boolean isPresenterCreated = false;

        if (viewModel.getPresenter() == null) {
            viewModel.setPresenter(initPresenter());
            isPresenterCreated = true;
        }

        presenter = viewModel.getPresenter();
        presenter.attachLifecycle(getLifecycle());
        presenter.attachView((V) this);
        presenter.setRepo(initRepository());

        if (isPresenterCreated) {
            presenter.onPresenterCreated();
        } else {
            //Hacky workaround I don't want to use
            presenter.onPresenterRestored();
        }
    }

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }

    @CallSuper
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        presenter.detachLifecycle(getLifecycle());
        presenter.detachView();
    }

    protected abstract P initPresenter();
    protected abstract R initRepository();

}

BasePresenter.java

public abstract class BasePresenter<V extends BaseContract.View> implements LifecycleObserver, BaseContract.Presenter<V> {

    private Bundle stateBundle;
    private V view;
    private BaseContract.Repository repo;

    @Override
    final public V getView() {
        return view;
    }

    @SuppressWarnings("unchecked")
    @Override
    final public BaseContract.Repository getRepo() {
        return repo;
    }

    @Override
    final public void attachLifecycle(Lifecycle lifecycle) {
        lifecycle.addObserver(this);
    }

    @Override
    final public void detachLifecycle(Lifecycle lifecycle) {
        lifecycle.removeObserver(this);
    }

    @Override
    final public <R extends BaseContract.Repository> void setRepo(R repo) {
        this.repo = repo;
    }

    @Override
    final public void attachView(V view) {
        this.view = view;
    }

    @Override
    final public void detachView() {
        view = null;
    }

    @Override
    final public boolean isViewAttached() {
        return view != null;
    }

    @Override
    final public Bundle getStateBundle() {
        return stateBundle == null
                ? stateBundle = new Bundle()
                : stateBundle;
    }

    @CallSuper
    @Override
    public void onPresenterDestroy() {
        if (stateBundle != null && !stateBundle.isEmpty()) {
            stateBundle.clear();
        }
    }

    @Override
    public void onPresenterCreated() {
        Log.d(APP_TAG, "BasePresenter.OnPresenterCreated");
    }

    @Override
    public void onPresenterRestored() {
        //Hacky
        Log.d(APP_TAG, "BasePresenter.onPresenterRestored");
    }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_START)
    void onStart() {
        if (isViewAttached()) {
            onStartWithAttachedView();
        }
    }

    public void onStartWithAttachedView() {

    }
}

我正在测试的片段: GameSituationsFragment.java

public class GameSituationsFragment extends BaseFragment<GameSituationsContract.View,
        GameSituationsContract.Repository, GameSituationsContract.Presenter>
        implements GameSituationsContract.View {
    @BindView(R.id.gs_prev_session_button)
    ImageView prevSessButton;
    @BindView(R.id.gs_next_session_button)
    ImageView nextSessButton;
    @BindView(R.id.gs_selected_session)
    TextView selectedSessionText;

    private static final String TAG = "[" + GameSituationsFragment.class.getSimpleName() + "] ";

    private InteractionListener interactionListener;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) return;

        if (activity instanceof GameSituationsFragment.InteractionListener) {
            interactionListener = (GameSituationsFragment.InteractionListener) activity;
        } else {
            if (BuildConfig.DEBUG) {
                throw new RuntimeException(activity.toString()
                        + " must implement GameSituationsFragment.InteractionListener");
            } else {
                //Todo what do we want to do?
                Log.e(TAG, activity.toString() + " must implement GameSituationsFragment.InteractionListener");
            }
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof GameSituationsFragment.InteractionListener) {
            interactionListener = (GameSituationsFragment.InteractionListener) context;
        } else {
            if (BuildConfig.DEBUG) {
                throw new RuntimeException(context.toString()
                        + " must implement GameSituationsFragment.InteractionListener");
            } else {
                //Todo what do we want to do?
                Log.e(TAG, context.toString() + " must implement GameSituationsFragment.InteractionListener");
            }
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_game_situations, container, false);
        ButterKnife.bind(this, view);

        return view;
    }

    @Override
    protected GameSituationsContract.Presenter initPresenter() {
        return new GameSituationsPresenter();
    }

    @Override
    protected GameSituationsContract.Repository initRepository() {
        return new GameSituationsRepository();
    }

    public interface InteractionListener{
        void onGsNextSessionClicked();
        void onGsPreviousSessionClicked();
    }
}

最后是片段的演示者: GameSituationsPresenter.java

public class GameSituationsPresenter extends BasePresenter<GameSituationsContract.View> implements GameSituationsContract.Presenter{
    GameSituationsRepository repo;

    private Bundle viewStateBundle = getStateBundle();

    private static final String TAG = "[" + GameSituationsPresenter.class.getSimpleName() + "] ";

    @Override
    public void onPresenterCreated(){
        Log.d(APP_TAG, TAG + "onPresenterCreated");
        repo = (GameSituationsRepository) getRepo();
        ...
        initializeViews();
    }

    @Override
    public void onPresenterRestored() {
        //So hacky
        initializeViews();
    }

    //NOT CALLED
    @OnLifecycleEvent(value = Lifecycle.Event.ON_START)
    protected void onStart(){
        Log.d(APP_TAG, TAG + "onStart");

        if (isViewAttached()) {
        }
    }

    //NOT CALLED
    @OnLifecycleEvent(value = Lifecycle.Event.ON_STOP)
    protected void onStop(){
        if (isViewAttached()) {

        }
    }

    //NOT CALLED
    @OnLifecycleEvent(value = Lifecycle.Event.ON_DESTROY)
    protected void onDestroy() {
        if (isViewAttached()) {
            //Something to do?
        }

        //a little cleanup
        repo = null;
    }

    private void initializeViews(){
        //Do view stuff
    }
}

所以问题是片段是否能够接收生命周期事件,或者我在实现中错过了某些东西?

谢谢。

0 个答案:

没有答案