Android 数据库-Room

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/moxiouhao/article/details/80668018

前言

最近项目中用得数据库框架 “ActivieAndroi” 由于作者停止维护了,它在升级到8.0之后会发生Crash,因此,我们准备给项目换一个数据库。主要考虑了Relam,Room,GreendDao 三个开源得数据库框架。

内容

Room

Google 支持的ARCH框架推荐;使用原生SQL;注解

使用

网上一半教程都是在翻译官方文档,有兴趣的可以自己去看下官方给的Document & Demo

Git:https://github.com/googlesamples/android-architecture-components/
Document:https://developer.android.com/training/data-storage/room/

1 引用Room库

dependencies {
    def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"

    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"

    // optional - RxJava support for Room
    implementation "android.arch.persistence.room:rxjava2:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "android.arch.persistence.room:guava:$room_version"

    // Test helpers
    testImplementation "android.arch.persistence.room:testing:$room_version"
}

2 定义数据表实体类

@Entity(tableName = "user_tb")
public class UserRoom {

    @PrimaryKey(autoGenerate = true)
    private int uid;
    @ColumnInfo
    private String name;
    @ColumnInfo
    private int age;
    @ColumnInfo
    private Date birthday;
    ... 省略了get/set
}

3 编写Dao
直接看Code吧,因为是ORM数据库,注解当然少不了。是不是有点想Retrofit得写法?而且支持写原生SQL,我觉得是很Nice得!别特么说Android程序员不需要学SQL,没点底子出了问题你都不晓得咋搞的。

@Dao
public interface UserDao {

    @Insert
    Long insertUser(UserRoom user);

    @Query("SELECT * FROM user_tb")
    Flowable<List<UserRoom>> queryAll();

    @Query("SELECT * FROM user_tb")
    List<UserRoom> queryForAll();

    @Query("SELECT * FROM user_tb WHERE name = :name")
    int deleteByName(String name);

    @Query("SELECT * FROM user_tb WHERE datetime(birthday/1000, 'unixepoch') >= datetime('now','-1 hour') ")
    Flowable<List<UserRoom>> queryWithinHour();

    @Delete
    void deleteUser(UserRoom user);

    @Query("DELETE FORM user_tb where uid = :id")
    void deleteUserById(int id)

}

4 在NApplication中初始化
写一个类继承RoomDatabaes,我是写了一个单利.

// 要生成的数据表实例类
@Database(entities = {UserRoom.class},version = 1,exportSchema = false)
// 如果要存储Date数据,需要加这个来转换
@TypeConverters({DateConverts.class})
public abstract class AndroidDataBases extends RoomDatabase {

    public abstract UserDao userDao();

    private static volatile AndroidDataBases INSTANCE;

    public static AndroidDataBases crateDatabases(Context context) {
        if (INSTANCE == null) {
            synchronized (AndroidDataBases.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            AndroidDataBases.class, "room.db")
                            .build();
                }
            }
        }
        return INSTANCE;
    }

    public static AndroidDataBases getInstance(){
        return INSTANCE;
    }
}


public class DateConverts {
    @TypeConverter
    public static Date revertDate(Long value) {
        return value == null ? null : new Date(value);
    }

    @TypeConverter
    public static Long converterDate(Date date) {
        return date == null ? null : date.getTime();
    }
}

CURD

有一点需要注意得是Room默认是必须在子线程操作得,否则抛异常。

    // 先获取一个UserDao
    var userDao: UserDao = AndroidDataBases.getInstance().userDao()().userDao();

    // 插入一条数据
    val user: UserRoom = UserRoom("admin2", 25, Date(System.currentTimeMillis()))
            AsyncTask.execute({
                var raw = userDao.insertUser(user)
                Log.d("picher","操作行号:"+raw)
            })
    // 查询数据
    AsyncTask.execute(Runnable {
                 var raws = userDao.queryForAll()
                 Log.d("picher","数据库:"+raws.size)
             })
    // 删除数据 & 修改数据类似 只要在Dao中写好了直接调

看下用了Rx得写法(有坑,插入数据时也会触发这个回掉):

首先需要引用Room 自己的RX库。

// RxJava support for Room
    compile "android.arch.persistence.room:rxjava2:1.1.1-rc1"
 private fun flowableDemo() {
           userDao.queryAll().subscribeOn(Schedulers.io())
                   .map({ users -> 
                       var names = ""
                       for (item in users) names += item.name
                       names
                   }).observeOn(AndroidSchedulers.mainThread()).subscribe({ names -> showTv.text =names})
    }

Room的坑

  1. 实例要给一个空参构造.
  2. 要支持存储Date类型的数据必须加@DateConvert.
  3. 和Rx一起用的时候需要引用Room的Rx库.
  4. Rx在查询完记得dispose,否则每次操作操作数据库都会收到回掉

暂时就遇到这些坑,之后如果遇到再来补上。大家慎踩…

总结

个人感觉上手还是不错的,开发上也比较爽,还能练写原生SQL,有Retrtofit使用经验的上手更快,只是大项目先别急着上,毕竟才出来,先把坑排一排在用。

展开阅读全文

Room Assignments

10-22

DescriptionnnOnce there was an inventor congress, where inventors from all over the world met in one place. The organizer of the congress reserved exactly one hotel room for each inventor. Each inventor, however, had its own preference regarding which room he would like to stay in. Being a clever inventor himself, the organizer soon found an objective way of doing the room assignments in a fair manner: each inventor wrote two different room numbers on a fair coin, one room number on each side. Then, each inventor threw his coin and was assigned the room number which was shown on the upper side of his coin. If some room had been assigned to more than one inventor, all inventors had to throw their coins again. n As you can imagine, this assignment process could take a long time or even not terminate at all. It has the advantage, however, that among all possible room assignments, one assignment is chosen randomly according to a uniform distribution. In order to apply this method in modern days, you should write a program which helps the organizer. n The organizer himself needs a hotel room too. As the organizer, he wants to have some advantage: he should be able to rate each of the rooms (the higher the rating, the better), and the program should tell him which two room numbers he should write on his coin in order to maximize the expected rating of the room he will be assigned to. The program also has access to the choices of the other inventors before making the proposal. It should never propose two rooms for the organizer such that it is not possible to assign all inventors to the rooms, if a valid assignment is possible at all.n InputnnThe input starts with a single number c (1 <= c <= 200) on one line, the number of test cases. Each test case starts with one line containing a number n (2 <= n <= 50 000), the number of inventors and rooms. The following n-1 lines contain the choices of the n-1 guests (excluding the organizer). For each inventor, there is a line containing two numbers a and b (1 <= a < b <= n), the two room numbers which are selected by the inventor. The last line of each test case consists of n integers v1, ... , vn (1 <= vi <= 1 000 000), where vi is the organizer's rating for room i. n OutputnnFor each test case, print a single line containing the two different room numbers a and b which should be selected by the organizer in order to maximize the expected rating of the room he will be assigned to. If there is more than one optimal selection, break ties by choosing the smallest a and, for equal a, the smallest b. If there is no way for the organizer to select two rooms such that an assignment of inventors to rooms is possible, print "impossible" instead. n Sample Inputnn3n 4n 1 2n 2 3n 1 3n 2 3 4 1n 3n 1 2n 2 3n 100 40 70n 5n 1 2n 1 2n 1 2n 3 4n 1 1 1 1 1n Sample Outputnn1 4n 1 3n impossiblen 问答

没有更多推荐了,返回首页