android mvp官方,MVP之Android官方MVP架构学习—Model层

一、Model层结构

Model层类位于data包下,组织结构如图:

model.jpg

二、Model层分析

1. 实体类

Tasks作为实体类,定义的属性和方法,具体可以查看代码

2. 接口

TasksDataSource定义了Model的回调接口和方法

public interface TasksDataSource {

interface LoadTasksCallback {

void onTasksLoaded(List tasks);

void onDataNotAvailable();

}

interface GetTaskCallback {

void onTaskLoaded(Task task);

void onDataNotAvailable();

}

void getTasks(@NonNull LoadTasksCallback callback);

void getTask(@NonNull String taskId, @NonNull GetTaskCallback callback);

void saveTask(@NonNull Task task);

void completeTask(@NonNull Task task);

void completeTask(@NonNull String taskId);

void activateTask(@NonNull Task task);

void activateTask(@NonNull String taskId);

void clearCompletedTasks();

void refreshTasks();

void deleteAllTasks();

void deleteTask(@NonNull String taskId);

}

3.实现类

3.1 TasksLocalDataSource

TasksLocalDataSource是TasksDataSource的本地数据源实现类,用于从本地数据库获取数据,采用单例模式,并且有两个帮助类TasksDbHelper和TasksPersistenceContract用于从操作数据库

3.1 TasksRemoteDataSource

TasksRemoteDataSource是TasksDataSource的远程数据源实现类,用于从服务端获取数据(demo里只是模仿从服务端获取),采用单例模式

3.1 TasksRepository

Repository也是TasksDataSource的实现类,其中持有两个两个TasksDataSource对象,一般为一个TasksLocalDataSource对象和一个TasksRemoteDataSource对象,用于统一管理获取数据的方式,采用单例模式

public class TasksRepository implements TasksDataSource {

private static TasksRepository INSTANCE = null;

// 远程数据源对象

private final TasksDataSource mTasksRemoteDataSource;

// 本地数据源对象

private final TasksDataSource mTasksLocalDataSource;

// 存放缓存数据

Map mCachedTasks;

// 缓存数据是否可用

boolean mCacheIsDirty = false;

// 构造方法

private TasksRepository(@NonNull TasksDataSource tasksRemoteDataSource,

@NonNull TasksDataSource tasksLocalDataSource) {

mTasksRemoteDataSource = checkNotNull(tasksRemoteDataSource);

mTasksLocalDataSource = checkNotNull(tasksLocalDataSource);

}

// 获取TasksRepository实例,采用单例模式

public static TasksRepository getInstance(TasksDataSource tasksRemoteDataSource,

TasksDataSource tasksLocalDataSource) {

if (INSTANCE == null) {

INSTANCE = new TasksRepository(tasksRemoteDataSource, tasksLocalDataSource);

}

return INSTANCE;

}

public static void destroyInstance() {

INSTANCE = null;

}

// 获取数据

@Override

public void getTasks(@NonNull final LoadTasksCallback callback) {

checkNotNull(callback);

// 如果缓存可用,则立即返回内存中的数据

if (mCachedTasks != null && !mCacheIsDirty) {

callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));

return;

}

if (mCacheIsDirty) {

// 如果缓存数据已经不可用,则从服务端更新数据

getTasksFromRemoteDataSource(callback);

} else {

// 从数据库获取数据,如果没有,则从服务端获取

mTasksLocalDataSource.getTasks(new LoadTasksCallback() {

@Override

public void onTasksLoaded(List tasks) {

refreshCache(tasks);

callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));

}

@Override

public void onDataNotAvailable() {

getTasksFromRemoteDataSource(callback);

}

});

}

}

// 从服务端获取数据

private void getTasksFromRemoteDataSource(@NonNull final LoadTasksCallback callback) {

mTasksRemoteDataSource.getTasks(new LoadTasksCallback() {

@Override

public void onTasksLoaded(List tasks) {

refreshCache(tasks);

refreshLocalDataSource(tasks);

callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));

}

@Override

public void onDataNotAvailable() {

callback.onDataNotAvailable();

}

});

}

}

可以看到,在实例化TasksRepository时需要传入两个TasksDataSource对象;在获取数据时先从缓存中获取,如果缓存中没有,则从数据库获取,数据库没有,再从服务端获取,若为强制刷新,则直接从服务端获取。

三、Model使用

1.TasksDataSource的实例化

在MVP中,Presenter对象持有Model对象,如:

public class AddEditTaskPresenter implements AddEditTaskContract.Presenter,

TasksDataSource.GetTaskCallback {

// TasksDataSource对象

@NonNull

private final TasksDataSource mTasksRepository;

// 实例化时传入TasksDataSource对象

public AddEditTaskPresenter(@Nullable String taskId, @NonNull TasksDataSource tasksRepository,

@NonNull AddEditTaskContract.View addTaskView) {

mTaskId = taskId;

mTasksRepository = checkNotNull(tasksRepository);

mAddTaskView = checkNotNull(addTaskView);

mAddTaskView.setPresenter(this);

}

}

Presenter在实例化是需要传入TasksDataSource对象,Presenter是在Activity中完成实例化的

public class AddEditTaskActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.addtask_act);

...

// 实例化Presenter,传入TasksDataSource对象

new AddEditTaskPresenter(

taskId,

Injection.provideTasksRepository(getApplicationContext()),

addEditTaskFragment);

}

}

可以看到TasksDataSource对象是由Injection类的provideTasksRepository方法生成

2.Gradle动态配置

在main/java目中并没有Injection类,通过查看app/build.gradle文件可以知道,项目有两个生产版本:mock和prod,如下:

productFlavors {

mock {

applicationIdSuffix = ".mock"

}

prod {

}

}

在项目的目录结构中也有对应的src/mock和src/prod两个目录目录

source_directories.jpg

在mock和prod中�分别有一个Injection类,这里利用了gradle中的productFlavor创建了多个版本,其中每个版本都可以在工程src目录下建立与main同级的文件夹,文件夹名字就是ProductFlavor的名字,可以在其中创建java目录并添加相应的java文件,不用的版本可以有相同名字不同实现的类,具体可查看Android Plugin for Gradle。

prod目录下的Injection

public class Injection {

public static TasksRepository provideTasksRepository(@NonNull Context context) {

checkNotNull(context);

return TasksRepository.getInstance(TasksRemoteDataSource.getInstance(),

TasksLocalDataSource.getInstance(context));

}

}

mock目录下的Injection

public class Injection {

public static TasksRepository provideTasksRepository(@NonNull Context context) {

checkNotNull(context);

return TasksRepository.getInstance(FakeTasksRemoteDataSource.getInstance(),

TasksLocalDataSource.getInstance(context));

}

}

可以看到:

prod的Injection创建TasksRepository实例时传入的是TasksRemoteDataSource实例和TasksLocalDataSource实例

mock的Injection创建TasksRepository实例时传入的是FakeTasksRemoteDataSource实例和TasksLocalDataSource实例,其中FakeTasksRemoteDataSource是在mock目录下创建的TasksDataSource的实现类。

通过这种方式可以实现不同版本注入不同的TasksDataSource实现类。

你可能感兴趣的:(android,mvp官方)