之前做了个简单的知乎日报的客户端,在这的基础上再加上了便签的功能,使用LitePal操作数据库。
效果
首先需要添加依赖
compile 'org.litepal.android:core:1.4.1'在这个功能中还添加了
compile 'com.hanks.animatecheckbox:library:0.1'compile 'com.android.support:multidex:1.0.0'animatecheckbox:就是一个checkbox,不过好看点。。
multidex:导入第三方项目后,导致重复,添加这个依赖可以进行分包 使用方法http://stackoverflow.com/questions/27377080/after-update-of-as-to-1-0-getting-method-id-not-in-0-0xffff-65536-error-i
需要设置AndroidManifest.xml里的application
android:name="android.support.multidex.MultiDexApplication"但是问题来了,litePal需要将application设置为
android:name="org.litepal.LitePalApplication"但是java不能多继承啊..
看了下LitePalFramework/LitePal ,发现可以定义自己的MyApplication
public class MyApplication extends android.support.multidex.MultiDexApplication { @Override public void onCreate() { super.onCreate(); LitePal.initialize(this); }}android:name=".app.MyApplication"再创建一个assets目录,在目录下建一个litepal.xml
<litepal> <dbname value="oneday"></dbname> <version value="2" /> <list> <mapping class="com.example.linsawako.zhihu.bean.Schedule"/> </list></litepal>LitePal是对象关系映射的模式,将面向对象的语言和面向关系的数据库之间建立一种映射关系。
<mapping>
用来声明要配置的映射模式类,需要完整的类名。 升级数据库的时候,只需要更改version的值。 只需要任意的一次数据库操作,这个数据库就会自动创建出来。
配置的工作就到这。
便笺的bean类
public class Schedule extends DataSupport implements Serializable{ PRivate int id; private Date date; private String content; private Boolean finish; public int getId() { return id; } public Date getDate() { return date; } public String getContent() { return content; } public Boolean getFinish() { return finish; } public void setContent(String content) { this.content = content; } public void setDate(Date date) { this.date = date; } public void setFinish(Boolean finish) { this.finish = finish; } public void setId(int id) { this.id = id; }}模型类需继承DataSupport。implements Serializable是因为需要在使用intent调转时,可以传递整个对象。关于序列化可以看下我的另外一篇文章 java-Serializable 序列化
RecyclerView的Adapter
public class ScheduleAdapter extends RecyclerView.Adapter<ScheduleAdapter.ViewHolder> { public final static int NAME = 1;//用来判断是哪个intent跳转的 private List<Schedule> list; private Context mContext; private int scheduleId; public ScheduleAdapter(List<Schedule> list) { this.list = list; } class ViewHolder extends RecyclerView.ViewHolder { CardView cardView; AnimateCheckBox animateCheckBox; TextView scheduleText; TextView date; public ViewHolder(View itemView) { super(itemView); cardView = (CardView) itemView.findViewById(R.id.schedule_cardview); animateCheckBox = (AnimateCheckBox) itemView.findViewById(R.id.schedule_checkbox); scheduleText = (TextView) itemView.findViewById(R.id.schedule_text); date = (TextView) itemView.findViewById(R.id.schedule_date); } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mContext == null) { mContext = parent.getContext(); } View view = LayoutInflater.from(mContext).inflate(R.layout.schedule_item, parent, false); final ViewHolder viewHolder = new ViewHolder(view); //点击后跳转,数据可更改 viewHolder.cardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int position = viewHolder.getAdapterPosition(); Schedule schedule = list.get(position); Intent intent = new Intent(mContext, AddScheduleActivity.class); intent.putExtra("ActivityName", NAME); intent.putExtra("Content", schedule); mContext.startActivity(intent); } }); //设置checkBox点击后的数据存储 viewHolder.animateCheckBox.setOnCheckedChangeListener(new AnimateCheckBox.OnCheckedChangeListener() { @Override public void onCheckedChanged(View buttonView, boolean isChecked) { int position = viewHolder.getAdapterPosition(); Schedule schedule = list.get(position); schedule.setFinish(viewHolder.animateCheckBox.isChecked()); schedule.update(schedule.getId()); } }); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Schedule schedule = list.get(position); holder.date.setText(new SimpleDateFormat("yyyy/MM/dd").format(schedule.getDate())); holder.scheduleText.setText(schedule.getContent()); holder.animateCheckBox.setChecked(schedule.getFinish()); } @Override public int getItemCount() { return list.size(); }}这里涉及了使用LitePal更新数据,
Schedule schedule = list.get(position);schedule.setFinish(viewHolder.animateCheckBox.isChecked());schedule.update(schedule.getId());更新数据的另一个方法,示例
albumToUpdate.updateAll("name = ?", "album");括号中相当于是where的内容。
ScheduleFragment显示便签的瀑布流
public class ScheduleFragment extends Fragment { private static final String TAG = "ScheduleFragment"; public final static int NAME = 0; private RecyclerView recyclerView; private List<Schedule> scheduleList; private ScheduleAdapter mAdapter; PopOptionUtil mPop;//用于长按时弹出删除提示框 public ScheduleFragment() { } @Override public void onResume() { super.onResume(); scheduleList.clear(); //去掉之前的数据 List<Schedule> newList = DataSupport.order("date desc").find(Schedule.class); scheduleList.addAll(newList);//注意要将数据复制过来,而不是直接使用,不然无法更新数据 mAdapter.notifyDataSetChanged(); Log.d(TAG, "onResume: "); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView: "); View view = inflater.inflate(R.layout.fragment_schedule, container, false);//fab点击后跳转到添加便签的界面 FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.schedule_fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.d(TAG, "onClick: intent"); Intent intent = new Intent(getContext(), AddScheduleActivity.class); intent.putExtra("ActivityName", NAME); startActivity(intent); } }); mPop = new PopOptionUtil(getContext()); scheduleList = DataSupport.order("date desc").find(Schedule.class); mAdapter = new ScheduleAdapter(scheduleList); recyclerView = (RecyclerView) view.findViewById(R.id.schedule_recyclerview); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(mAdapter);//设置recyclerview的长按事件 recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // ... } @Override public void onItemLongClick(View view, final int position) { Log.d(TAG, "onItemLongClick: "); mPop.setOnPopClickEvent(new PopClickEvent() { @Override public void onNextClick() { //删除item Log.d(TAG, "onNextClick: delete"); int id = scheduleList.get(position).getId(); Log.d(TAG, "onNextClick: position:" + position + " id: " + id); deleteData(id); scheduleList.remove(position); mAdapter.notifyItemRemoved(position); mAdapter.notifyItemRangeChanged(0,scheduleList.size());//这个需要设置,因为删除后item的position会改变 mPop.dismiss(); } }); mPop.show(view); } })); return view; }//litepal删除数据 public void deleteData(int id){ DataSupport.deleteAll(Schedule.class, "id = ?", String.valueOf(id)); Log.d(TAG, "deleteData: " + id); }}关于PopOptionUtil参考了这篇文章仿QQ长按弹出功能菜单 ,就不把具体代码贴上来了
recyclerview的长按事件,参考Android RecyclerView点击事件与长按事件
AddScheduleActivity
public class AddScheduleActivity extends AppCompatActivity { private static final String TAG = "AddScheduleActivity"; private int activityName; private int scheduleID; @Bind(R.id.addSchedule_editText) EditText contentText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_schedule); ButterKnife.bind(this); Toolbar toolbar = (Toolbar) findViewById(R.id.edit_toolbar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true);//让导航按钮显示出来,设置为返回键 } Intent intent = getIntent(); activityName = intent.getIntExtra("ActivityName", 0);//判断是哪个intent跳转的 //修改便签的事件 if (activityName == ScheduleAdapter.NAME){ Schedule schedule = (Schedule) intent.getSerializableExtra("Content"); contentText.setText(schedule.getContent());//填入已有的数据 scheduleID = schedule.getId(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home://返回 finish(); break; case R.id.save://存储键 Log.d(TAG, "onOptionsItemSelected: savedata"); if (activityName == ScheduleAdapter.NAME) {//如果是已有的数据就更新,否则存储 updateDate(); } else if (activityName == ScheduleFragment.NAME) { saveDate(); } finish(); break; } return true; } //使用litepal更新数据 public void updateDate() { Schedule schedule = new Schedule(); schedule.setContent(contentText.getText().toString()); schedule.setDate(new Date()); schedule.update(scheduleID); } //使用litepal存储数据 public void saveDate(){ Schedule schedule = new Schedule(); schedule.setDate(new Date());//存入的时间 schedule.setContent(contentText.getText().toString()); schedule.setFinish(false); schedule.save(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_schedule, menu); return true; }}差不多就这样,GitHub:https://github.com/linsawako/oneDay
说下感想吧,,单单搬砖还是无聊的orz,玩了一寒假,也快开学了,如往常一样,写的计划没一个做到的(:з」∠)…明天起好好打基础
新闻热点
疑难解答