Android之官方MVP例子分析(第四篇taskdetail包)
0、嘿嘿,这篇该详情页包了1、先看大牛的interface,看下这个页面有哪些页面逻辑,根据业务逻辑,View又是需要如何跟着变化/*** This specifies the contract between the view and the presenter.* 在View和presenter之间指定的连接器contract接口,把View和presenter放在...
·

0、嘿嘿,这篇该详情页包了
1、先看大牛的interface,看下这个页面有哪些业务逻辑(交互),根据业务逻辑的操作哦,View又会产生哪些变化
/**
* This specifies the contract between the view and the presenter.
* 在View和presenter之间指定的连接器contract接口,把View和presenter放在一起,牛逼
*/
public interface TaskDetailContract {
/**
* 看下在TaskDetail页面下的每个业务逻辑,会对View带来一些什么变化,View上会怎么提示用户
*/
interface View extends BaseView<Presenter> {
void setLoadingIndicator(boolean active); //显示加载进度条,加载Task时,如果缓慢就调用
void showMissingTask(); //展示丢失的任务
void hideTitle(); //隐藏标题,业务上可能会用到隐藏标题吗?
void showTitle(String title); //展示标题,有隐藏,当然就有显示了。
void hideDescription(); //隐藏详细内容
void showDescription(String description); //展示详细描述
void showCompletionStatus(boolean complete); //展示完成状态
void showEditTask(String taskId); //展示编辑Task的页面,即跳转到EditTask页
void showTaskDeleted(); //展示Task已经被删除的提示,业务上有在详情页删除的逻辑,View上要有体现
void showTaskMarkedComplete(); //展示Task标记完成,业务上可以标记Task为完成状态,View上给用户一个提示
void showTaskMarkedActive(); //展示Task标记活跃,业务上标记Task为活跃状态时,View上同样给用户一个提示
boolean isActive(); //是否活跃,还是判断Fragment是否已经依附到Activity上面
}
/**
* 在Task详情页下,我们会做什么,即当前TaskDetail页面下需求的业务逻辑会有哪些
* 我记得小强喜欢把服务器的交互逻辑也放在Presenter里面,这样是有道理的
* 服务器的交互逻辑,也是业务逻辑,他这么做也是有道理的撒
*/
interface Presenter extends BasePresenter {
void editTask(); //编辑Task,跳转到AddEditTask页面
void deleteTask(); //删除Task,直接删除掉Task,在业务上是要关闭当前的TaskDetail页的,这些都交给View去做
void completeTask(); //标记Task为完成状态
void activateTask(); //标记Task为活动状态
}
}
2、Activity,嘿嘿
/**
* Displays task details screen.
* 显示Task详情的页面
*/
public class TaskDetailActivity extends AppCompatActivity {
public static final String EXTRA_TASK_ID = "TASK_ID"; //先就整个常量,来干什么
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用基类的onCreate()方法,掉不掉的
setContentView(R.layout.taskdetail_act); //初始化布局
// Set up the toolbar. 初始化Tool bar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
// Get the requested task id
// 获取发起请求的Task id
String taskId = getIntent().getStringExtra(EXTRA_TASK_ID); //从Intent中拿出来就行
TaskDetailFragment taskDetailFragment = (TaskDetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.contentFrame); //通过布局id,获取Fragment
if (taskDetailFragment == null) {// 如果没有拿到Fragment
taskDetailFragment = TaskDetailFragment.newInstance(taskId); //那就只好创建一个Fragment了
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(),
taskDetailFragment, R.id.contentFrame); //将Fragment加入到Activity中
}
// Create the presenter 创建TaskDetail的Presenter
new TaskDetailPresenter(
taskId, //把Task id传过去
Injection.provideTasksRepository(getApplicationContext()),
taskDetailFragment); //打开本地记录的仓库
}
/**
* 支持导航键?
* @return 调用back键后,返回true
*/
@Override
public boolean onSupportNavigateUp() {
onBackPressed(); //同back键按下效果
return true; //返回true
}
}
3、Presenter实现类,业务逻辑实现类
/**
* Listens to user actions from the UI ({@link TaskDetailFragment}), retrieves the data and updates
* the UI as required.
*/
public class TaskDetailPresenter implements TaskDetailContract.Presenter {
private final TasksRepository mTasksRepository;
private final TaskDetailContract.View mTaskDetailView; //即TaskDetailFragment,因为它实现了TaskDetailContact.View接口
@Nullable
private String mTaskId;
public TaskDetailPresenter(@Nullable String taskId,
@NonNull TasksRepository tasksRepository,
@NonNull TaskDetailContract.View taskDetailView) {
mTaskId = taskId;
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null!");
mTaskDetailView = checkNotNull(taskDetailView, "taskDetailView cannot be null!");
mTaskDetailView.setPresenter(this); //哈哈,在这里,创建TaskDetailPresenter的时候,给Fragment下的mPresenter进行了初始化
}
@Override
public void start() {
openTask();
}
private void openTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTaskDetailView.setLoadingIndicator(true);
mTasksRepository.getTask(mTaskId, new TasksDataSource.GetTaskCallback() {
@Override
public void onTaskLoaded(Task task) {
// The view may not be able to handle UI updates anymore
if (!mTaskDetailView.isActive()) {
return;
}
mTaskDetailView.setLoadingIndicator(false);
if (null == task) {
mTaskDetailView.showMissingTask();
} else {
showTask(task);
}
}
@Override
public void onDataNotAvailable() {
// The view may not be able to handle UI updates anymore
if (!mTaskDetailView.isActive()) {
return;
}
mTaskDetailView.showMissingTask();
}
});
}
@Override
public void editTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTaskDetailView.showEditTask(mTaskId);
}
@Override
public void deleteTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.deleteTask(mTaskId);
mTaskDetailView.showTaskDeleted();
}
@Override
public void completeTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.completeTask(mTaskId);
mTaskDetailView.showTaskMarkedComplete();
}
@Override
public void activateTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.activateTask(mTaskId);
mTaskDetailView.showTaskMarkedActive();
}
private void showTask(@NonNull Task task) {
String title = task.getTitle();
String description = task.getDescription();
if (Strings.isNullOrEmpty(title)) {
mTaskDetailView.hideTitle();
} else {
mTaskDetailView.showTitle(title);
}
if (Strings.isNullOrEmpty(description)) {
mTaskDetailView.hideDescription();
} else {
mTaskDetailView.showDescription(description);
}
mTaskDetailView.showCompletionStatus(task.isCompleted());
}
}
4、控件变化实现类
/**
* Main UI for the task detail screen.
* Task详情页最主要的UI,就在这个类里面
* 当然这个Fragment一定是要实现TaskDetailContract.View接口的,View的变化,全在里面
* Let us do it
*/
public class TaskDetailFragment extends Fragment implements TaskDetailContract.View {
@NonNull
private static final String ARGUMENT_TASK_ID = "TASK_ID"; //参数 TASK ID
@NonNull
private static final int REQUEST_EDIT_TASK = 1; //请求编辑TASK的,请求码为1
private TaskDetailContract.Presenter mPresenter; //TaskDetailContract.Presenter的引用在此
private TextView mDetailTitle; //View
private TextView mDetailDescription; //View
private CheckBox mDetailCompleteStatus; //View
/**
* 创建Fragment的方法
* @param taskId 要传入Task的id哦
* @return
*/
public static TaskDetailFragment newInstance(@Nullable String taskId) {
Bundle arguments = new Bundle(); //创建Bundle对象
arguments.putString(ARGUMENT_TASK_ID, taskId); //把Task的id放到Bundle里面, ARGUMENT_TASK_ID就是它的key哦
TaskDetailFragment fragment = new TaskDetailFragment();//new一个Fragment对象
fragment.setArguments(arguments); //给Fragment设置Bundle
return fragment; //返回创建的Fragment对象
//至于为啥要它携带上Task id,后面就会知道了
}
/**
* 生命周期方法,参考Fragment生命周期
*/
@Override
public void onResume() {
super.onResume();
mPresenter.start(); //调用了start()方法,我们看下mPresenter在哪里初始化的,是调用的setPresenter方法哦
}
/**
* 生命周期方法
* @param inflater
* @param container
* @param savedInstanceState
* @return
*/
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.taskdetail_frag, container, false); //初始化布局
setHasOptionsMenu(true); //设置显示Options菜单
mDetailTitle = (TextView) root.findViewById(R.id.task_detail_title); //拿到View
mDetailDescription = (TextView) root.findViewById(R.id.task_detail_description); //拿到View
mDetailCompleteStatus = (CheckBox) root.findViewById(R.id.task_detail_complete);//拿到View
// Set up floating action button
FloatingActionButton fab =
(FloatingActionButton) getActivity().findViewById(R.id.fab_edit_task);//拿到View
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.editTask();
}
});//哈哈,设置点击事件监听器对象
return root; //返回View
}
/**
* 这个方法是TaskDetailContact.View下的一个方法,我们实现了它,就是它来初始化Presenter嘛
* 进去看看在哪里调用的该方法,牛逼
* @param presenter 参数就是presenter嘛
*/
@Override
public void setPresenter(@NonNull TaskDetailContract.Presenter presenter) {
mPresenter = checkNotNull(presenter);
}
/**
* Options菜单下,item的点击事件
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { //获取item的id
case R.id.menu_delete: //如果id是menu_delete
mPresenter.deleteTask(); //调用Presenter的删除Task
return true; //直接返回true
}
return false; //返回false
}
/**
* 创建OptionMenu菜单时,会调用的方法
* @param menu
* @param inflater
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.taskdetail_fragment_menu, menu);
}
/**
* 设置加载提示
* @param active 活跃状态
*/
@Override
public void setLoadingIndicator(boolean active) {
if (active) {
mDetailTitle.setText("");
mDetailDescription.setText(getString(R.string.loading));
}
}
/**
* 隐藏详细描述,就是把View GONE掉嘛
*/
@Override
public void hideDescription() {
mDetailDescription.setVisibility(View.GONE);
}
/**
* 隐藏标题,就是tile的View GONE掉嘛
*/
@Override
public void hideTitle() {
mDetailTitle.setVisibility(View.GONE);
}
/**
* 展示详细描述, View首先View.VISIBLE,总得显示出来
* View然后设置Text,牛逼
* @param description
*/
@Override
public void showDescription(@NonNull String description) {
mDetailDescription.setVisibility(View.VISIBLE);
mDetailDescription.setText(description);
}
/**
* 展示完成状态
* @param complete
*/
@Override
public void showCompletionStatus(final boolean complete) {
Preconditions.checkNotNull(mDetailCompleteStatus);
mDetailCompleteStatus.setChecked(complete); //先把checkBox设置为选中状态
mDetailCompleteStatus.setOnCheckedChangeListener( //然后为checkBox设置监听器,当checkBox状态改变时的监听器
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mPresenter.completeTask(); //如果是选中状态,调用presenter,标记Task为完成状态
} else {
mPresenter.activateTask(); //如果是非选中的状态,调用presenter的activateTask(),标记Task为活跃状态
}
}
});
}
/**
* 很明显,这是要跳转到编辑Task页啊,用show也没错,毕竟最后展示的是它
* @param taskId
*/
@Override
public void showEditTask(@NonNull String taskId) {
Intent intent = new Intent(getContext(), AddEditTaskActivity.class); //显式跳转
intent.putExtra(AddEditTaskFragment.ARGUMENT_EDIT_TASK_ID, taskId); //这里在Activity中放入一个Task id,而key就用都是AddEditTaskFragment下的key
startActivityForResult(intent, REQUEST_EDIT_TASK); //开启Activity
}
/**
* Task删除,把Activity finish掉就好了
*/
@Override
public void showTaskDeleted() {
getActivity().finish();
}
/**
* 展示Task标记为完成状态,其实这里是弹出一个Snackbar
*/
public void showTaskMarkedComplete() {
Snackbar.make(getView(), getString(R.string.task_marked_complete), Snackbar.LENGTH_LONG)
.show();
}
/**
* 展示Task标记为活动状态,其实这里就是弹出一个Snackbar
*/
@Override
public void showTaskMarkedActive() {
Snackbar.make(getView(), getString(R.string.task_marked_active), Snackbar.LENGTH_LONG)
.show();
}
/**
* 调用startActivityForResult后,关掉栈顶的Activity后,会回调这个方法
* @param requestCode 请求码
* @param resultCode 结果码
* @param data Intent对象
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_EDIT_TASK) { //判断请求码为REQUEST_EDIT_TASK
// If the task was edited successfully, go back to the list.
if (resultCode == Activity.RESULT_OK) { //判断结果码为上一个Activity正常关闭
getActivity().finish(); //得到TaskDetailAcFragment的Activity后,关闭Activity
}
}
}
/**
* 展示标题
* @param title 传入要展示的标题
*/
@Override
public void showTitle(@NonNull String title) {
mDetailTitle.setVisibility(View.VISIBLE); //设置View为VISBLE
mDetailTitle.setText(title); //设置标题
}
/**
* 展示丢失的Task
*/
@Override
public void showMissingTask() {
mDetailTitle.setText(""); //设置标题为""
mDetailDescription.setText(getString(R.string.no_data)); //设置内容为"No data"
}
/**
* 判断fragment是否为活动状态吧?
* @return
*/
@Override
public boolean isActive() {
return isAdded();
}
}
更多推荐



所有评论(0)