Android Wear - 运行 在单独的线程上使用 Java 房间数据库指令?

Android Wear - Run Room Database Instructions on a Separate Thread using Java?

我编写了一个简单的应用程序,用于检测来自智能手表 运行ning Android Wear OS 上传感器的光体积描记图 (PPG) 信号。我目前正尝试使用 Room 记录该数据,以便我可以访问数据并对其进行分析。当我尝试将数据插入数据库时​​,我 运行 遇到了一个问题,出现以下错误:

2022-01-08 14:15:13.435 5482-5482/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.ppg_extraction_final, PID: 5482
    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.java:469)
        at androidx.room.RoomDatabase.beginTransaction(RoomDatabase.java:553)
        at com.example.ppg_extraction_final.db.PpgDao_Impl.add(PpgDao_Impl.java:58)
        at com.example.ppg_extraction_final.ui.MainActivity.writePpgData(MainActivity.java:98)
        at com.example.ppg_extraction_final.ui.MainActivity.onSensorChanged(MainActivity.java:72)
        at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:833)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:326)
        at android.os.Looper.loop(Looper.java:160)
        at android.app.ActivityThread.main(ActivityThread.java:6680)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我知道我收到这个错误是因为我试图在主线程上操作数据库,这会导致我的 UI 速度变慢。我也知道 Kotlin 协程以相对较少的样板文件为这个问题提供了一个很好的解决方案。但是,在 Java 中编写了我的程序后,我对更正此错误的最佳方法有点迷茫。我是否可以在我当前的应用程序结构中以某种方式实现 kotlin 协程?将整个应用程序迁移到 kotlin 是否值得?在 java 中是否有其他方法可以执行此操作?

这是我的 MainActivity 的相关部分。 PpgDatabase、PpgData 和 PpgDao 分别指我的数据库、实体和 DAO 类。这些都在他们自己的文件中。如果需要此代码,请告诉我!

public class MainActivity extends Activity implements SensorEventListener {

    private TextView textView;
    private SensorManager sensorManager;
    PpgDatabase ppgDatabase;
    PpgDao ppgDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        com.example.ppg_extraction_final.databinding.ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        textView = findViewById(R.id.dataText);

        // Instantiate sensor manager
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

        // Obtain db instance
        ppgDatabase = DatabaseClient.getInstance(getApplicationContext()).getPpgDatabase();

        // Instantiate ppg dao
        ppgDao = ppgDatabase.getPpgDao();
    }

    public void onStartClick(View view) {
        // Begin listening for sensor events on start click
        // 65572 = PPG sensor type
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(65572),
                sensorManager.SENSOR_DELAY_NORMAL);
    }

    public void onStopClick(View view) {
        // Stop listening for sensor events on stop click
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // 65572 = PPG sensor type
        if (event.sensor.getType() == 65572)
            writePpgData(ppgDao, event);

    }

    public void writePpgData(PpgDao ppgDao, SensorEvent event) {
        // Function for adding sensor event to db
        PpgData ppgData = new PpgData();

        ppgData.setCh0(event.values[0]);
        ppgData.setCh1(event.values[1]);

        ppgDao.add(ppgData);
    }

}

如有任何建议,我将不胜感激。谢谢!

我认为 Kotlin 是首选。

但是因为这个问题本身不应该让你困扰这么久,我认为你应该能够使用 Executors。

查看 Room Basic Sample by Google:

特别是 Database initialization

这里executors.diskIO()用于在后台线程上与DataBase交互

执行器已定义 here