diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/BaseFragment.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/BaseFragment.java index a312d134..2cce11bf 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/BaseFragment.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/BaseFragment.java @@ -6,6 +6,9 @@ package com.fernandocejas.android10.sample.presentation.view.fragment; import android.app.Fragment; +import android.os.Bundle; +import android.util.Log; +import android.view.View; import android.widget.Toast; import com.fernandocejas.android10.sample.presentation.internal.di.HasComponent; @@ -13,6 +16,32 @@ * Base {@link android.app.Fragment} class for every fragment in this application. */ public abstract class BaseFragment extends Fragment { + + private boolean mIsInjected = false; + + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + mIsInjected = onInjectView(); + } catch (IllegalStateException e) { + Log.e(e.getClass().getSimpleName(), e.getMessage()); + mIsInjected = false; + } + } + + @Override public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (mIsInjected) onViewInjected(savedInstanceState); + } + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (!mIsInjected) { + mIsInjected = onInjectView(); + if (mIsInjected) onViewInjected(null); + } + } + /** * Shows a {@link android.widget.Toast} message. * @@ -24,9 +53,46 @@ protected void showToastMessage(String message) { /** * Gets a component for dependency injection by its type. + * + * @throws IllegalStateException if component has not been initialized yet. */ @SuppressWarnings("unchecked") - protected C getComponent(Class componentType) { - return componentType.cast(((HasComponent) getActivity()).getComponent()); + protected C getComponent(Class componentType) throws IllegalStateException { + C component = componentType.cast(((HasComponent) getActivity()).getComponent()); + if (component == null) { + throw new IllegalStateException(componentType.getSimpleName() + " has not been initialized yet."); + } + return component; + } + + /** + * Called to do an optional injection. This will be called on {@link #onCreate(Bundle)} and if + * an exception is thrown or false returned, on {@link #onActivityCreated(Bundle)} again. + * Within this method get the injection component and inject the view. Based on returned value + * {@link #onViewInjected(Bundle)} will be called. Check {@link #onViewInjected(Bundle)} + * documentation for more info. + * + * @return True, if injection was successful, false otherwise. Returns false by default. + * @throws IllegalStateException If there is a failure in getting injection component or + * injection process itself. This can occur if activity holding + * component instance has been killed by the system and has not + * been initialized yet. + */ + protected boolean onInjectView() throws IllegalStateException { + // Return false by default. + return false; + } + + /** + * Called when the fragment has been injected and the field injected can be initialized. This + * will be called on {@link #onViewCreated(View, Bundle)} if {@link #onInjectView()} returned + * true when executed on {@link #onCreate(Bundle)}, otherwise it will be called on + * {@link #onActivityCreated(Bundle)} if {@link #onInjectView()} returned true right before. + * + * @param savedInstanceState If non-null, this fragment is being re-constructed + * from a previous saved state as given here. + */ + protected void onViewInjected(Bundle savedInstanceState) { + // Intentionally left empty. } } diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserDetailsFragment.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserDetailsFragment.java index e5c51334..c55867e8 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserDetailsFragment.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserDetailsFragment.java @@ -43,20 +43,20 @@ public UserDetailsFragment() { setRetainInstance(true); } - @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override protected boolean onInjectView() throws IllegalStateException { this.getComponent(UserComponent.class).inject(this); + return true; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { final View fragmentView = inflater.inflate(R.layout.fragment_user_details, container, false); ButterKnife.bind(this, fragmentView); return fragmentView; } - @Override public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + @Override protected void onViewInjected(Bundle savedInstanceState) { + super.onViewInjected(savedInstanceState); this.userDetailsPresenter.setView(this); if (savedInstanceState == null) { this.loadUserDetails(); diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserListFragment.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserListFragment.java index 6da47c9a..e0ead954 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserListFragment.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/fragment/UserListFragment.java @@ -60,21 +60,21 @@ public UserListFragment() { } } - @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override protected boolean onInjectView() throws IllegalStateException { this.getComponent(UserComponent.class).inject(this); + return true; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { final View fragmentView = inflater.inflate(R.layout.fragment_user_list, container, false); ButterKnife.bind(this, fragmentView); - setupRecyclerView(); return fragmentView; } - @Override public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + @Override protected void onViewInjected(Bundle savedInstanceState) { + super.onViewInjected(savedInstanceState); + this.setupRecyclerView(); this.userListPresenter.setView(this); if (savedInstanceState == null) { this.loadUserList();