Android Room 库。无法访问主线程上的数据库

Android Room library. Cannot access database on the main thread

提问人:Drained 提问时间:11/9/2023 最后编辑:Mandar PanditDrained 更新时间:11/12/2023 访问量:32

问:

我有一个SQLite本地数据库,并实现了房间库。 当我完成项目时,本地数据库会创建。

尝试构建项目并得到这个:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dblearning.dbroom_test/com.dblearning.dbroom_test.RecyclerActivity}: 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.app.ActivityThread.performLaunchActivity(ActivityThread.java:3698)                                                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3855)                                                                                        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:105)                                                                            at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:136)                                                                 at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2267)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7964)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:553)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
    at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.kt:439)
    at androidx.room.RoomDatabase.query(RoomDatabase.kt:479)
    at androidx.room.util.DBUtil.query(DBUtil.kt:75)
    at com.dblearning.dbroom_test.DAO_Impl.getAll(DAO_Impl.java:165)
    at com.dblearning.dbroom_test.RecyclerActivity.onCreate(RecyclerActivity.java:29)
    at android.app.Activity.performCreate(Activity.java:8069)
    at android.app.Activity.performCreate(Activity.java:8049)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3668)

这是我的活动类:

public class RecyclerActivity extends AppCompatActivity  {
    private Button add,del,update;
    private EditText dataField;
    List<DataEntity>  dataEntityList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler);
        RoomDB db = Room.databaseBuilder(this,
                RoomDB.class, "tab").build();
        DAO dao = db.Dao();
        dataEntityList =dao.getAll();
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        Adapter entityAdapter = new Adapter(dataEntityList);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        recyclerView.setAdapter(entityAdapter);
           ... 
    }
}

这是我的 DAO 类:

@Dao
public interface DAO {

    @Query("SELECT * FROM tab")
    List<DataEntity> getAll();

    @Query("SELECT * FROM tab WHERE id IN (:userIds)")
    List<DataEntity> loadAllByIds(int[] userIds);
    @Query("DELETE FROM tab")
    void deleteAll();

    @Query("SELECT * FROM tab WHERE first_item LIKE :first AND " + "second_item LIKE :last LIMIT 1")
    DataEntity findByName(String first, String last);

    @Update
    void update(DataEntity entity);

    @Insert
    void insertAll(DataEntity... Entities);
    @Delete
    void delete(DataEntity Entity);
}

这是我的 Entity 类:

@Entity(  tableName ="tab" )
public class DataEntity {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    public int uid;

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    @ColumnInfo(name = "first_item")
    public String firstItem;

    public String getFirstItem() {
        return firstItem;
    }

    public void setFirstItem(String firstItem) {
        this.firstItem = firstItem;
    }

    @ColumnInfo(name = "second_item")
    public String secondItem;

    public String getSecondItem() {
        return secondItem;
    }

    public void setSecondItem(String secondItem) {
        this.secondItem = secondItem;
    }
    public DataEntity(){

    }

}

Excpected 通过 GUI 为将来的人口创建一个空数据库。 尝试编译我的项目时出错。 尝试谷歌解决并通过错误消息在此处搜索它,但只找到了 kotlin。

java android-sqlite android-room crud

评论

0赞 dev.bmax 11/9/2023
您可以在 Codelab 中找到解决方案:developer.android.com/codelabs/android-room-with-a-view
0赞 Chirag Thummar 11/9/2023
您需要在其中定义逻辑,该逻辑将处理与数据库相关的所有操作,并在 Thread 上执行该操作。ViewModelIO

答:

1赞 Drained 11/10/2023 #1

您可以在 Codelab 中找到解决方案:developer.android.com/codelabs/android-room-with-a-view – dev.bmax

您需要在 ViewModel 中定义逻辑,该逻辑将处理 所有与数据库相关的操作,并在 IO 线程上执行。– 奇拉格·图玛尔

我添加了一个 ViewModel 和 Repository,并在我的活动中使用它。我的应用程序已构建。 CRUD 操作现在工作正常。

developer.android.com/codelabs/android-room-with-a-view 我按照这些步骤创建了一个带有存储库的 ViewModel。在添加带有 Repository 类的 ViewModel 并将其应用于我的项目之后。

评论

0赞 Szzaass 11/11/2023
如果你在自我回答中分享你所做的事情的例子,它会帮助下一个可能有同样问题的人,所以这会很好=) 此外,如果问题已解决,您可能希望将答案标记为正确,以表明此问题已解决!干得好!