当前位置: 首页 > 知识库问答 >
问题:

无法使用ThreadPoolExecutor访问主线程Android Room上的数据库

呼延俊风
2023-03-14

我得到了一个著名的错误“无法访问主线程上的数据库,因为它可能会长期锁定UI”但根据我的理解,我没有访问主线程中的数据库,因为我正在执行由ThreadPoolExecutor执行的Runnable中的调用。我做错了什么?

在下面的方法中,我使用runnable从网络获取数据并将其存储在本地数据库中。

private void refresh() {
    executor.execute(() -> {
        if (!dataSource.hasData()) {
            recipeService.getAllRecipes().enqueue(new Callback<List<Recipe>>() {
                @Override
                public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) {
                    dataSource.save(response.body());
                }

                @Override
                public void onFailure(Call<List<Recipe>> call, Throwable t) {
                    throw new RuntimeException(t);
                }
            });
        }

    });
}

数据源.保存:

@Override
    public void save(List<Recipe> recipes) {
        for (Recipe recipe : recipes) {
            recipeDao.insert(recipe);
            int count = 1;

            for (Ingredient ingredient : recipe.getIngredients()) {
                ingredient.setId(count++);
                ingredient.setRecipeId(recipe.getId());
                ingredientDao.insert(ingredient);
            }

            for (Step step : recipe.getSteps()) {
                step.setRecipeId(recipe.getId());
                stepDao.insert(step);
            }

        }
    }

执行人定义为:

@Provides
Executor executor() {
    return new ThreadPoolExecutor(4, 8, 60,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>());
}
06-18 03:03:38.653 27231-27231/com.github.alexpfx.udacity.nanodegree.android.baking_app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.github.alexpfx.udacity.nanodegree.android.baking_app, PID: 27231
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long periods of time.
at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:137)
at android.arch.persistence.room.RoomDatabase.beginTransaction(RoomDatabase.java:184)
at com.github.alexpfx.udacity.nanodegree.android.baking_app.data.local.RecipeDao_Impl.insert(RecipeDao_Impl.java:89)
at com.github.alexpfx.udacity.nanodegree.android.baking_app.recipe.RecipeLocalDataSource.save(RecipeLocalDataSource.java:34)
at com.github.alexpfx.udacity.nanodegree.android.baking_app.recipe.RecipesRepositoryImpl$1.onResponse(RecipesRepositoryImpl.java:49)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)

共有1个答案

冯枫
2023-03-14

您可以将实现更改为:

private void refresh() {

        if (!dataSource.hasData()) {
            recipeService.getAllRecipes().enqueue(new Callback<List<Recipe>>() {
                @Override
                public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) {

                executor.execute(() -> {
                    dataSource.save(response.body());
                  });
                }

                @Override
                public void onFailure(Call<List<Recipe>> call, Throwable t) {
                    throw new RuntimeException(t);
                }
            });
        }
}

onResponse函数总是在UITHREAD中调用。

 类似资料:
  • 在“我的活动”中实现了以下功能: 不幸的是,在执行上面的方法时,它会与下面的堆栈跟踪崩溃: 这个问题似乎与主线程上db操作的执行有关。但是,上面链接中提供的示例测试代码并不在单独的线程上运行:

  • 本文向大家介绍ThreadPoolExecutor线程池的使用方法,包括了ThreadPoolExecutor线程池的使用方法的使用技巧和注意事项,需要的朋友参考一下 ThreadPoolExecutor ThreadPoolExecutor线程池,java提供开发框架,管理线程的创建、销毁、优化、监控等。 有4种不同的任务队列: 1.ArrayBlockingQueue:基于数组结构的任务队列。

  • 这是运行命令后发生的情况: 启动:pid=4346 port=27017 dbpath=/var/lib/mongodb/data/db 64位host=era-inspiron-5559 2017-02-12T14:39:18.644+0530 I CONTROL[initandlisten]db版本v3.4.2 2017-02-12T14:39:18.644+0530 I控件[initandl

  • 在主活动中,我有LiveData,其中包含成员和单击侦听器。如果我点击一个成员,那么他的ID将通过intent.putExtra。该ID稍后会传递给在此活动中打开的方法。有了这个活动,我想看看一个会员的详细情况。在我的MemberInfo活动中,我标出了我的问题所在的一行。它显示了这个错误:无法访问主线程上的数据库,因为它可能会锁定用户界面很长一段时间。 我的DAO由以下代码组成: 这是我的主要活

  • 我正在尝试创建一个具有一定数量线程的ThreadPoolExector,但同时,我想控制池队列的大小。所以我使用完整的构造函数创建了执行器: 然而,这给了我一个非法辩论例外。如果我将构造函数更改为 它起作用了。如果我希望理想的线程数和最大线程数相同,为什么它不起作用呢。

  • 我的协同程序在主线程上运行,这是我在协同程序上下文中指定的: 但我还是犯了这个错误: 在我上面的协程调用到我的数据库。 这里是我的: 如果我的协同程序上下文在主线程上运行,为什么仍然会出现错误?