2012-01-29 90 views
0

我的活动的oncreate()方法中有一些线程。当方向改变时,线程再次重新启动(在每个方向改变时创建线程的新实例)。避免在方向更改时重新启动线程

我不想使用android:configChangesandroid:screenOrientation。因为活动取决于方向。

+0

想要了解更多关于屏幕定位维护的信息吗? – 2012-01-29 13:23:19

回答

1

使用android:configChanges,但在overrided 方法只调用super.onConfigurationCanged()方法(或不重写,通常)。

旋转时间onCreate()不会被调用,您的踏板不会重新启动,但您的布局将被旋转。

+0

非常好。清除了我的困惑。 – Vivek 2012-01-29 16:57:31

2

我正在使用这种方法: 我在存储线程的活动中有一个字段。在onRetainNonConfigurationInstance()回答这个字段。它以这种方式得到保存,稍后可用于新活动的新实例。

在onStart()我从getLastNonConfigurationInstance()中获得线程。这可以是null(线程不是jet开始的),也可以是onRetainNonConfigurationInstance()保存的线程的引用。 如果您正在显示(并需要恢复)进度对话框,您还应该在线程中拥有一个状态(例如STARTED,RUNNING,DONE等)来处理onStart()中的进度显示。

如果您需要与线程进行通信,您可能需要注入处理程序(例如作为线程构造函数的参数)。

这里是一个例子。该线程从数据库中读取GPS数据以供日后后处理。我想只有在这里显示相关代码的省略方法的方法名称应该为themselfes说话,

这是所有从活动类:

private ProgressDialog progressDialog = null; 
private LoadGpsDataThread loadGpsLogThread = null; 

这是处理器用来沟通:

/** 
* This handler updates the progress dialog when the logged GPS data is loaded. 
*/ 
final Handler progressHandler = new Handler() { 
    @Override 
    public void handleMessage(final Message msg) { 
     Bundle b; 
     switch(msg.arg2) { 
     case UPDATE_LOADER: 
      // Update from GPS data loading thread 
      final int total = msg.arg1; 
      if(GpsPostprocessingActivity.this.progressDialog != null) 
       GpsPostprocessingActivity.this.progressDialog.setProgress(total); 
      if(GpsPostprocessingActivity.this.loadGpsLogThread != null && GpsPostprocessingActivity.this.loadGpsLogThread.state == STATE_DONE) { 
       GpsPostprocessingActivity.this.dismissProgress(); 
       GpsPostprocessingActivity.this.fillGraphView(); 
      } 
      break; 
     case IGpsDataPostProccessor.STATUS_ANALYZER: 
      GpsPostprocessingActivity.this.statusView.setText(msg.arg1); 
      break; 
     case IGpsDataPostProccessor.UPDATE_ANALYZER: 
      int sample; 
      switch(msg.arg1) { 
      // ... 
      } 
      break; 
     case IGpsDataPostProccessor.GRAPH_UPDATE: 
       GpsPostprocessingActivity.this.fillGraphView(); 
       break; 
      } 
      break; 
     } 
    } 
}; 

这里是方法,它开始线程,注意处理程序构造函数的参数:

/** 
* Load the GPS data from the database. 
* @param loading if <code>true</code> the load thread is already 
*     running. In this case only the progress dialog is opened. 
*/ 
private void loadGpsData(final boolean loading) { 
    if(DEBUG) 
     Log.d(TAG, "loadGpsData: Loading GPS data, already loading = " + loading); 
    final int dataSize = this.gpsFlight.size(); 

    final String title = this.globalState.getString(R.string.titel_load_gps_data); 
    final String msg = this.globalState.getFormattedTemplate(R.string.msg_tmpl_loading_gps_data, this.flightDesc); 
    this.showProgress(title, msg, dataSize); 

    if(! loading) { 
     this.loadGpsLogThread = new LoadGpsDataThread(this.progressHandler); 
     this.loadGpsLogThread.start(); 
    } 
} 

@Override 
public Object onRetainNonConfigurationInstance() { 
    // Dialog is removed in onSaveInstanceState(), see comment there 
    // Check that there is a worker thread that 
    // needs preserving 
    if (this.loadGpsLogThread != null) { 
     // remove reference to this activity (important to avoid memory leak) 
     this.loadGpsLogThread.handler = null; 
     // Return the instance to be retained 
     if(DEBUG) 
      Log.d(TAG, "onRetainNonConfigurationInstance: saved process"); 
     return this.loadGpsLogThread; 
    } 
    return super.onRetainNonConfigurationInstance(); 
} 

这里是启动逻辑:

@Override 
protected void onStart() { 
    if(DEBUG) 
     Log.d(TAG, "onStart"); 
    super.onStart(); 

    this.refreshData(); 
    this.flightView.setText(this.flightDesc); 
    this.logView.setText(this.getGpsLogDescription()); 
    this.statusView.setText(null); 
    this.initProfileSpinner(); 
    // graphView is set asynchronously by the GPS data loading thread 

    // Get the last load thread and check whether it is still running 
    if (this.getLastNonConfigurationInstance() != null) { 
     this.loadGpsLogThread = (LoadGpsDataThread) this.getLastNonConfigurationInstance(); 
     this.loadGpsLogThread.handler = this.progressHandler; 
     switch (this.loadGpsLogThread.state) { 
     case STATE_RUNNING: 
      // Show the progress dialog again 
      this.loadGpsData(true); 
      break; 
     case STATE_NOT_STARTED: 
      // Close the progress dialog in case it is open 
      this.dismissDialog(PROGRESS_DIALOG); 
      break; 
     case STATE_DONE: 
      this.loadGpsLogThread = null; 
      // Close the progress dialog in case it is open 
      this.dismissDialog(PROGRESS_DIALOG); 
      break; 
     default: 
      // Close the progress dialog in case it is open 
      // Get rid of the sending thread 
      if(DEBUG) 
       Log.d(TAG, "Unknown progress thread state"); 
      this.dismissProgress(); 
     } 
    } 
    else { 
     if(! this.globalState.detectorState.isGpsDataCacheAvailable(this.gpsFlight)) { 
      this.loadGpsData(false); 
      this.analysisResult = null; 
     } 
     else 
      // data already loaded 
      this.fillGraphView(); 
    } 

    this.graphView.setShowLines(this.globalState.getBooleanPref(IPreferences.PREFS_GPS_GRAPH_LINES)); 
    this.processSubActivityResult(); 
} 

这是线程的内部类:

/** 
* This thread loads the GPS data from the database and 
* updates the progress dialog via the handler. 
*/ 
private class LoadGpsDataThread extends Thread { 
    Handler handler; 
    int state; 
    int stepsDone; 

    LoadGpsDataThread(final Handler h) { 
     this.handler = h; 
     this.state = STATE_NOT_STARTED; 
    } 

    @Override 
    public void run() { 
     this.state = STATE_RUNNING; 
     this.stepsDone = 0; 
     final Cursor c = GpsPostprocessingActivity.this.queryGpsData(); 
     try { 
      while (c.moveToNext() && (this.state == STATE_RUNNING)) { 
       final TrackData row = GpsPostprocessingActivity.this.globalState.getDb().readGpsData(c); 
       GpsPostprocessingActivity.this.globalState.detectorState.gpsData[this.stepsDone] = row; 
       this.stepsDone += 1; 

       if(this.handler != null) { 
        // can be null if the activity has been destroyed 
        final Message msg = this.handler.obtainMessage(); 
        msg.arg1 = this.stepsDone; 
        msg.arg2 = UPDATE_LOADER; 
        this.handler.sendMessage(msg); 
       } 
      } 
     } 
     finally { 
      this.state = STATE_DONE; 
      c.close(); 
     } 
     if(DEBUG) 
      Log.d(TAG, "Data load thread finished"); 
    } 
} 
+0

感谢您的建议+1。一个例子会更好理解。 – Vivek 2012-01-29 13:34:01

+0

好的,我添加了一个例子。为了节省空间和阅读,我只试图显示相关部分。 – Stefan 2012-01-29 17:09:31

相关问题