Android 我的Runnable中的Sqlite交互正在导致ANR

Android 我的Runnable中的Sqlite交互正在导致ANR,android,multithreading,android-sqlite,Android,Multithreading,Android Sqlite,我有一个类,Recorder,它捕获传感器数据并将其写入数据库。所有数据库处理都发生在记录器中。在这里,我在一个新的线程中运行它。mContext来自getApplicationContext() 以下是记录器的相关位: public Recorder(SensorManager sensorManager, Context context){ mSensorManager = sensorManager; mContext = context; } void start(){

我有一个类,Recorder,它捕获传感器数据并将其写入数据库。所有数据库处理都发生在记录器中。在这里,我在一个新的线程中运行它。mContext来自getApplicationContext()

以下是记录器的相关位:

public Recorder(SensorManager sensorManager, Context context){
    mSensorManager = sensorManager;
    mContext = context;
}

void start(){               
    List <Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
    for(Sensor sensor : sensorList){
        mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
    }
}

public void onSensorChanged(SensorEvent event) {
    SensorDatabase dbHelper = new SensorDatabase(mContext);
    mDb = dbHelper.getWritableDatabase();

    if(mDb != null && mDb.isOpen()){
        ContentValues values = new ContentValues();
        values.put(DataColumns.ACCURACY, event.accuracy);
        // more values stuff ... 

        mDb.insert(SensorDatabase.TABLE_NAME, null, values);
        mDb.close();
    }
}
有什么建议吗?我很困惑

这个Runnable怎么会在这里阻塞UI线程

Runnable
没有阻塞主应用程序线程(也称为“UI线程”)
onSensorChanged()
正在阻止主应用程序线程,因为在主应用程序线程上调用了
onSensorChanged()
,因此您在主应用程序线程上执行磁盘I/O

这个Runnable怎么会在这里阻塞UI线程

Runnable
没有阻塞主应用程序线程(也称为“UI线程”)
onSensorChanged()
正在阻止主应用程序线程,因为在主应用程序线程上调用了
onSensorChanged()
,因此您正在主应用程序线程上执行磁盘I/O。

我曾经(错误地、愚蠢地)假设从非ui线程注册事件侦听器将使侦听器位于所述非ui线程上。为了实现所需的功能,我执行了以下操作,并显式地为registerListener方法提供了一个新的处理程序:

    mThread = new HandlerThread("RecorderThread");
    mThread.start();

    List <Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
    for(Sensor sensor : sensorList){
        mSensorManager.registerListener(
                Recorder.this, 
                sensor, 
                SensorManager.SENSOR_DELAY_FASTEST, 
                new Handler(mThread.getLooper())
        );
    } 
mThread=newHandlerThread(“RecorderThread”);
mThread.start();
List sensorList=mSensorManager.getSensorList(Sensor.TYPE_ALL);
用于(传感器:传感器列表){
mSensorManager.registerListener(
录音机,这个,
传感器
SensorManager.SENSOR\u延迟\u最快,
新处理程序(mThread.getLooper())
);
} 
这似乎很有效

我(错误地、愚蠢地)假设从非ui线程注册事件侦听器会将侦听器放在所述非ui线程上。为了实现所需的功能,我执行了以下操作,并显式地为registerListener方法提供了一个新的处理程序:

    mThread = new HandlerThread("RecorderThread");
    mThread.start();

    List <Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
    for(Sensor sensor : sensorList){
        mSensorManager.registerListener(
                Recorder.this, 
                sensor, 
                SensorManager.SENSOR_DELAY_FASTEST, 
                new Handler(mThread.getLooper())
        );
    } 
mThread=newHandlerThread(“RecorderThread”);
mThread.start();
List sensorList=mSensorManager.getSensorList(Sensor.TYPE_ALL);
用于(传感器:传感器列表){
mSensorManager.registerListener(
录音机,这个,
传感器
SensorManager.SENSOR\u延迟\u最快,
新处理程序(mThread.getLooper())
);
} 

这似乎很有效

也许使用主应用程序上下文是问题所在?如果您感到困惑,想尝试一些东西,请创建一个新的服务类来包装您的记录器逻辑,然后将该服务用作上下文可能是使用主应用程序上下文的问题?如果您感到困惑,想尝试一些东西,请创建一个新的服务类来包装记录器逻辑,然后将该服务用作上下文
    mThread = new HandlerThread("RecorderThread");
    mThread.start();

    List <Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
    for(Sensor sensor : sensorList){
        mSensorManager.registerListener(
                Recorder.this, 
                sensor, 
                SensorManager.SENSOR_DELAY_FASTEST, 
                new Handler(mThread.getLooper())
        );
    }