2012-01-29 5 views
0

アクティビティのoncreate()メソッドにスレッドがいくつかあります。オリエンテーションが変更されると、スレッドが再び再開されます(スレッドが変更されるたびにスレッドの新しいインスタンスが作成されます)。オリエンテーションの変更でスレッドを再起動しないようにする

私はandroid:configChangesまたはandroid:screenOrientationを使用しません。アクティビティはオリエンテーションに依存するためです。

+0

画面の向きを維持したいのですか? –

答えて

1

使用android:configChangesが、オーバーライド方法でのみsuper.onConfigurationCanged()メソッドを呼び出す(またはそれを上書きしません。

@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(); 
} 

これは内部クラスとしてスレッドです一般的に)。

回転時にCreate()は呼び出されず、トレッドは再開されませんが、レイアウトは回転します。

+0

非常に良い。私の混乱を解消した。 – Vivek

2

私はこのアプローチを使用しています: スレッドに格納されているアクティビティにフィールドがあります。 onRetainNonConfigurationInstance()でこのフィールドに答えます。この方法で保存され、後でアクティビティの新しいインスタンスで使用できます。

onStart()では、getLastNonConfigurationInstance()からスレッドを取得します。これは、null(スレッドはジェットが開始されていない)またはonRetainNonConfigurationInstance()によって保存されたスレッドへの参照です。 進行状況ダイアログを表示している場合(そして復元する必要がある場合)、onStart()の進行状況表示を復元するためのスレッド内の状態(STARTED、RUNNING、DONEなど)も必要です。

スレッドと通信する必要がある場合は、ハンドラを挿入することができます(スレッドのコンストラクタへのパラメータなど)。

ここは例です。スレッドは後で後処理するためにデータベースからGPSデータを読み込みます。

:これはハンドラである

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

の通信に使用される:私は

これは、アクティビティクラスからのすべてのですが、省略メソッドのメソッド名は、themselfesのために話すべきで、ここでしか関連するコードを表示しようとしましたここで

/** 
* 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(); 
} 
ここでは

は開始論理である:、

/** 
* 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

ありがとうございました。一例がさらに評価されます。 – Vivek

+0

私は例を追加しました。スペースと読書を節約するために、私は関連する部分だけを表示しようとしました。 – Stefan

関連する問題