2012-09-24 25 views
1

我有一个类,录音机,捕捉传感器数据并将其写入到数据库。所有数据库处理都在记录器中进行。在这里我正在一个新的线程中运行它。 mContext来自getApplicationContext()。SQLite的相互作用导致ANR

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

下面是相关位的记录:

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线程永远不会尝试打开数据库连接,至少我不打算这么做。

我看着traces.txt的ANR,故称线程 “主” 被执行:

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

任何指针?我很困惑。

+0

也许使用的主要应用程序上下文是什么问题?如果你被困住了,想要尝试一些东西,创建一个新的Service类来包装你的Recorder逻辑,然后使用该服务作为上下文 – Mike

回答

0

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

Runnable不阻止主应用程序线程(又名“UI线程”)。 onSensorChanged()阻止主应用程序线程,因为onSensorChanged()被称为主应用程序线程,因此你的主应用程序线程做磁盘I/O。

0

我有(错误和愚蠢)假设从非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()) 
     ); 
    } 

这似乎运作良好。