使用 java 在 android 中添加数据存储空间时出现问题
Problem in adding Room for data storage in android using java
我试图在 java 中实现用于持久数据存储的 Room。但是我 运行 遇到了问题。
In first try:
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
上面的应用程序崩溃并出现错误:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
每当我尝试将数据插入数据库时。
In the second try:
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
ListenableFuture<Integer> addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
将 return 类型更改为持有 ListenableFuture<Integer>
因为 official doc 要求这样做。
该应用程序未成功构建并显示以下错误:
error: Not sure how to handle insert method's return type.
所以,我的问题是如何使用带 java 的空间正确并成功地将数据插入数据库中。
请帮忙
您基本上是用应用程序的第一个 运行 创建了数据库,并试图在主线程上访问数据库,这会引发错误。
当您更改数据库并尝试 运行 应用程序时,您更改了数据库方案但未提供到新版本的迁移。
更改数据库的解决方案是,打开设备管理器并删除您的数据库,这会强制系统使用您更新的数据库方案创建一个新的数据库实例。或者你可以提供一个迁移,当你更新一个已经在生产中的应用程序的数据库方案时,这是必要的
您试图从主线程访问数据库的错误解决方案是,数据库操作需要异步处理并且不允许阻塞主线程。
您需要创建一个访问数据库的线程,使用 kotlin,您可以简单地创建一个协程,然后 运行 将操作作为协程。使用 Java 你应该使用 RXJava
要在 UI 线程中使用 Room,您需要按如下方式初始化数据库
database = Room.databaseBuilder(YOUR_CONTEXT, AppDatabase.class, "database")
.allowMainThreadQueries() //this string need for working in UI thread
.build();
但不建议在生产代码中这样做
- 我从未使用过 Guava,但这里有一个 guide 用于使用 ListenableFuture。
正如 Dominik Wuttke 所说,您可以使用协程或 RxJava 而不是 ListenableFuture 进行异步工作。
在网上折腾了好久,才知道可以用下面两种方法来写insert query:
- Using a thread class
Operations.java
public class Operations{
private MyDao myDao;
public Operations(Context context){
MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
.fallbackToDestructiveMigration()
.build();
myDao = db.myDao();
}
public void insertUser(UserDetails userDetails){
new Thread{
@override
public void run(){
myDao.addUser(userDetails);
}
}.start();
}
}
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
或
- Using ExecutorService class
Operations.java
public class Operations{
private MyDao myDao;
public Operations(Context context){
MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
.fallbackToDestructiveMigration()
.build();
myDao = db.myDao();
}
public void insertUser(UserDetails userDetails){
MyDatabase.databaseWriteExecutor.execute(()->{
notesDb.notesDao().addNote(note));
}
}
}
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public static final ExecutorService databaseWriteExecutor =
Executors.newFixedThreadPool(2);
public abstract MyDao myDao();
}
我试图在 java 中实现用于持久数据存储的 Room。但是我 运行 遇到了问题。
In first try:
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
上面的应用程序崩溃并出现错误:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
每当我尝试将数据插入数据库时。
In the second try:
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
ListenableFuture<Integer> addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
将 return 类型更改为持有 ListenableFuture<Integer>
因为 official doc 要求这样做。
该应用程序未成功构建并显示以下错误:
error: Not sure how to handle insert method's return type.
所以,我的问题是如何使用带 java 的空间正确并成功地将数据插入数据库中。
请帮忙
您基本上是用应用程序的第一个 运行 创建了数据库,并试图在主线程上访问数据库,这会引发错误。
当您更改数据库并尝试 运行 应用程序时,您更改了数据库方案但未提供到新版本的迁移。
更改数据库的解决方案是,打开设备管理器并删除您的数据库,这会强制系统使用您更新的数据库方案创建一个新的数据库实例。或者你可以提供一个迁移,当你更新一个已经在生产中的应用程序的数据库方案时,这是必要的
您试图从主线程访问数据库的错误解决方案是,数据库操作需要异步处理并且不允许阻塞主线程。
您需要创建一个访问数据库的线程,使用 kotlin,您可以简单地创建一个协程,然后 运行 将操作作为协程。使用 Java 你应该使用 RXJava
要在 UI 线程中使用 Room,您需要按如下方式初始化数据库
database = Room.databaseBuilder(YOUR_CONTEXT, AppDatabase.class, "database") .allowMainThreadQueries() //this string need for working in UI thread .build();
但不建议在生产代码中这样做
- 我从未使用过 Guava,但这里有一个 guide 用于使用 ListenableFuture。
正如 Dominik Wuttke 所说,您可以使用协程或 RxJava 而不是 ListenableFuture 进行异步工作。
在网上折腾了好久,才知道可以用下面两种方法来写insert query:
- Using a thread class
Operations.java
public class Operations{
private MyDao myDao;
public Operations(Context context){
MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
.fallbackToDestructiveMigration()
.build();
myDao = db.myDao();
}
public void insertUser(UserDetails userDetails){
new Thread{
@override
public void run(){
myDao.addUser(userDetails);
}
}.start();
}
}
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public abstract MyDao myDao();
}
或
- Using ExecutorService class
Operations.java
public class Operations{
private MyDao myDao;
public Operations(Context context){
MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
.fallbackToDestructiveMigration()
.build();
myDao = db.myDao();
}
public void insertUser(UserDetails userDetails){
MyDatabase.databaseWriteExecutor.execute(()->{
notesDb.notesDao().addNote(note));
}
}
}
MyDao.java
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addUser(UserDetails userDetails);
}
MyDatabase.java
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public static final ExecutorService databaseWriteExecutor =
Executors.newFixedThreadPool(2);
public abstract MyDao myDao();
}