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

}

 

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐