"无法访问主线程上的数据库" AsyncTask中的异常

时间:2018-04-11 16:19:14

标签: java android android-room android-livedata

我用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)

2 个答案:

答案 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