1

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

        Runnable startRunnable = new Runnable(){
            public void run() {
                Recorder recorder = new Recorder((SensorManager) getSystemService(SENSOR_SERVICE), mContext);
                recorder.start();
            }
        };
        recorderThread = new Thread(startRunnable);
        recorderThread.start();

以下是 Recorder 的相关位:

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();
    }
}

应用程序记录数据,但出现 ANR 错误。如果我这样做是为了不在记录器中初始化数据库,则不会出现 ANR 错误。

这个 Runnable 怎么会在这里阻塞 UI 线程?没有回调,UI 线程从不尝试打开数据库连接,至少我不打算这样做。

我查看了 ANR 的 traces.txt,它说线程“main”正在执行:

 android.database.sqlite.SQLiteStatement.native_executeSql(Native Method) 

任何指针?我很困惑。

4

2 回答 2

1

我曾经(错误地,愚蠢地)假设从非 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())
        );
    } 

这似乎运作良好。

于 2012-10-02T00:08:06.677 回答
0

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

不会阻塞主Runnable应用程序线程(又名“UI 线程”)。onSensorChanged()正在阻塞主应用程序线程,因为在onSensorChanged()主应用程序线程上被调用,因此您正在主应用程序线程上执行磁盘 I/O。

于 2012-09-24T18:09:06.523 回答