Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I am using this approach: I have a field in the activity which stores the thread. In onRetainNonConfigurationInstance() answer this field. It gets saved this way and it is available to the fresh instance of the activity later.</p> <p>In onStart() I get the thread from getLastNonConfigurationInstance(). This is either null (thread not jet started) or its the reference to the thread saved by onRetainNonConfigurationInstance(). If you are showing (and need to restore) a progress dialog you should also have a state in the thread (e.g. STARTED, RUNNING, DONE, and so on) to handle restoring the progress display in onStart().</p> <p>If you need to communicate with the thread you might want to inject a handler (e.g. as parameter to the thread's constructor). </p> <p>Here is an example. The thread reads GPS data from a database for later post-processing. I tried to only show the relevant code here, method names of omitted methods should speak for themselfes,</p> <p>This is all from the activity class:</p> <pre><code>private ProgressDialog progressDialog = null; private LoadGpsDataThread loadGpsLogThread = null; </code></pre> <p>This is the handler used to communicate:</p> <pre><code>/** * 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 &amp;&amp; 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; } } }; </code></pre> <p>Here is the method, which starts the thread, note the handler as constructor parameter:</p> <pre><code>/** * Load the GPS data from the database. * @param loading if &lt;code&gt;true&lt;/code&gt; 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(); } </code></pre> <p>Here is the start logic:</p> <pre><code>@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(); } </code></pre> <p>This is the thread as inner class:</p> <pre><code>/** * 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() &amp;&amp; (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"); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload