Android学习(1)数据库架构room及recyclerView的使用

在学习android的路上总是没有耐心,项目写了不少,文档也翻了不少。但是每次之前用过的东西需要再次用到的时候,又不知道该怎么用了,而且很多东西文档看看,实际上真写起代码来还是会遇到一定问题的,这里就新建了一个android项目,用以学习android的一些架构和控件。

这里贴一下项目地址,如果有需要可以看一下。https://github.com/libo1223/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用起来简单又清爽。

上一个架构图

Android学习(1)数据库架构room及recyclerView的使用

要用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);