Android Room牛刀小试 - Go语言中文社区

Android Room牛刀小试


Room在SQLite之上提供了一个抽象层来访问数据库,可以在充分利用SQLite强大功能的同时对数据库进行流畅的访问。

优点

  • 减少了写大量代码来在SQL查询和Java数据对象之间进行转换。
  • 数据层改变自动更新SQL查询。减少了查询过程的耗时。

使用

添加依赖

compile "android.arch.persistence.room:runtime:1.0.0-beta1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-beta1"

可能发生的错误

Error:Failed to resolve: android.arch.persistence.room:runtime:1.0.0-beta1
Error:Failed to resolve: annotationProcessor

解决办法:
往工程级别下的gradle文件里添加google的maven仓库

allprojects {
    repositories {
        jcenter()
        maven {
            url 'https://maven.google.com'
        }
    }
}

Room三要素:

  • Dao:用来处理数据库操作,如增删改查,编译的时候会生成_impl结尾的实现类,实现在DAO中定义的增删改查方法
  • Entity:实体类,一个实体类对应一张表
  • Database:作为底层连接数据库的主要接入点,它是一个抽象的类,并继承RoomDatabase,编译的时候会自动生成一个_impl结尾的实现类,实现数据库以及表的创建及打开

代码:

Tips:这里使用了RxJava2.0里的Completable以及Maybe用来处理数据库操作,以及ui更新。
为什么用Maybe不用Single?Maybe是发送0个或1个数据,而single是发送一个数据并且结果要么成功要么错误抛异常。

创建一个DAO接口,这个接口主要是提供数据库增删改查方法,编译的时候会生成一个BookDao_Impl的实现类:
BookDao.java

@Dao
public interface BookDao {
    //这里使用Maybe
    @Query("SELECT * FROM book")
    Maybe<List<Book>> getAllBooks();

    @Query("SELECT * FROM book where bookid = :id")
    Maybe<Book> getBookById(int id);

    @Insert
    void insertAll(Book... books);

    @Delete
    void delete(Book book);

    @Update
    void updateBooks(Book... books);
}

Entity: 一个实体类对应一张表
Book.java

@Entity(tableName = "book")
public class Book {
    @PrimaryKey(autoGenerate = true)
    private int bookid;

    @ColumnInfo(name = "book_name")
    private String bookName;

    @ColumnInfo(name = "author")
    private String author;

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getAuthor() {
        return author;
    }

    public void setBookid(int bookid) {
        this.bookid = bookid;
    }

    public int getBookid() {
        return bookid;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookName() {
        return bookName;
    }
}

Database:抽象类,编译的时候会生成一个BookDatabase_Impl实现类,实现数据库和表的创建打开,并且实现bookDao()方法
BookDatabase.java

@Database(entities = {Book.class}, version = 1)
public abstract class BookDatabase extends RoomDatabase {
    public abstract BookDao bookDao();
}

DatabaseCallback.java 用于更新ui和提示操作结果

public interface DatabaseCallback {
    void onLoadBooks(List<Book> books);

    void onAdded();

    void onDeleted();

    void onUpdated();

    void onError(String err);
}

创建一个Manager方便我们对数据库进行管理操作:
注意:数据库的操作要在子线程中进行,不要在主线程进行操作
LocalCacheManager.java

public class LocalCacheManager {
    private static LocalCacheManager _instance;
    private BookDatabase db;
    private static final String DB_NAME = "book-database";

    public static LocalCacheManager getInstance(Context context) {
        if (_instance == null) {
            _instance = new LocalCacheManager(context);
        }
        return _instance;
    }

    public LocalCacheManager(Context context) {
        db = Room.databaseBuilder(context, BookDatabase.class, DB_NAME).build();
    }

    public void getBooks(final DatabaseCallback databaseCallback) {
        db.bookDao()
                .getAllBooks()
                //在io线程进行数据库操作
                .subscribeOn(Schedulers.io())
                //在主线程进行数据反馈
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<Book>>() {
                    @Override
                    public void accept(@NonNull List<Book> books) throws Exception {
                        databaseCallback.onLoadBooks(books);
                    }
                });
    }

    public void addBook(final DatabaseCallback databaseCallback, final Book... books) {
        //这里使用Completable是因为数据库处理完后不发射数据,只处理onComplete 和 onError 事件
        Completable
                .fromAction(new Action() {
                    @Override
                    public void run() throws Exception {
                        db.bookDao().insertAll(books);
                    }
                })
                //在主线程进行反馈
                .observeOn(AndroidSchedulers.mainThread())
                //在io线程进行数据库操作
                .subscribeOn(Schedulers.io())
                .subscribe(new CompletableObserver() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onComplete() {
                        databaseCallback.onAdded();
                    }

                    @Override
                    public void onError(Throwable e) {
                        databaseCallback.onError(e.getMessage());
                    }
                });
    }

    public void delete(final DatabaseCallback databaseCallback, final int id) {
        Completable
                .fromAction(new Action() {
                    @Override
                    public void run() throws Exception {
                        Book book = new Book();
                        book.setBookid(id);
                        db.bookDao().delete(book);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new CompletableObserver() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onComplete() {
                        databaseCallback.onDeleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        databaseCallback.onError(e.getMessage());
                    }
                });

    }

    public void getBookById(final DatabaseCallback callback, int id) {
        db.bookDao().getBookById(id).observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<Book>() {
                    @Override
                    public void accept(@NonNull Book book) throws Exception {
                        ArrayList<Book> list = new ArrayList<>();
                        list.add(book);
                        callback.onLoadBooks(list);
                    }
                });
    }

    public void updateBook(final DatabaseCallback callback, final Book... book) {
        Completable.fromAction(new Action() {
            @Override
            public void run() throws Exception {
                db.bookDao().updateBooks(book);
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new CompletableObserver() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onComplete() {
                        callback.onUpdated();
                    }

                    @Override
                    public void onError(Throwable e) {
                        callback.onError(e.getMessage());
                    }
                });
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener, DatabaseCallback {
    TextView panel;
    Button btnAdd, btnDelete, btnSelect,btnUpdate;
    EditText etName, etId, etAuthor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnAdd = findViewById(R.id.add);
        btnDelete = findViewById(R.id.delete);
        btnSelect = findViewById(R.id.select);
        etName = findViewById(R.id.name);
        etId = findViewById(R.id.id);
        etAuthor = findViewById(R.id.author);
        panel = findViewById(R.id.panel);
        btnUpdate = findViewById(R.id.update);
        btnAdd.setOnClickListener(this);
        btnDelete.setOnClickListener(this);
        btnSelect.setOnClickListener(this);
        btnUpdate.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.add:
                if (etName.getText().toString().trim().length() > 0 && etAuthor.getText().toString().trim().length() > 0 && etId.getText().toString().trim().length() > 0) {
                    final Book book = new Book();
                    book.setAuthor(etAuthor.getText().toString().trim());
                    book.setBookName(etName.getText().toString().trim());
                    LocalCacheManager.getInstance(getApplicationContext()).addBook(MainActivity.this, book);
                } else {
                    Toast.makeText(this, "Please input", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.delete:
                if (etId.length() > 0) {
                    LocalCacheManager.getInstance(getApplicationContext()).delete(MainActivity.this, Integer.parseInt(etId.getText().toString().trim()));
                }
                break;
            case R.id.select:
                if (etId.length() > 0) {
                    LocalCacheManager.getInstance(getApplicationContext()).getBookById(MainActivity.this, Integer.parseInt(etId.getText().toString().trim()));
                } else {
                    LocalCacheManager.getInstance(getApplicationContext()).getBooks(MainActivity.this);
                }
                break;
            case R.id.update:
                if (etId.length() > 0) {
                    final Book book = new Book();
                    book.setBookid(Integer.parseInt(etId.getText().toString().trim()));
                    book.setAuthor(etAuthor.getText().toString().trim());
                    book.setBookName(etName.getText().toString().trim());
                    LocalCacheManager.getInstance(getApplicationContext()).updateBook(MainActivity.this, book);
                }
                break;
        }
    }


    @Override
    public void onLoadBooks(List<Book> books) {
        panel.setText("");
        for (Book book : books) {
            panel.append("nID:" + book.getBookid() + "nName:" + book.getBookName() + "nAuthor:" + book.getAuthor());
        }
    }

    @Override
    public void onAdded() {
        Toast.makeText(this, "Add Successfully", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDeleted() {
        Toast.makeText(this, "Deleted Successfully", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpdated() {
        Toast.makeText(this, "Updated Successfully", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(String err) {
        Toast.makeText(this, err, Toast.LENGTH_SHORT).show();
    }
}

运行发现警告错误:

Error: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

解决办法:
在app module下的gradle文件里添加下面代码:

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
    ...
}

最后

相比Sqlite,Room上手非常简单,因为有关数据库以及表的创建,还有增删改查的实现,都在编译的时候自动帮你写好了,我们只需要关心在哪个线程调用哪个方法进行处理,不需要关心具体实现。但是还是建议新手有时间可以看看_Impl结尾的类里面是怎么实现的。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u010198148/article/details/78521558
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-14 01:17:19
  • 阅读 ( 392 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢