1

センサー データをキャプチャしてデータベースに書き込む Recorder クラスがあります。すべてのデータベース処理は 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 エラーが発生しています。Recorder でデータベースが初期化されないようにすれば、ANR エラーは発生しません。

この Runnable がここで UI スレッドをブロックしている可能性はありますか? コールバックはなく、UI スレッドがデータベース接続を開こうとすることはありません。少なくとも、そうするつもりはありません。

ANR の traces.txt を調べたところ、スレッド「メイン」が実行されていることがわかりました。

 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 に答える