Android MVP MVVM框架梳理 (一)
Android MVP框架梳理 梳理下Google推荐的MVP MVVM Demo
源码Git地址
- todo‑mvp
- todo‑mvp‑clean
- todo‑mvp‑dagger
- todo‑mvp‑rxjava
- todo‑mvvm‑databinding
- todo‑mvvm‑live
todo‑mvp
todo‑mvp源码Git地址
这个项目中还用到了guava room等框架包 会逐渐梳理出来~
1.MVP简介
MVC是基于MVC模式框架上发展而来的,在Android中代码框架中 大家都会使用MVC模式 MVC在代码中的应用如下:
Modle:对应Bean对象和数据
View:对应XML布局
Control:对应Activity
但是Activity中经常需要处理View的好多逻辑业务,导致Activity业务很臃肿 复杂。MVP 模式可以很好的解决这种问题 使代码结构更清晰 业务更明确 更易于理解阅读
MVP框架职责如下:
Modle:依然对应Bean对象和数据
View:对应Activity Fragment 只做View的展示
Presenter:支持人角色 负责业务逻辑处理
项目包结构如下:
项目类结构如下:
除了util工具类 其余的包都是按照业务逻辑在自己的包中,每个包都符合MVP模式
2.包中功能解释
2.1data包
1.定义了bean对象 Task
2.定义了数据源的接口 TasksDataSource
3.实现了数据仓库接口:本地数据仓库,远程数据仓库
4.实现综合数据仓库TasksRepository 里边有本地和远程的数据仓库的对象 可以实现数据源的不同存储,缓存的功能
2.2addedittask包
addedittask,statistics,taskdetail,tasks里边有事一个MVP模式 只梳理下addedittask中的逻辑 其他包是类似的
AddEditTaskActivity:初始化View层和Presenter层 并实现Presenter和View的绑定
AddEditTaskContract:定义了View和Presenter的接口
AddEditTaskFragment:View层实现了AddEditTaskContract中的View接口
AddEditTaskPresenter :Presenter层 实现了AddEditTaskContract的Presenter接口
2.2.1 AddEditTaskContract.java
定义了View和Presenter的接口
public interface AddEditTaskContract {
interface View extends BaseView<Presenter> {
void showEmptyTaskError();
void showTasksList();
void setTitle(String title);
void setDescription(String description);
boolean isActive();
}
interface Presenter extends BasePresenter {
void saveTask(String title, String description);
void populateTask();
boolean isDataMissing();
}
}
2.2.2 AddEditTaskFragment.java
//实现View层的接口
public class AddEditTaskFragment extends Fragment implements AddEditTaskContract.View {
...
//点击事件交给Presenter层去处理
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.saveTask(mTitle.getText().toString(), mDescription.getText().toString());
}
});
...
//Presenter层处理完逻辑 回调之View层展现
@Override
public void showEmptyTaskError() {
Snackbar.make(mTitle, getString(R.string.empty_task_message), Snackbar.LENGTH_LONG).show();
}
@Override
public void showTasksList() {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
}
2.2.3 AddEditTaskPresenter.java
//实现Presenter的接口
public class AddEditTaskPresenter implements AddEditTaskContract.Presenter,
TasksDataSource.GetTaskCallback {
//处理View层发送来的请求
@Override
public void saveTask(String title, String description) {
if (isNewTask()) {
createTask(title, description);
} else {
updateTask(title, description);
}
}
private void updateTask(String title, String description) {
if (isNewTask()) {
throw new RuntimeException("updateTask() was called but task is new.");
}
//交于综合数据仓库去处理数据
mTasksRepository.saveTask(new Task(title, description, mTaskId));
//处理完后回调View层展示处理结果
mAddTaskView.showTasksList(); // After an edit, go back to the list.
}
}
2.2.4 AddEditTaskActivity.java
初始化View层和Presenter层 并实现Presenter和View的绑定
//初始化View层
if (addEditTaskFragment == null) {
addEditTaskFragment = AddEditTaskFragment.newInstance();
}
boolean shouldLoadDataFromRepo = true;
// Prevent the presenter from loading data from the repository if this is a config change.
if (savedInstanceState != null) {
// Data might not have loaded when the config change happen, so we saved the state.
shouldLoadDataFromRepo = savedInstanceState.getBoolean(SHOULD_LOAD_DATA_FROM_REPO_KEY);
}
//初始化View层和Presenter层 并实现Presenter和View的绑定
mAddEditTaskPresenter = new AddEditTaskPresenter(
taskId,
Injection.provideTasksRepository(getApplicationContext()),
addEditTaskFragment,
shouldLoadDataFromRepo);
2.2.5 TasksDataSource 数据处理相关的
private void updateTask(String title, String description) {
if (isNewTask()) {
throw new RuntimeException("updateTask() was called but task is new.");
}
//交于综合数据仓库去处理数据
mTasksRepository.saveTask(new Task(title, description, mTaskId));
//处理完后回调View层展示处理结果
mAddTaskView.showTasksList(); // After an edit, go back to the list.
}
/**
* 综合数据仓储处理
* TasksRepository.java
* @param task
*/
@Override
public void saveTask(@NonNull Task task) {
checkNotNull(task);
//远程数据仓储处理
mTasksRemoteDataSource.saveTask(task);
//本地数据仓储处理
mTasksLocalDataSource.saveTask(task);
// 加入本地缓存
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.put(task.getId(), task);
}
/**
* 本地数据存储
* 因为操作数据库需要放在非UI线程处理
* TasksLocalDataSource.java
* @param task
*/
@Override
public void saveTask(@NonNull final Task task) {
checkNotNull(task);
//启动线程 在非UI进程进行数据库操作
Runnable saveRunnable = new Runnable() {
@Override
public void run() {
mTasksDao.insertTask(task);
}
};
mAppExecutors.diskIO().execute(saveRunnable);
}
/**
* 远程数据操作处理
* 此处代码为模拟的
* TasksRemoteDataSource.java
*
* @param task
*/
@Override
public void saveTask(@NonNull Task task) {
TASKS_SERVICE_DATA.put(task.getId(), task);
}