我的活動的oncreate()方法中有一些線程。當方向改變時,線程再次重新啓動(在每個方向改變時創建線程的新實例)。避免在方向更改時重新啓動線程
我不想使用android:configChanges
或android:screenOrientation
。因爲活動取決於方向。
我的活動的oncreate()方法中有一些線程。當方向改變時,線程再次重新啓動(在每個方向改變時創建線程的新實例)。避免在方向更改時重新啓動線程
我不想使用android:configChanges
或android:screenOrientation
。因爲活動取決於方向。
使用android:configChanges
,但在overrided 方法只調用super.onConfigurationCanged()
方法(或不重寫,通常)。
旋轉時間onCreate()不會被調用,您的踏板不會重新啓動,但您的佈局將被旋轉。
非常好。清除了我的困惑。 – Vivek 2012-01-29 16:57:31
我正在使用這種方法: 我在存儲線程的活動中有一個字段。在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");
}
}
想要了解更多關於屏幕定位維護的信息嗎? – 2012-01-29 13:23:19