2012-01-29 58 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

相關問題