日程的增删改查

来源:互联网 发布:samba端口号作用 编辑:程序博客网 时间:2024/05/16 03:24

一些改动

首先,为了方便按条件查询时日期时间的比较,我们在Schedule类以及数据库表中加入了一个long类型的变量与字段,用于保存日期时间,同时也在本地数据库的工具类中做了相应的更改

由于用户的UID传递较麻烦,所以这里新建了一个类继承自Application,添加了一个名为user_id的成员变量,并添加了get set方法

添加日程功能

上次做好了本地数据库的工具类,所以添加功能是比较简单的,只需要
获取信息->判断信息合法性->封装至对象->保存至本地数据库->保存至firebase数据库

首先设计UI
这个UI也是比较简单,把所有需要的信息放上去就OK了,就只有日期时间特别点,需要用按钮来触发选择器,默认为当前时间,拖放控件,修改ID,在string.xml中加入资源文本,修改按钮的OnClick事件,做好后如图
这里写图片描述

初始化日期时间选择器部分
由于时间选择器和日期选择器差不多,所以这里只展示选择日期的部分
在窗口类中添加几个成员变量-日期选择器,侦听器,保存选择了的日期时间的int变量以及一个用于存储选择的日期时间的Calendar类对象

    private DatePickerDialog dateDlg;    private DatePickerDialog.OnDateSetListener dateLis;    private int mYear,mMonth,mDay;    private int mHour,mMin;    private Calendar mCal=Calendar.getInstance();

再定义一个当日期选择了时触发的用于更新UI的函数()

    private void OnDateChose(){        tv_date.setText(mYear+"-"+mMonth+"-"+mDay);    }

然后在自己定义的init函数中初始化这些对象

dateLis=new DatePickerDialog.OnDateSetListener() {            @Override            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {                mYear=year;                mMonth=month;                mDay=dayOfMonth;                mCal.set(Calendar.YEAR,mYear);                mCal.set(Calendar.MONTH,mMonth);                mCal.set(Calendar.DAY_OF_MONTH,mDay);                mMonth++;                OnDateChose();            }        };        mYear = mCal.get(Calendar.YEAR);        mMonth = mCal.get(Calendar.MONTH);        mDay = mCal.get(Calendar.DAY_OF_MONTH);        mHour= mCal.get(Calendar.HOUR_OF_DAY);        mMin= mCal.get(Calendar.MINUTE);        dateDlg=new DatePickerDialog(this,dateLis,mYear,mMonth,mDay);        ...        OnDateChose();

由于保存的日期月份与选择的月份相差1,且mCal变量中以及保存了选择好的日期,所以这里为了显示时正常将mMonth变量值加一
初始化完成后调用一次更新UI用的函数以显示初始值

然后编写选择日期按钮的OnClick函数

    public void date(View v){        dateDlg.show();    }

接着编新建日程按钮的OnClick响应函数

public void insert(View v){        String id= RandomUtils.getRandomId();        String date=mYear+"-"+(mMonth+1)+"-"+mDay;        String time=mHour+":"+mMin;        String who=et_who.getText().toString();        String more=et_more.getText().toString();        int level=sp_level.getSelectedItemPosition();        if(who.equals("") || more.equals("")){            UIUtils.makeToast("不能留空",this);        }        Schedule schedule=new Schedule(id,date,time,who,more,null,level,mCal.getTimeInMillis());        ScheduleDbUtils db=new ScheduleDbUtils(this,null);        db.insert(schedule);        cloud(schedule);    }

最后编写函数cloud用于将数据备份至firebase数据库

        public void cloud(Schedule schedule){            final AlertDialog  dlg=UIUtils.createDialog(getString(R.string.insert_cloud_handling),this);            String uid=((GreenAppApplication)getApplication()).getUid();            FirebaseDatabase db=FirebaseDatabase.getInstance();  db.getReference().child("schedules").child(uid).child(schedule.getId()).setValue(schedule).addOnCompleteListener(new OnCompleteListener<Void>() {            @Override            public void onComplete(@NonNull Task<Void> task) {                dlg.dismiss();                if(task.isSuccessful()){                    UIUtils.makeToast(getString(R.string.insert_succeed),InsertScheduleActivity.this);                }else{                    UIUtils.makeToast(getString(R.string.insert_failed),InsertScheduleActivity.this);                }                InsertScheduleActivity.this.finish();            }        });    }

编写查询功能

查询主要有两种方式,一种是查询全部,一种是按条件查询

改动工具类

原来的本地数据库工具类的查询功能以及不能满足需求了,需要再定义一个接受whereClause与whereArgs的查询函数并让接受id的查询函数调用那个函数

 public List<Schedule> select(String id) {        if(id==null){            return select(null,null);        }else{            String whereClause = "s_id=?";            String[] whereArgs = {id};            return select(whereClause,whereArgs);        }    }    public List<Schedule> select(String whereClause,String[] whereArgs) {        SQLiteDatabase db = getReadableDatabase();        List<Schedule> result = new ArrayList<>();        Cursor cursor = db.query(TABLE_NAME, null, whereClause, whereArgs, null, null, null);        if (cursor.moveToFirst()) {            for (int i = 0; i < cursor.getCount(); i++) {                cursor.move(i);                String id=cursor.getString(0);                String date=cursor.getString(1);                String time=cursor.getString(2);                String who=cursor.getString(3);                int level=cursor.getInt(4);                String more=cursor.getString(5);                long t=cursor.getLong(6);                Schedule schedule=new Schedule(id,date,time,who,more,null,level,t);                result.add(schedule);            }        }        return result;    }

设计UI与实现功能
这里会出现四个Activity(今后可能会用对话框代替部分)
分别是充当菜单作用的SelectSchedulesActivity,
用户输入查询条件的SelectSchedulesConditionActivity,
显示查询结果的SelectSchedulesResultActivity,
用于显示日程详细信息并提供更改与删除操作的SelectSchedulesResultMoreActivity

SelectSchedulesActivity:
由于这只是充当菜单作用,所以UI相对简单
这里写图片描述
下面两个按钮只是用于跳转至其他Activity,重点是恢复与备份功能(以后可能会移到别处或自动处理)
这里把两个功能分开来做
备份将本地数据同步到云端,就需要获取本地的所有日程,然后挨个上传至服务器(以后可能会加入一个字段来保存日程内容的MD5,如果MD5且ID相同的日程就跳过以减少服务器与客户端的负担)

public void cloud(View v){        str_id=R.string.select_cloud_succeed;        List<Schedule> schedules=db.select(null);        if(schedules==null || schedules.size()==0){            UIUtils.makeToast(getString(str_id),SelectSchedulesActivity.this);            return;        }        FirebaseDatabase fdb=FirebaseDatabase.getInstance();        final AlertDialog dlg=UIUtils.createDialog(getString(R.string.select_cloud_handling),this);        for(final Schedule schedule:schedules){            DatabaseReference ref=fdb.getReference().child("schedules").child(uid).child(schedule.getId());            ref.setValue(schedule).addOnFailureListener(new OnFailureListener() {                @Override                public void onFailure(@NonNull Exception e) {                    str_id=R.string.select_cloud_failed;                }            });        }        dlg.dismiss();        UIUtils.makeToast(getString(str_id),SelectSchedulesActivity.this);    }

恢复功能就是将服务器上的弄到本地数据库里面去
但由于本地数据库并不能覆盖同ID的数据
所以先判断是否存在同ID的,不存在就添加,存在就修改

   public void download(View v){        str_id=R.string.select_download_succeed;        FirebaseDatabase fdb=FirebaseDatabase.getInstance();        final AlertDialog dlg=UIUtils.createDialog(getString(R.string.select_download_handling),this);        final DatabaseReference ref=fdb.getReference().child("schedules").child(uid);        ref.addListenerForSingleValueEvent(new ValueEventListener() {            @Override            public void onDataChange(DataSnapshot dataSnapshot) {                if(dataSnapshot.getChildrenCount()==0){                    str_id=R.string.select_download_succeed;                }                Iterable<DataSnapshot> children=dataSnapshot.getChildren();                for(DataSnapshot child:children){                    String id=child.child("id").getValue(String.class);                    List<Schedule> result=db.select(id);                    if(result!=null && result.size()!=0){                        db.update(child.getValue(Schedule.class),id);                        continue;                    }                    db.insert(child.getValue(Schedule.class));                }            }            @Override            public void onCancelled(DatabaseError databaseError) {                str_id=R.string.select_download_failed;                return;            }        });        dlg.dismiss();        UIUtils.makeToast(getString(str_id),SelectSchedulesActivity.this);    }

SelectSchedulesConditionActivity:
按条件查询就要考虑输入的空白数据,因为用户要使用这种查询是因为用户并不知晓所需日程的全部内容,所以这里有两种解决方案,一种是判断所输入的是否为空,如果为空那么就让该字段为任意值都可以查询到,即忽略该字段,还有一种是使用户并不用做出任何操作就可以查询到所有,这里显然是后者更方便,由于数据库中保存了日期时间化为long类型后的数据,所以用大于小于运算符就可以做出比较,文本类信息就用LIKE关键字,在所输入的数据的前后加入通配符’%’
这里的默认日期时间就是当时,默认查找当前时间之后的
等级默认是最低的那个,然后条件是大于等于,即任何日程都符合
其他的文本信息默认为空,即任何文本都可以匹配成功
这里写图片描述
UI也以选择性的控件为主,以引导用户查找
日期时间选择器前面以及介绍过了,重点在于查找部分

    public void select(View v){        int time_con=sp_date_time_condition.getSelectedItemPosition();        int level_con=sp_level_condition.getSelectedItemPosition();        int level=sp_level.getSelectedItemPosition();        long time=mCal.getTimeInMillis();        String who=et_who.getText().toString();        String more=et_more.getText().toString();        String operatorTime[]={"<","=",">"};        String operatorLevel[]={">","=","<",">=","<="};        who="%"+who+"%";        more="%"+more+"%";        String whereClause="s_time_long "+operatorTime[time_con]+" ? and s_level"+operatorLevel[level_con]+" ? and s_who like ? and s_more like ?";        String whereArgs[]={String.valueOf(time),String.valueOf(level),who,more};        ScheduleDbUtils db=new ScheduleDbUtils(this,null);        List<Schedule> schedules=db.select(whereClause,whereArgs);        Intent intent=new Intent(this,SelectSchedulesResultActivity.class);        intent.putExtra("schedules", (Serializable) schedules);        startActivity(intent);    }

这样就可以查找出符合条件的日程了

SelectSchedulesResultActivity:
这里的控件也就只有个ListView,用于展示查询结果
这里需要一个适配器
新建一个类MyAdapter继承自BaseAdapter,添加构造函数获取必须的数据

class MyAdapter extends  BaseAdapter{    private List<Schedule> schedules;    private boolean isListNull=false;    private Context context;    public MyAdapter(List<Schedule> schedules,boolean isListNull,Context context){        this.schedules=schedules;        this.isListNull=isListNull;        this.context=context;    }    ...

这里在res目录下新建一个view
这里写图片描述
这里只需改动一下getCount函数以及getView函数

   @Override    public int getCount() {        if(isListNull){            return 1;        }        return schedules.size();    }    ...        @Override    public View getView(int position, View convertView, ViewGroup parent) {        if(isListNull){            LinearLayout layout=new LinearLayout(context);            TextView tv=new TextView(context);            tv.setText("没有数据");            layout.addView(tv);            return layout;        }        View view=View.inflate(context,R.layout.view_select_result,null);        TextView tv_date,tv_time,tv_who,tv_level,tv_more;        tv_date= (TextView) view.findViewById(R.id.select_result_tv_date);        tv_time= (TextView) view.findViewById(R.id.select_result_tv_time);        tv_who= (TextView) view.findViewById(R.id.select_result_tv_who);        tv_level= (TextView) view.findViewById(R.id.select_result_tv_level);        tv_more= (TextView) view.findViewById(R.id.select_result_tv_more);        Schedule schedule=schedules.get(position);        String date=schedule.getDate();        String time=schedule.getTime();        String who=schedule.getWho();        String level= schedule.levelToString(context);        String more=schedule.getMore();        tv_date.setText(context.getString(R.string.select_result_date)+date);        tv_time.setText(context.getString(R.string.select_result_time)+time);        tv_who.setText(context.getString(R.string.select_result_who)+who);        tv_level.setText(context.getString(R.string.select_result_level)+level);        tv_more.setText(context.getString(R.string.select_result_more)+more);        return view;    }

这里还需要为这个ListView做一个项目点击侦听器

class MyClickListener implements AdapterView.OnItemClickListener{    private Context context;    private List<Schedule> schedules;    public MyClickListener(Context context,List<Schedule> schedules){        this.context=context;        this.schedules=schedules;    }    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        if(schedules.size()==0)            return;        Schedule schedule=schedules.get(position);        Intent intent=new Intent(context,SelectSchedulesResultMoreActivity.class);        intent.putExtra("schedule",schedule);        intent.putExtra("pos",position);        context.startActivity(intent);    }}

由于More窗口处理完成后需要告知Result窗口,所以这里再定义一个个广播接收者

   private BroadcastReceiver receiver=new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            int what=intent.getIntExtra("what",0);            int pos=intent.getIntExtra("pos",0);            switch(what){                case 0://Delete                    schedules.remove(pos);                    break;                case 1://Update                    Schedule schedule= (Schedule) intent.getSerializableExtra("schedule");                    schedules.set(pos,schedule);                    break;            }            lv_result.setAdapter(new MyAdapter(schedules,(schedules.size()==0)?true:false,context));        }    };

最后在init函数中设置它们

    public void init(){        lv_result= (ListView) findViewById(R.id.select_result_lv_result);        schedules= (List<Schedule>) getIntent().getSerializableExtra("schedules");        boolean isListNull=false;        if(schedules==null || schedules.size()==0){            isListNull=true;        }else{            lv_result.setOnItemClickListener(new MyClickListener(this,schedules));        }        adapter=new MyAdapter(schedules,isListNull,this);    }

在onCreate函数中注册广播接受者

        IntentFilter filter = new IntentFilter();        filter.addAction("com.greenapp.note.SCHEDULE_CHANGE");        registerReceiver(receiver,filter);

SelectSchedulesResultMoreActivity:
这里写图片描述
这个UI和insert的差不多
功能的实现也和insert类似,获取信息,然后本地数据库的update,再设置firebase数据库中的值,就ok了,删除只需删除本地数据库里的值,然后将firebase数据库里的值设置为null就ok了

db.getReference().child("schedules").child(uid).child(schedule.getId()).setValue(null)//删除
原创粉丝点击