Android第四次作业

一、团队成员

姓名:李凯    学号:1600509018   班级:计算机164班   博客链接地址:https://www.cnblogs.com/JusperLee/

姓名:季轩石   学号:1600802115   班级:计算机164班   博客链接地址:http://www.cnblogs.com/midnightclad/

二、团队项目APK链接

Time APK地址:https://github.com/JusperLee/Time/blob/master/APK/Time.apk

三、团队项目代码

GitHub链接网址:https://github.com/JusperLee/Time

四、团队项目介绍

4.1 团队项目总体效果截图

App启动页

App的三个页面按钮对应的页面

扫描二维码关注公众号,回复: 4690725 查看本文章

 添加定量计划页面

 

 打卡计划页面展示

 

提醒事项页面展示

 

 主题目前仅仅有白色和黑色

 

 时间添加控件展示

 

 4.2 实现的功能及其效果描述

4.2.1 添加计划功能展示

        首先我们点击添加计划按钮,然后根据自己的需求我们有两个选项可以选择,一个是定量计划,一个是打卡计划,下面我们展示一下定量计划。我们先填写好自己计划的信息点击确定就可以在主页面上看到自己填写的内容了。由于截图较多,换了一种方式展示使用操作gif来展示。

4.2.2 打卡计划展示

        打卡计划也是通过自定义填写内容可以直接生成一个打卡计划的卡片,然后每天可以通过该卡片生成一个打卡内容。下面时演示的gif动图。

 4.2.3 添加提醒事项功能展示

        首先我们选中下面的菜单栏的第二个内容,然后点击添加TODO,输入你要提醒的事项,然后选择提醒时间,就可以添加提醒了。下面是我们的gif动态演示。

 4.2.4 主题的更改功能展示

        我们通过更改按钮进行主题更改,可以更改为白天和黑夜,下面通过gif来展示我们的主题更改功能。

 五、项目核心代码展示

5.1 添加计划代码

package com.lj.Time.page.plan;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;

import com.lj.Time.R;
import com.lj.Time.common.CustomFragmentPagerAdapter;
import com.lj.Time.event.PlanSelectedEvent;
import com.lj.Time.page.base.BaseActivity;
import com.lj.Time.widget.NoScrollViewPager;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * 添加计划界面
 */
public class AddPlanActivity extends BaseActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.view_pager)
    NoScrollViewPager viewPager;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_add_plan;
    }

    @Override
    protected void initView(@Nullable Bundle savedInstanceState) {
        ButterKnife.bind(this);
        EventBus.getDefault().register(this);

        initToolbar(toolbar, "添加计划", true);

        List<Fragment> fragmentList = new ArrayList<>();
        fragmentList.add(new ChoosePlanTypeFragment());
        fragmentList.add(new AddPlanFragment());

        CustomFragmentPagerAdapter fragmentPagerAdapter = new CustomFragmentPagerAdapter(getSupportFragmentManager(), fragmentList);

        viewPager.setAdapter(fragmentPagerAdapter);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(PlanSelectedEvent event) {
        if(event.getPlanType() == -1) {
            viewPager.setCurrentItem(0);
        }else{
            viewPager.setCurrentItem(1);
        }
    }

    @Override
    public void onBackPressed() {
        if(viewPager.getCurrentItem() == 1){
            EventBus.getDefault().post(new PlanSelectedEvent(-1));
        }else{
            super.onBackPressed();
        }
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }
}

5.2 修改计划功能

package com.lj.Time.presenter.plan;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.lj.Time.contract.plan.IEditPlanContract;
import com.lj.Time.db.ClockPlan;
import com.lj.Time.db.ClockPlanDao;
import com.lj.Time.db.DBManager;
import com.lj.Time.db.RationPlan;
import com.lj.Time.db.RationPlanDao;
import com.lj.Time.event.PlanChangedEvent;
import com.lj.Time.model.plan.EditPlanDataEntity;
import com.lj.Time.model.plan.ShowPlanEntity;
import com.lj.Time.util.DateUtils;

import org.greenrobot.eventbus.EventBus;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * 修改计划
 */
public class EditPlanPresenterImpl implements IEditPlanContract.Presenter {

    private Context context;
    private IEditPlanContract.View view;

    private long planId;
    /**
     * 0-定量计划
     * 1-打卡计划
     */
    private int planType;

    private Handler mHandler = new Handler(Looper.getMainLooper());

    private RationPlanDao mRationPlanDao;
    private ClockPlanDao mClockPlanDao;

    private RationPlan rationPlan;
    private ClockPlan clockPlan;

    public EditPlanPresenterImpl(Context context, IEditPlanContract.View view) {
        this.context = context;
        this.view = view;

        mRationPlanDao = DBManager.getInstance().getRationPlanDao();
        mClockPlanDao = DBManager.getInstance().getClockPlanDao();
    }

    @Override
    public void initDate(long planId, int planType) {
        this.planId = planId;
        this.planType = planType;
        view.showRoundProgressDialog();
        if (planType == 0) {
            view.showRationPlan();
            getRationPlanWithId();
        } else {
            view.showClockPlan();
            getClockPlanWithId();
        }
    }

    private void getRationPlanWithId() {
        Observable.create((ObservableEmitter<Integer> e) -> {
            List<RationPlan> rationPlanList = mRationPlanDao.queryBuilder()
                    .where(RationPlanDao.Properties.Id.eq(planId))
                    .list();
            if (rationPlanList.isEmpty()) {
                e.onNext(0);
            } else {
                rationPlan = rationPlanList.get(0);
                e.onNext(1);
            }
            e.onComplete();
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe((Integer value) -> {
                    if (value == 0) {
                        planDoesNotExits();
                    } else {
                        mHandler.postDelayed(() -> view.fillRationPlanData(rationPlan), 500);
                    }
                });
    }

    private void getClockPlanWithId() {
        Observable.create((ObservableEmitter<Integer> e) -> {
            List<ClockPlan> clockPlanList = mClockPlanDao.queryBuilder()
                    .where(ClockPlanDao.Properties.Id.eq(planId))
                    .list();
            if (clockPlanList.isEmpty()) {
                e.onNext(0);
            } else {
                clockPlan = clockPlanList.get(0);
                e.onNext(1);
            }
            e.onComplete();
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe((Integer value) -> {
                    if (value == 0) {
                        planDoesNotExits();
                    } else {
                        mHandler.postDelayed(() -> view.fillClockPlanData(clockPlan), 500);
                    }
                });
    }

    private void planDoesNotExits() {
        view.showNoActionSnackbar("计划不存在啊?怎么回事");
        mHandler.postDelayed(() -> ((Activity) view).finish(), 700);
    }

    @Override
    public void updatePlan(final EditPlanDataEntity editData) {
        if (planType == 0) {
            if (DateUtils.compareDate("yyyy-MM-dd", rationPlan.getStartDate(), editData.getFinishDate()) != -1) {
                view.showNoActionSnackbar("结束时间不能小于开始时间!!!");
                return;
            }
            Observable.create((ObservableEmitter<Integer> e) -> {
                rationPlan.setName(editData.getName());
                rationPlan.setTarget(editData.getTarget());
                rationPlan.setCurrent(editData.getCurrent());
                rationPlan.setFinishDate(editData.getFinishDate());
                rationPlan.setUnit(editData.getUnit());
                rationPlan.setPeriodIsOpen(editData.isPeriodIsOpen());
                if(editData.isPeriodIsOpen()){
                    rationPlan.setPeriodPlanTarget(editData.getPeriodTarget());
                    rationPlan.setPeriodPlanType(editData.getPeriodPlanType());
                }
                mRationPlanDao.insertOrReplace(rationPlan);
                DBManager.getInstance().clear();
                e.onNext(0);
                e.onComplete();
            }).subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(integer -> editSuccess());
        } else {
            Observable.create((ObservableEmitter<Integer> e) -> {
                clockPlan.setName(editData.getName());
                if (!TextUtils.isEmpty(editData.getDescription())) {
                    clockPlan.setDescription(editData.getDescription());
                }
                mClockPlanDao.insertOrReplace(clockPlan);
                DBManager.getInstance().clear();
                e.onNext(0);
                e.onComplete();
            }).subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(integer -> editSuccess());
        }
    }

    @Override
    public void deletePlan() {
        if (planType == 0) {
            mRationPlanDao.deleteByKey(planId);
        } else {
            mClockPlanDao.deleteByKey(planId);
        }
        view.showNoActionSnackbar("搞定");
        DBManager.getInstance().clear();
        EventBus.getDefault().post(new PlanChangedEvent());
        mHandler.postDelayed(() -> ((Activity) context).finish(), 700);
    }

    @Override
    public void deletePeriod() {
        if (rationPlan != null) {
            rationPlan.setPeriodIsOpen(false);
            mRationPlanDao.insertOrReplace(rationPlan);
            DBManager.getInstance().clear();
            initDate(planId, planType);
        }
    }

    private void editSuccess() {
        view.showNoActionSnackbar("修改好了");
        EventBus.getDefault().post(new PlanChangedEvent());
        mHandler.postDelayed(() -> ((Activity) context).finish(), 700);
    }

    @Override
    public void onDestroy() {
        mRationPlanDao = null;
        mClockPlanDao = null;
    }
}

5.3 提醒计划已完成功能代码

package com.lj.Time.presenter.todo;

import com.lj.Time.contract.todo.ICompletedTodoContract;
import com.lj.Time.db.DBManager;
import com.lj.Time.db.Todo;
import com.lj.Time.db.TodoDao;
import com.lj.Time.model.todo.ShowTodoEntity;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * 已完成的待办事项
 */
public class CompletedTodoPresenterImpl implements ICompletedTodoContract.Presenter {

    private ICompletedTodoContract.View view;


    private TodoDao mTodoDao;
    private Observable<Integer> updateTodoObservable;

    private List<ShowTodoEntity> listData = new ArrayList<>();

    public CompletedTodoPresenterImpl(ICompletedTodoContract.View view) {
        this.view = view;

        mTodoDao = DBManager.getInstance().getTodoDao();

        updateTodoObservable = Observable.create(e -> {
            listData.clear();
            List<Todo> todoList = mTodoDao.queryBuilder()
                    .where(TodoDao.Properties.Completed.eq(true))
                    .orderAsc(TodoDao.Properties.Date)
                    .list();
            if (!todoList.isEmpty()) {
                listData.addAll(Observable.fromIterable(todoList)
                        .map(todo -> {
                            ShowTodoEntity showTodo = new ShowTodoEntity();
                            showTodo.setType(0);
                            showTodo.setTodo(todo);
                            return showTodo;
                        })
                        .toList()
                        .blockingGet());
            }
            e.onNext(0);
            e.onComplete();
        });
    }

    @Override
    public void update() {
        updateTodoObservable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(integer -> view.notifyTodoChanged(listData));
    }
}

5.4 提醒计划展示实现代码

 

package com.lj.Time.presenter.todo;

import android.content.Context;

import com.lj.Time.contract.todo.IShowTodoContract;
import com.lj.Time.db.DBManager;
import com.lj.Time.db.Todo;
import com.lj.Time.db.TodoDao;
import com.lj.Time.model.todo.ShowTodoEntity;
import com.lj.Time.util.DateUtils;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * 待办事项展示
 */
public class ShowTodoPresenterImpl implements IShowTodoContract.Presenter {

    private Context context;
    private IShowTodoContract.View view;

    private TodoDao mTodoDao;
    private Observable<Integer> updateTodoObservable;

    private String dateFormat = "yyyy-MM-dd HH:mm";
    private String currentDate = DateUtils.getCurrentDate(dateFormat);

    private List<ShowTodoEntity> listData = new ArrayList<>();

    public ShowTodoPresenterImpl(Context context, IShowTodoContract.View view) {
        this.context = context;
        this.view = view;

        mTodoDao = DBManager.getInstance().getTodoDao();

        updateTodoObservable = Observable.create(e -> {
            listData.clear();
            List<Todo> todoList = mTodoDao.queryBuilder()
                    .where(TodoDao.Properties.Completed.eq(false))
                    .orderAsc(TodoDao.Properties.Date)
                    .list();
            if (!todoList.isEmpty()) {
                listData.addAll(Observable.fromIterable(todoList)
                        .map(todo -> {
                            ShowTodoEntity showTodo = new ShowTodoEntity();
                            showTodo.setType(0);
                            showTodo.setTodo(todo);
                            showTodo.setLevel(getLevel(todo));
                            return showTodo;
                        })
                        .toList()
                        .blockingGet());
            }
            ShowTodoEntity addTodoEntity = new ShowTodoEntity();
            addTodoEntity.setType(1);
            listData.add(addTodoEntity);
            e.onNext(0);
            e.onComplete();
        });
    }

    /**
     * 获取待办事项紧急等级
     */
    private int getLevel(Todo todo) {
        int level = 1;
        int hourSpace = DateUtils.getHourSpace(dateFormat, currentDate, todo.getDate());
        if (hourSpace <= 1) {
            level = 6;
        } else if (hourSpace <= 5) {
            level = 5;
        } else if (hourSpace <= 12) {
            level = 4;
        } else if (hourSpace <= 24) {
            level = 3;
        } else if (hourSpace <= 48) {
            level = 2;
        }
        return level;
    }

    @Override
    public void update() {
        updateTodoObservable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(integer -> view.notifyTodoChanged(listData));

    }
}

六、运行其他团队项目的apk,并进行评论

          由于同学们还没写完,我们还不能进行排名并评论。因此,等都提交完后进行排名并评论。

七、项目遇到的问题

    李凯,1600509018,在做项目的过程中遇到了很多的问题:

    (1)由于我想到对我们的这个项目使用greenrobot的一个开源项目EventBus,来对项目提供高效的发布和订阅事件,来对不同线程之间传递数据。我在引入GrennDao时出现了,项目混淆日志报错,Could not init DAOConfig。                           通过在国外论坛发现了给问题的解决方法:在proguard-rules.pro中加入

-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {  
    public static java.lang.String TABLENAME;  
}  
-keep class **$Properties 

                 (2)同时在将项目进行运行的时候,在虚拟机安装app的时候报了一个错误:Android Studio配置androidannotations 出现 Error:Execution failed for task ':app:compileDebugJavaWithJavac'。我的问题的解决方式是通过更新                                       BuildTools,然后clean项目后重新进行Build。问题就解决了。

                 (3)同时在安装apk的时候也出现了一个这个错误。error Unknown failure (at android.os.Binder.execTransact(Binder.java:565)) Error while Installing APKs。通过Stackoverflow查询网友们的评论,我也找到了解决方案。这是由于                               我在移动项目的时候没有重新生成项目,当我移动项目文件夹时,就我而言,Build-> Clean Project解决了这个问题。

                   还有其他的一些问题,是由于我的代码出现的问题我认为那种代码出现的问题只属于个人问题,也容易解决,通过查看log就可以解决这些问题,而我在文章中提出的这些问题都是比较棘手的,给大家提供个解决方案用来参考

八、项目分工

姓名 分工 工作比例 分数(10分)
李凯 UI,功能实现,数据库 60% 10
季轩石 UI,部分功能实现 40% 10

 

猜你喜欢

转载自www.cnblogs.com/JusperLee/p/10192769.html