这是我第一次使用Fragments处理Google Lifecycle Architecture组件 . 我的应用程序使用带有BaseViewModel的MVP来保持Presenter跨配置更改 .
在我的活动中,按照Lifecycle组件的预期,为Presenter调用所有Activity生命周期事件;但是,没有任何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
}
}
所以问题是能够接收生命周期事件的片段还是我在实现中遗漏了什么?
提前致谢 .