This snippet of code is extracted for Google's sample of MPV for Android. https://github.com/googlesamples/android-architecture/tree/todo-mvp/
-Then it's time for the Contract which is resposible for all the communication between the Presenter and the View and we create one for each module , for the presenter part it contains all the functionalilty it will handle like responding for specific event from the view and then excutes some bussnies logic or fetching data and the triggers the view callback which will be written in the View Contract part , "TasksContract".
-The Repository class is the part in our implementation that is resposiple of getting and fetching the data from any data-source in our app eg. webservice , local database and send it to presenter to handle the logic on it and update the view UI
-Then we create our Presenter class which implements our Contract Presenter with it's functions , see "TasksPresenter" class for as an example
-Next is the View part it's usually an Activity or a Fragment in our case of MVP we prefer Fragment inside Activity The use of both activities and fragments allows for a better separation of concerns which compliments this implementation of MVP. In this version of the app, the Activity is the overall controller which creates and connects views and presenters. The use of fragments supports tablet layouts or UI screens with multiple views:-
In our activity we got a refrence for the view and then we intialize the fragment and attach it to the presenter see "TasksActivity" class for more details.
In the Fragment we implement the View interface in our contract and we create a refrence of our Presenter Class then we intialize it using the setPresenter implemented method and we fire the start() method in the Fragment onResume to start the first task related to our lifecycle.
At anythime we could trigger the presenter functions using it's refrence
public class TasksFragment extends Fragment implements TasksContract.View {
// our refrence of the presenter
private TasksContract.Presenter mPresenter;
//triggering a presenter function based on the fragment lifecycle
@Override
public void onResume() {
super.onResume();
mPresenter.start();
}
//initializing the presenter from the method we impelmented from the Contract.View after the Presenter
//class triggered this function
@Override
public void setPresenter(@NonNull TasksContract.Presenter presenter) {
mPresenter = checkNotNull(presenter);
}
//at anytime we could trigger any function of the presenter class using it's instance eg.
mPresenter.completeTask(completedTask);
}
public class TasksActivity extends AppCompatActivity {
private TasksPresenter mTasksPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tasks_act);
TasksFragment tasksFragment =
(TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (tasksFragment == null) {
// Create the fragment
tasksFragment = TasksFragment.newInstance();
ActivityUtils.addFragmentToActivity(
getSupportFragmentManager(), tasksFragment, R.id.contentFrame);
}
// Create the presenter and attach it to our View (Fragment)
mTasksPresenter = new TasksPresenter(
Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
}
}
public class TasksPresenter implements TasksContract.Presenter {
//refrence for the repository that is resposible for fetching the model data from any datasource
private final TasksRepository mTasksRepository;
//refrence of the View to trigger the functions after proccessing the task
private final TasksContract.View mTasksView;
// Presenter's Constructor the intialize the view attached to it
//and the repository and setting the view to this Presenter
public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");
mTasksView.setPresenter(this);
}
//triggring a method based on the view lifecycle
@Override
public void start() {
loadTasks(false);
}
//anytime we want to trigger a function inside our view we use our view refrence eg.
mTasksView.showSuccessfullySavedMessage();
}
public interface TasksContract {
interface Presenter extends BasePresenter {
//the presenter functions that will be triggered from the view
//eg. Bussines logic or fetching data from the backend
//based on the user actions or a View Lifecycle.
void result(int requestCode, int resultCode);
void loadTasks(boolean forceUpdate);
void addNewTask();
void openTaskDetails(@NonNull Task requestedTask);
void completeTask(@NonNull Task completedTask);
void activateTask(@NonNull Task activeTask);
void clearCompletedTasks();
void setFiltering(TasksFilterType requestType);
TasksFilterType getFiltering();
}
//this presenter between <Presenter> is what we just declared in the above interface
interface View extends BaseView<Presenter> {
//triggered functions from the presenter to update the UI
void setLoadingIndicator(boolean active);
void showTasks(List<Task> tasks);
void showAddTask();
void showTaskDetailsUi(String taskId);
void showTaskMarkedComplete();
void showTaskMarkedActive();
void showCompletedTasksCleared();
void showLoadingTasksError();
void showNoTasks();
void showActiveFilterLabel();
void showCompletedFilterLabel();
void showAllFilterLabel();
void showNoActiveTasks();
void showNoCompletedTasks();
void showSuccessfullySavedMessage();
boolean isActive();
void showFilteringPopUpMenu();
}
}
public interface BaseView<T> {
void setPresenter(T presenter);
}
public interface BasePresenter {
void start();
}