Android学习(1)数据库架构room及recyclerView的使用
在学习android的路上总是没有耐心,项目写了不少,文档也翻了不少。但是每次之前用过的东西需要再次用到的时候,又不知道该怎么用了,而且很多东西文档看看,实际上真写起代码来还是会遇到一定问题的,这里就新建了一个android项目,用以学习android的一些架构和控件。
这里贴一下项目地址,如果有需要可以看一下。https://github.com/afei1223/androidStudy
参考文档
room:https://developer.android.google.cn/training/data-storage/room
RecyclerView:https://developer.android.google.cn/guide/topics/ui/layout/recyclerview
room是一个数据库框架,用的还是sqlite。官方文档也推荐使用room,个人感觉,room用起来简单又清爽。
上一个架构图
要用room这个架构的话,首先需要的依赖,官方文档已经给出了,可以直接copy一份,懒得去看官方文档的话,我这里贴一份
def room_version = "2.2.5" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor // optional - Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version" // optional - RxJava support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // Test helpers testImplementation "androidx.room:room-testing:$room_version"
然后先创建一个对象。User类
@Entity public class User { @PrimaryKey(autoGenerate = true) public int uid; @ColumnInfo(name = "name") public String name; @ColumnInfo(name = "password") public String password; }
@Entity表示数据库的表。这段代码其实就是创建了一个三个字段的表。
uid上面那个primaryKey是主键的意思,然后autogrnnrete则是是否自增的属性。如果不自增的话每次,插入数据就必须要填入uid。
ColumnInfo这个表示字段名,字段为name和password。
建完表之后,还缺一些增删改查的方法,
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Insert void insertAll(User... users); @Query("DELETE FROM user WHERE name = (:name) and password = :password") void delete(String name,String password); }
这个dao即表示用于访问数据的方法。然后query后面跟着的是sql语句,直接写增删改查之类的。调用这个方法即调用了这个sql。当然还有直接的delete和insert可以用于增删。个人感觉用query比较好。
这里是有个小知识点,就是User... user 这三个点表示,参数的类型可以是数组,也可以不是。比较神奇。
添加这个,自己领悟。
@Database(entities = {User.class}, version = 1 ,exportSchema = false ) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
用下面的方法创建数据库。
final AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
下面是我自己写的增删查。
//增 db.userDao().insertAll(user); //删 db.userDao().delete(user.name,user.password); //查 List<User> users = db.userDao().getAll();
比较简单,但是数据库操作不能在主线程里,线程这块我还没有搞得很透彻,所以这里不多说。如果想要代码可以跑起来可以参考我的项目。
这边拿到数据要展示怎么办,总不能log出来吧,所以顺带把recyclerview一起学了,本来想用listview的,看官方推荐都换成了recycleView。所以就采用这种,
之前用过viewpagaer,发现这种都需要一个adapter来插入view。
recyclerView比较简单,也没别的什么。有一点view的操作需要在ui线程下,一般来说你不创建线程不就是ui线程了么。但是刚刚拿数据不是在ui线程里啊,只能用handler.senMessage()给他发出去,然后接收渲染。
recycleView没有什么难度,直接在layout里去申明就好了。
这里贴一下,adapter的代码,讲一下。
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { // private String[] mDataset; private List<User> mDataset; // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class MyViewHolder extends RecyclerView.ViewHolder { // each data item is just a string in this case public TextView textView_id; public LinearLayout linearLayout; public MyViewHolder(LinearLayout l) { super(l); linearLayout = l; // textView_id = v; } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(List<User> myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view // TextView v = (TextView) LayoutInflater.from(parent.getContext()) // .inflate(R.layout.database_view, parent, false); LinearLayout l = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.database_view,parent,false); MyViewHolder vh = new MyViewHolder(l); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(MyViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element // holder.textView_id.setText(mDataset.get(position)); TextView textView_id= holder.linearLayout.findViewById(R.id.database_id); textView_id.setText(String.valueOf(mDataset.get(position).uid)); TextView textView_name = holder.linearLayout.findViewById(R.id.database_name); textView_name.setText(mDataset.get(position).name); TextView textView_pass = holder.linearLayout.findViewById(R.id.database_password); textView_pass.setText(mDataset.get(position).password); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { Log.i("databaseActivity","length:"+mDataset.size()); return mDataset.size(); } }
我这添加的布局可以到demo里去看(都贴出来太繁琐了),我简单说一下我对这个adapter的理解把,在oncreteViewholder先拿到对应的layout,这就相当于一个item了,getItemCount返回的是传入数据的数量,传入十条数据,他就会创建十个item,在onBindViewHolder中把数据绑定到自己添加的view上去。
其实代码真的听简单易懂的,如果看了我说的不是很明白,强烈建议直接看代码理解。
用的时候只要这样就可以用了
recyclerView = findViewById(R.id.database_recycler); // use this setting to improve performance if you know that changes // in content do not change the layout size of the RecyclerView recyclerView.setHasFixedSize(true); // use a linear layout manager LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); MyAdapter mAdapter = new MyAdapter(users); recyclerView.setAdapter(mAdapter);