我用LiveData构建了一个简单的Room示例,但是得到了一个
无法访问主线程上的数据库" - IllegalStateException
我的一般架构是具有ViewModel&的片段的活动。带房间的存储库。
我的电话从这里开始(我剪切了片段,点击了调用该方法的按钮)。
我使用androidannotations,但这不应该与错误有关。
在我看来,它的直接前进和插入调用显然是在AsyncTask中,所以这就是为什么我真的被异常所困惑。
我的ViewModel:
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
@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:无法访问main上的数据库 线程,因为它可能会长时间锁定UI。 在 android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:164) 在 android.arch.persistence.room.RoomDatabase.beginTransaction(RoomDatabase.java:211) 在 org.name.project.package.KeywordDao_Impl.insert(KeywordDao_Impl.java:81) 在 org.name.project.package.KeywordsRepository $ insertAsyncTask.doInBackground(KeywordsRepository.java:42)
答案 0 :(得分:3)
您需要致电execute
让asychtask的doInBackground
方法在后台运行
new insertAsyncTask(keywordDao).execute(keyword);
否则用这个
new insertAsyncTask(keywordDao).doInBackground(keyword);
你只是在调用类实例的方法。
类似的例子是java中的Thread
threadInstance.start()
创建的线程不是threadInstance.run()
答案 1 :(得分:1)
更改
public void addKeyword(Keyword keyword) {
new insertAsyncTask(keywordDao).doInBackground(keyword);
}
到
public void addKeyword(Keyword keyword) {
new insertAsyncTask(keywordDao).execute(keyword);
}
execute
会在后台主题中调用doInBackground
。