我有一个类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错误。如果我这样做,以便数据库不在记录器中初始化,则没有ANR错误。
这个Runnable怎么能在这里阻止UI线程?没有回调,UI线程永远不会尝试打开数据库连接,至少我不打算这样做。
我查看了ANR的traces.txt,它说线程“main”正在执行:
android.database.sqlite.SQLiteStatement.native_executeSql(Native Method)
任何指针?我很困惑。
答案 0 :(得分:0)
这个Runnable怎么能在这里阻止UI线程?
Runnable
未阻止主应用程序线程(a.k.a。,“UI线程”)。 onSensorChanged()
阻塞了主应用程序线程,因为在主应用程序线程上调用onSensorChanged()
,因此您在主应用程序线程上执行磁盘I / O.
答案 1 :(得分:0)
我(错误地,愚蠢地)假设从非ui线程注册事件监听器会将监听器放在所述非ui线程上。为了完成所需的操作,我做了以下操作,并明确地为registerListener方法提供了一个新的Handler:
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())
);
}
这似乎运作良好。