新的工作已经定了,在上班之前有点事情需要处理下,也趁机休息下,所以好几天没有更新博客了,但是心里还是惦记着今后需要写点什么,感觉还是有很多需要学习,但是接下来会偏向于通过实例来分析架构设计上的一些技术吧。总的来说今天的博客会从如下几方面进行展开:

  1. 开源代码的架构分析
  2. 自定义View + 设计方面的知识 + MD 风格
  3. AOSP源码分析
  4. RectNative + H5
  5. 开源流媒体播放器源码分析
    希望今年能够在架构上有所提高。

好了,转入正题,今天想向大家介绍的是Google Sample发布的android开发中的框架设计例子,完整的源码大家可以在如下链接中下载:
Android Architecture

这里包括:

todo-mvp/ - Basic Model-View-Presenter architecture.
todo-mvp-loaders/ - Based on todo-mvp, fetches data using Loaders.
todo-mvp-databinding/ - Based on todo-mvp, uses the Data Binding Library.
todo-mvp-clean/ - Based on todo-mvp, uses concepts from Clean Architecture.
todo-mvp-dagger/ - Based on todo-mvp, uses Dagger2 for Dependency Injection
todo-mvp-contentproviders/ - Based on todo-mvp-loaders, fetches data using Loaders and uses Content Providers
dev-todo-mvp-rxjava/ - Based on todo-mvp, uses RxJava for concurrency and data layer abstraction.
todo-mvp-fragmentless/ - Based on todo-mvp, uses Android views instead of Fragments.

我们接下来将会一个个对上述代码进行分析,在继续往下看之前建议大家先看下我之前写的MVC,MVP,MVVM的介绍:
这篇博客将会对todo-mvp进行分析,它是后续所有的基础,在介绍之前我们先来看下它的类图:


再和

进行对比下这样会更容易理解整个MVP模式:

下面我们再来看下项目代码是怎么组织的:

addedittask
statistics
taskdetail
tasks

这三个包是并列的分别对应的是添加编辑任务的功能,统计功能,任务详细信息查询功能,任务展现功能,我们这边只以tasks(任务展现功能)功能作为分析对象。

module 层代码位于/data 数据层上使用的是三级缓存:内存级别,本地数据级别,远程网络级别。
View 层代码位于TasksFragment中
Presenter 层代码位于TasksPresenter

TasksContract 是合同类,当中定义了MVP模式中使用到的View和Presenter接口。
TasksActivity创建了View和Presenter
BasePresenter 是所有Presenter的父接口
BaseView 是所有View层的父接口

了解了整个代码结构,大家就可以进行源码分析了。

首先看下BaseView这个接口,所有的View都会实现这个接口,它只有一个方法声明setPresenter,它是用于为View层设置Presenter。

package com.example.android.architecture.blueprints.todoapp;
public interface BaseView<T> {
void setPresenter(T presenter);
}

接着我们同样看下所有Presenter的接口,这里同样也只有一个方法start。

package com.example.android.architecture.blueprints.todoapp;
public interface BasePresenter {
void start();
}

那么这两个接口的作用是什么呢?我们可以在代码中看到所有的Presenter都会实现BasePresenter,所有的类都会实现BaseView。也就是说我们可以将所有的Presenter以及View的公共接口放置在这个地方声明。

我们接下来看下合同类:TasksContract
首先我们需要了解下合同类是用来干嘛的,合同类其实是用于规范View层和Presenter交互接口的类。其中合同类中View接口都是用于操作界面上的控制,Presenter接口基本上是通过Presenter来操作module层。

public interface TasksContract {

interface View extends BaseView<Presenter> {
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();
}

interface Presenter extends BasePresenter {

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();
}
}

介绍了重要的接口后我们看下具体的实现,首先看下TasksActivity:

public class TasksActivity extends AppCompatActivity {

//................
private TasksPresenter mTasksPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//...........................
//创建TaskFragment View
TasksFragment tasksFragment = (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (tasksFragment == null) {
//创建TaskFragment View
tasksFragment = TasksFragment.newInstance();
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), tasksFragment, R.id.contentFrame);
}

// 创建一个Presenter 这个Presenter持有一个Module以及一个TaskFragment这个View
mTasksPresenter = new TasksPresenter(Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
//..........................
}
//..........................
}

上面的逻辑很简单,就是创建一个TaskFragment作为View层。并将其添加到TasksActivity上,然后再创建一个TasksPresenter,TasksPresenter 中持有数据层TasksRepository,以及View层TasksFragment

我们先来看下View层:

public class TasksFragment extends Fragment implements TasksContract.View {

private TasksContract.Presenter mPresenter;

private TasksAdapter mListAdapter;

private View mNoTasksView;

private ImageView mNoTaskIcon;

private TextView mNoTaskMainView;

private TextView mNoTaskAddView;

private LinearLayout mTasksView;

private TextView mFilteringLabelView;

public TasksFragment() {
// Requires empty public constructor
}

public static TasksFragment newInstance() {
return new TasksFragment();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建Adapter
mListAdapter = new TasksAdapter(new ArrayList<Task>(0), mItemListener);
}

@Override
public void onResume() {
super.onResume();
//加载数据
mPresenter.start();
}

@Override
public void setPresenter(@NonNull TasksContract.Presenter presenter) {
//给当前的View设置Presenter
mPresenter = checkNotNull(presenter);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mPresenter.result(requestCode, resultCode);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.tasks_frag, container, false);

// Set up tasks view
ListView listView = (ListView) root.findViewById(R.id.tasks_list);
listView.setAdapter(mListAdapter);
mFilteringLabelView = (TextView) root.findViewById(R.id.filteringLabel);
mTasksView = (LinearLayout) root.findViewById(R.id.tasksLL);

// Set up no tasks view
mNoTasksView = root.findViewById(R.id.noTasks);
mNoTaskIcon = (ImageView) root.findViewById(R.id.noTasksIcon);
mNoTaskMainView = (TextView) root.findViewById(R.id.noTasksMain);
mNoTaskAddView = (TextView) root.findViewById(R.id.noTasksAdd);
mNoTaskAddView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.addNewTask();
}
});

// Set up floating action button
FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab_add_task);

fab.setImageResource(R.drawable.ic_add);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.addNewTask();
}
});

// Set up progress indicator
final ScrollChildSwipeRefreshLayout swipeRefreshLayout = (ScrollChildSwipeRefreshLayout) root.findViewById(R.id.refresh_layout);
swipeRefreshLayout.setColorSchemeColors(
ContextCompat.getColor(getActivity(), R.color.colorPrimary),
ContextCompat.getColor(getActivity(), R.color.colorAccent),
ContextCompat.getColor(getActivity(), R.color.colorPrimaryDark)
);
// Set the scrolling view in the custom SwipeRefreshLayout.
swipeRefreshLayout.setScrollUpChild(listView);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mPresenter.loadTasks(false);
}
});
setHasOptionsMenu(true);
return root;
}
//...........................

}

View层中最重要的是setPresenter这个方法,通过这个方法让View层持有Presenter的引用,有了Presenter引用就可以将View层中的业务逻辑移到Presenter上,从而保证View层的轻便。
而View层中的方法大部分是和页面上控件操作有关。实现这些方法供Presenter调用。

我们再来看下数据层:

public class Injection {

public static TasksRepository provideTasksRepository(@NonNull Context context) {
checkNotNull(context);
return TasksRepository.getInstance(TasksRemoteDataSource.getInstance(),TasksLocalDataSource.getInstance(context));
}
}

我们先来看下TasksDataSource,这个是数据层的一个接口,这里定义了两个回调接口,这两个回调接口用于在数据层完成任务之后回调通知Presenter:

public interface TasksDataSource {

interface LoadTasksCallback {

void onTasksLoaded(List<Task> 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);
}

介绍了TasksDataSource我们就可以看下TasksRepository类的实现了。它有两个重要的实例对象mTasksRemoteDataSource,用于模拟网络层数据来源。mTasksLocalDataSource 用于表示本地数据来源这里代表的是数据库。
mCachedTasks 是内存缓存,使用mCacheIsDirty表示缓存内数据是否有效。

public class TasksRepository implements TasksDataSource {

private static TasksRepository INSTANCE = null;
//模拟网络层数据来源
private final TasksDataSource mTasksRemoteDataSource;
//模拟本地数据来源
private final TasksDataSource mTasksLocalDataSource;
/**
* 内存缓存
*/
Map<String, Task> mCachedTasks;

/**
* 用于表示当前缓存数据是否有效
* Marks the cache as invalid, to force an update the next time data is requested. This variable
* has package local visibility so it can be accessed from tests.
*/
boolean mCacheIsDirty = false;

private TasksRepository(@NonNull TasksDataSource tasksRemoteDataSource,
@NonNull TasksDataSource tasksLocalDataSource) {
mTasksRemoteDataSource = checkNotNull(tasksRemoteDataSource);
mTasksLocalDataSource = checkNotNull(tasksLocalDataSource);
}

/**
* Returns the single instance of this class, creating it if necessary.
*
* @param tasksRemoteDataSource the backend data source
* @param tasksLocalDataSource the device storage data source
* @return the {@link TasksRepository} instance
*/
// 使用一个单例创建TasksRepository
public static TasksRepository getInstance(TasksDataSource tasksRemoteDataSource,
TasksDataSource tasksLocalDataSource) {
if (INSTANCE == null) {
INSTANCE = new TasksRepository(tasksRemoteDataSource, tasksLocalDataSource);
}
return INSTANCE;
}

/**
* Used to force {@link #getInstance(TasksDataSource, TasksDataSource)} to create a new instance
* next time it's called.
*/
public static void destroyInstance() {
INSTANCE = null;
}

/**
* 从缓存,本地数据源(SQLite)或者远程数据源中获取 Task
* Gets tasks from cache, local data source (SQLite) or remote data source, whichever is
* available first.
* <p>
* Note: {@link LoadTasksCallback#onDataNotAvailable()} is fired if all data sources fail to
* get the data.
*/
@Override
public void getTasks(@NonNull final LoadTasksCallback callback) {

checkNotNull(callback);

// Respond immediately with cache if available and not dirty
// 如果内存中有内容并且缓存中的数据是可用的那么直接将缓存中的内容传递出去
if (mCachedTasks != null && !mCacheIsDirty) {
callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));
return;
}

if (mCacheIsDirty) {
///如果缓存中的数据不可用那么需要从网络中获取新的数据
// If the cache is dirty we need to fetch new data from the network.
getTasksFromRemoteDataSource(callback);
} else {
// Query the local storage if available. If not, query the network.
//这个一般发生在第一次,也就是这时候mCachedTasks = null 并且mCacheIsDirty = false
mTasksLocalDataSource.getTasks(new LoadTasksCallback() {
@Override
public void onTasksLoaded(List<Task> tasks) {
//从数据库中加载数据到缓存
refreshCache(tasks);
callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));
}
@Override
public void onDataNotAvailable() {
//如果数据库中没有数据那么就从缓存中获取
getTasksFromRemoteDataSource(callback);
}
});
}
}

/**
* 要保存的时候将数据存储到远程数据库,本地数据库,以及缓存中
*/
@Override
public void saveTask(@NonNull Task task) {
checkNotNull(task);
//保存到远程数据源中
mTasksRemoteDataSource.saveTask(task);
//保存到本地数据库中
mTasksLocalDataSource.saveTask(task);
// Do in memory cache update to keep the app UI up to date
//保存到缓存中
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.put(task.getId(), task);
}

/**
* 添加完成任务,也就是将complete标志为设置为true
*/
@Override
public void completeTask(@NonNull Task task) {

checkNotNull(task);
mTasksRemoteDataSource.completeTask(task);
mTasksLocalDataSource.completeTask(task);
Task completedTask = new Task(task.getTitle(), task.getDescription(), task.getId(), true);
// Do in memory cache update to keep the app UI up to date
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.put(task.getId(), completedTask);
}

@Override
public void completeTask(@NonNull String taskId) {
checkNotNull(taskId);
completeTask(getTaskWithId(taskId));
}

//添加激活任务,实现上是简单得将complete设置成false
@Override
public void activateTask(@NonNull Task task) {

checkNotNull(task);
mTasksRemoteDataSource.activateTask(task);
mTasksLocalDataSource.activateTask(task);
Task activeTask = new Task(task.getTitle(), task.getDescription(), task.getId());
// Do in memory cache update to keep the app UI up to date
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.put(task.getId(), activeTask);
}

@Override
public void activateTask(@NonNull String taskId) {
checkNotNull(taskId);
activateTask(getTaskWithId(taskId));
}

/**
* 清除完成的任务
*/
@Override
public void clearCompletedTasks() {

mTasksRemoteDataSource.clearCompletedTasks();
mTasksLocalDataSource.clearCompletedTasks();

// Do in memory cache update to keep the app UI up to date
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
Iterator<Map.Entry<String, Task>> it = mCachedTasks.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Task> entry = it.next();
if (entry.getValue().isCompleted()) {
it.remove();
}
}
}

/**
* Gets tasks from local data source (sqlite) unless the table is new or empty. In that case it
* uses the network data source. This is done to simplify the sample.
* <p>
* Note: {@link LoadTasksCallback#onDataNotAvailable()} is fired if both data sources fail to
* get the data.
*/

/**
* 依次从缓存,本地,远程中查找某个任务
* @param taskId
* @param callback
*/
@Override
public void getTask(@NonNull final String taskId, @NonNull final GetTaskCallback callback) {

checkNotNull(taskId);
checkNotNull(callback);

//从缓存中获取指定任务id的任务
Task cachedTask = getTaskWithId(taskId);
// Respond immediately with cache if available
if (cachedTask != null) {
callback.onTaskLoaded(cachedTask);
return;
}

//从本地数据源以及远程数据源获取指定id的任务数据
// Load from server/persisted if needed.
// Is the task in the local data source? If not, query the network.
mTasksLocalDataSource.getTask(taskId, new GetTaskCallback() {
@Override
public void onTaskLoaded(Task task) {
callback.onTaskLoaded(task);
}

@Override
public void onDataNotAvailable() {
mTasksRemoteDataSource.getTask(taskId, new GetTaskCallback() {
@Override
public void onTaskLoaded(Task task) {
callback.onTaskLoaded(task);
}

@Override
public void onDataNotAvailable() {
callback.onDataNotAvailable();
}
});
}
});
}

/**
* 将当前缓存设置为不可用
*/
@Override
public void refreshTasks() {
mCacheIsDirty = true;
}

/**
* 删除远程,本地,以及缓存中的任务
*/
@Override
public void deleteAllTasks() {
mTasksRemoteDataSource.deleteAllTasks();
mTasksLocalDataSource.deleteAllTasks();

if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.clear();
}

/**
* 将某个任务从缓存,本地数据库,远程数据库中删除
* @param taskId
*/
@Override
public void deleteTask(@NonNull String taskId) {
mTasksRemoteDataSource.deleteTask(checkNotNull(taskId));
mTasksLocalDataSource.deleteTask(checkNotNull(taskId));
mCachedTasks.remove(taskId);
}

/**
* 从远程中加载任务并添加到缓存和本地数据库
* @param callback
*/
private void getTasksFromRemoteDataSource(@NonNull final LoadTasksCallback callback) {
mTasksRemoteDataSource.getTasks(new LoadTasksCallback() {
@Override
public void onTasksLoaded(List<Task> tasks) {
///从远程加载数据后添加到缓存和本地数据库
refreshCache(tasks);
refreshLocalDataSource(tasks);
callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values()));
}

@Override
public void onDataNotAvailable() {
callback.onDataNotAvailable();
}
});
}

/**
* 用参数的tasks来填充mCachedTasks
* @param tasks
*/
private void refreshCache(List<Task> tasks) {
if (mCachedTasks == null) {
mCachedTasks = new LinkedHashMap<>();
}
mCachedTasks.clear();
for (Task task : tasks) {
mCachedTasks.put(task.getId(), task);
}
mCacheIsDirty = false;
}

/**
* 用参数的tasks来填充mTasksLocalDataSource
* @param tasks
*/
private void refreshLocalDataSource(List<Task> tasks) {
mTasksLocalDataSource.deleteAllTasks();
for (Task task : tasks) {
mTasksLocalDataSource.saveTask(task);
}
}

/**
* 从缓存中获取指定id的任务
* @param id 要获取任务的id
* @return
*/
@Nullable
private Task getTaskWithId(@NonNull String id) {
checkNotNull(id);
if (mCachedTasks == null || mCachedTasks.isEmpty()) {
return null;
} else {
return mCachedTasks.get(id);
}
}
}

上述的好处是我们可以随便更换数据源数据获取的底层实现。而不需要改动到其他部分,只要我们修改方案的时候按照接口定义规范进行实现即可。这样对于多人开发也是有很大好处的,和其他部分解耦了就可以单独开发了。

我们再来看下Presenter表示层:

public class TasksPresenter implements TasksContract.Presenter {

private final TasksRepository mTasksRepository;

private final TasksContract.View mTasksView;

private TasksFilterType mCurrentFiltering = TasksFilterType.ALL_TASKS;

private boolean mFirstLoad = true;

public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {
//数据层
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
//视图层
mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");
//将Presenter赋值给View层
mTasksView.setPresenter(this);
}

//加载任务数据
@Override
public void start() {
loadTasks(false);
}

//处理返回值
@Override
public void result(int requestCode, int resultCode) {
// If a task was successfully added, show snackbar
if (AddEditTaskActivity.REQUEST_ADD_TASK == requestCode && Activity.RESULT_OK == resultCode) {
//显示SnakeBar
mTasksView.showSuccessfullySavedMessage();
}
}

//加载数据
@Override
public void loadTasks(boolean forceUpdate) {
// Simplification for sample: a network reload will be forced on first load.
loadTasks(forceUpdate || mFirstLoad, true);
mFirstLoad = false;
}

/**
* @param forceUpdate Pass in true to refresh the data in the {@link TasksDataSource}
* @param showLoadingUI Pass in true to display a loading icon in the UI
*/
//加载数据
private void loadTasks(boolean forceUpdate, final boolean showLoadingUI) {

if (showLoadingUI) {
mTasksView.setLoadingIndicator(true);
}

if (forceUpdate) {
mTasksRepository.refreshTasks();
}

// The network request might be handled in a different thread so make sure Espresso knows
// that the app is busy until the response is handled.
EspressoIdlingResource.increment(); // App is busy until further notice

mTasksRepository.getTasks(new TasksDataSource.LoadTasksCallback() {
@Override
public void onTasksLoaded(List<Task> tasks) {

//创建需要显示的Task
List<Task> tasksToShow = new ArrayList<Task>();

// This callback may be called twice, once for the cache and once for loading
// the data from the server API, so we check before decrementing, otherwise
// it throws "Counter has been corrupted!" exception.
if (!EspressoIdlingResource.getIdlingResource().isIdleNow()) {
EspressoIdlingResource.decrement(); // Set app as idle.
}

// We filter the tasks based on the requestType
for (Task task : tasks) {
//根据mCurrentFiltering 显示那种类型的任务
switch (mCurrentFiltering) {
case ALL_TASKS:
tasksToShow.add(task);
break;
case ACTIVE_TASKS:
if (task.isActive()) {
tasksToShow.add(task);
}
break;
case COMPLETED_TASKS:
if (task.isCompleted()) {
tasksToShow.add(task);
}
break;
default:
tasksToShow.add(task);
break;
}
}
// The view may not be able to handle UI updates anymore
if (!mTasksView.isActive()) {
return;
}
if (showLoadingUI) {
mTasksView.setLoadingIndicator(false);
}
//处理这些任务
processTasks(tasksToShow);
}

@Override
public void onDataNotAvailable() {
// The view may not be able to handle UI updates anymore
if (!mTasksView.isActive()) {
return;
}
mTasksView.showLoadingTasksError();
}
});
}

private void processTasks(List<Task> tasks) {
if (tasks.isEmpty()) {
// Show a message indicating there are no tasks for that filter type.
//根据类型显示当前需要显示的空加载信息
processEmptyTasks();
} else {
// Show the list of tasks
//显示任务
mTasksView.showTasks(tasks);
// Set the filter label's text.
showFilterLabel();
}
}

private void showFilterLabel() {
switch (mCurrentFiltering) {
case ACTIVE_TASKS:
mTasksView.showActiveFilterLabel();
break;
case COMPLETED_TASKS:
mTasksView.showCompletedFilterLabel();
break;
default:
mTasksView.showAllFilterLabel();
break;
}
}

private void processEmptyTasks() {
switch (mCurrentFiltering) {
case ACTIVE_TASKS:
mTasksView.showNoActiveTasks();
break;
case COMPLETED_TASKS:
mTasksView.showNoCompletedTasks();
break;
default:
mTasksView.showNoTasks();
break;
}
}

//AddEditTaskActivity
@Override
public void addNewTask() {
mTasksView.showAddTask();
}

//TaskDetailActivity
@Override
public void openTaskDetails(@NonNull Task requestedTask) {
checkNotNull(requestedTask, "requestedTask cannot be null!");
mTasksView.showTaskDetailsUi(requestedTask.getId());
}

@Override
public void completeTask(@NonNull Task completedTask) {
checkNotNull(completedTask, "completedTask cannot be null!");
mTasksRepository.completeTask(completedTask);
mTasksView.showTaskMarkedComplete();
loadTasks(false, false);
}

@Override
public void activateTask(@NonNull Task activeTask) {
checkNotNull(activeTask, "activeTask cannot be null!");
mTasksRepository.activateTask(activeTask);
mTasksView.showTaskMarkedActive();
loadTasks(false, false);
}

@Override
public void clearCompletedTasks() {
mTasksRepository.clearCompletedTasks();
mTasksView.showCompletedTasksCleared();
loadTasks(false, false);
}

/**
* Sets the current task filtering type.
*
* @param requestType Can be {@link TasksFilterType#ALL_TASKS},
* {@link TasksFilterType#COMPLETED_TASKS}, or
* {@link TasksFilterType#ACTIVE_TASKS}
*/
@Override
public void setFiltering(TasksFilterType requestType) {
mCurrentFiltering = requestType;
}

@Override
public TasksFilterType getFiltering() {
return mCurrentFiltering;
}

}

它持有View层和数据层,这些方法提供给View层调用,绝大部分的代码是调用View层以及数据层的实现,它只负责整个状态的逻辑。数据层和Presenter层的交互使用的是Callback回调机制,回调接口在数据层接口中定义的。

Contents