package nucleus.presenter;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* This is a base class for all presenters. Subclasses can override
* {@link #onCreate}, {@link #onDestroy}, {@link #onSave},
* {@link #onTakeView}, {@link #onDropView}.
* <p/>
* {@link Presenter.OnDestroyListener} can also be used by external classes
* to be notified about the need of freeing resources.
*
* @param <View> a type of view to return with {@link #getView()}.
*/
public class Presenter<View> {
@Nullable
private View view;
private CopyOnWriteArrayList<OnDestroyListener> onDestroyListeners = new CopyOnWriteArrayList<>();
/**
* This method is called after presenter construction.
*
* This method is intended for overriding.
*
* @param savedState If the presenter is being re-instantiated after a process restart then this Bundle
* contains the data it supplied in {@link #onSave}.
*/
protected void onCreate(@Nullable Bundle savedState) {
}
/**
* This method is being called when a user leaves view.
*
* This method is intended for overriding.
*/
protected void onDestroy() {
}
/**
* A returned state is the state that will be passed to {@link #onCreate} for a new presenter instance after a process restart.
*
* This method is intended for overriding.
*
* @param state a non-null bundle which should be used to put presenter's state into.
*/
protected void onSave(Bundle state) {
}
/**
* This method is being called when a view gets attached to it.
* Normally this happens during {@link Activity#onResume()}, {@link Fragment#onResume()}
* and {@link android.view.View#onAttachedToWindow()}.
*
* This method is intended for overriding.
*
* @param view a view that should be taken
*/
protected void onTakeView(View view) {
}
/**
* This method is being called when a view gets detached from the presenter.
* Normally this happens during {@link Activity#onPause()} ()}, {@link Fragment#onDestroyView()}
* and {@link android.view.View#onDetachedFromWindow()}.
*
* This method is intended for overriding.
*/
protected void onDropView() {
}
/**
* A callback to be invoked when a presenter is about to be destroyed.
*/
public interface OnDestroyListener {
/**
* Called before {@link Presenter#onDestroy()}.
*/
void onDestroy();
}
/**
* Adds a listener observing {@link #onDestroy}.
*
* @param listener a listener to add.
*/
public void addOnDestroyListener(OnDestroyListener listener) {
onDestroyListeners.add(listener);
}
/**
* Removed a listener observing {@link #onDestroy}.
*
* @param listener a listener to remove.
*/
public void removeOnDestroyListener(OnDestroyListener listener) {
onDestroyListeners.remove(listener);
}
/**
* Returns a current view attached to the presenter or null.
*
* View is normally available between
* {@link Activity#onResume()} and {@link Activity#onPause()},
* {@link Fragment#onResume()} and {@link Fragment#onPause()},
* {@link android.view.View#onAttachedToWindow()} and {@link android.view.View#onDetachedFromWindow()}.
*
* Calls outside of these ranges will return null.
* Notice here that {@link Activity#onActivityResult(int, int, Intent)} is called *before* {@link Activity#onResume()}
* so you can't use this method as a callback.
*
* @return a current attached view.
*/
@Nullable
public View getView() {
return view;
}
/**
* Initializes the presenter.
*/
public void create(Bundle bundle) {
onCreate(bundle);
}
/**
* Destroys the presenter, calling all {@link Presenter.OnDestroyListener} callbacks.
*/
public void destroy() {
for (OnDestroyListener listener : onDestroyListeners)
listener.onDestroy();
onDestroy();
}
/**
* Saves the presenter.
*/
public void save(Bundle state) {
onSave(state);
}
/**
* Attaches a view to the presenter.
*
* @param view a view to attach.
*/
public void takeView(View view) {
this.view = view;
onTakeView(view);
}
/**
* Detaches the presenter from a view.
*/
public void dropView() {
onDropView();
this.view = null;
}
}