我用 LiveData 构建了一个简单的 Room 示例,但是得到了一个
Cannot access database on the main thread"- IllegalStateException
我的一般架构是带有 fragment 的 Activity , fragment 具有带有 Room 的 ViewModel 和 Repository。
我的调用从这里开始(我剪掉了 fragment ,点击调用该方法的按钮)。
我使用的是androidannotations,但应该与错误无关。
在我看来,它很直接,插入调用显然是在 AsyncTask 中,所以这就是为什么我真的对异常感到困惑的原因。
我的 View 模型:
class FragmentAddKeywordsViewModel extends AndroidViewModel {
KeywordsRepository repository;
public FragmentAddKeywordsViewModel(@NonNull Application application) {
super(application);
if (repository == null) {
repository = new KeywordRepository(application);
}
}
public void addKeyword(Keyword keyword) {
repository.addKeyword(keyword);
}
}
这是我的仓库:
public class KeywordsRepository {
private KeywordDao keywordDao;
public KeywordsRepository (Application application) {
KeywordDatabase db = KeywordDatabase.getDatabase(application);
keywordDao= db.keywordDao();
}
public void addKeyword(Keyword keyword) {
new insertAsyncTask(keywordDao).doInBackground(keyword);
}
private static class insertAsyncTask extends AsyncTask<Keyword, Void, Void> {
private KeywordDao mAsyncTaskDao;
insertAsyncTask(KeywordDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Keyword... params) {
mAsyncTaskDao.insert(params[0]); // This line throws the exception
Log.d(getClass().getSimpleName(), "do in background 1");
return null;
}
}
}
我的数据库
@Database(entities = {Keywords.class}, version = 1, exportSchema = false)
public abstract class KeywordDatabase extends RoomDatabase {
public abstract KeywordsDao keywordDao();
private static KeywordDatabase INSTANCE;
private static RoomDatabase.Callback sRoomDatabaseCallback =
new RoomDatabase.Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
};
public static KeywordDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (KeywordDatabase .class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
KeywordDatabase.class, "keywords")
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
}
最后但同样重要的是我的道
@Dao
interface KeywordDao {
@Query("SELECT * FROM keywords")
LiveData<List<Keyword>> getAllKeywords();
@Insert
void insert(Keyword keyword);
@Delete
void delete(Keyword keyword);
@Query("DELETE FROM keywords")
void deleteAll();
}
这就是我的错误堆栈的结尾:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:164) at android.arch.persistence.room.RoomDatabase.beginTransaction(RoomDatabase.java:211) at org.name.project.package.KeywordDao_Impl.insert(KeywordDao_Impl.java:81) at org.name.project.package.KeywordsRepository$insertAsyncTask.doInBackground(KeywordsRepository.java:42)
最佳答案
你需要调用execute
让asychtask的doInBackground
方法在后台运行
new insertAsyncTask(keywordDao).execute(keyword);
否则用这个
new insertAsyncTask(keywordDao).doInBackground(keyword);
您只是在调用类实例的方法。
类似的例子是 java 中的 Thread
,其中 threadInstance.start()
创建的线程不是 threadInstance.run()
关于java - "Cannot access database on the main thread"AsyncTask异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49780040/