2011年9月17日 星期六

[AndroidDev] Process and Thread

[Process]
* 如果 application 在沒有任何 component 被執行中的情況下開啟,則會開啟新的 process 執行單一執行緒;若是已有被執行中的 component,則會在相同的 process and thread 執行你所要執行的功能。
  • When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution.
  • By default, all components of the same application run in the same process and thread (called the "main" thread).
  • If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process and uses the same thread of execution.
* However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.
  • <activity>, <service>, <receiver>, and 中可利用 android:process 屬性來指定其 component 要跑在那個 process 上。
  • <application> 也能利用 android:process 去設定所有 components 的預設值。
  • By default, all components of the same application run in the same process and most applications should not change this.
* Process Types
To determine which processes to keep and which to kill, the system places each process into an "importance hierarchy" based on the components running in the process and the state of those components.
  1. Foreground process: user 正在執行中的 process。ex:
    • User 正在使用的 activity (activity is onResume())。
    • User 正在使用的 activity 所使用的 service
    • The Service has called startForeground().
    • A Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).
    • A BroadcastReceiver that's executing its onReceive() method.
  2. Visible process: A process that doesn't have any foreground components, but still can affect what the user sees on screen. ex:
    • An Activity that is not in the foreground, but is still visible to the user (its onPause() method has been called). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.
    • A Service that's bound to a visible (or foreground) activity.
  3. Service process: A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories.
  4. Background process: A process holding an activity that's not currently visible to the user (the activity's onStop() method has been called). These processes have no direct impact on the user experience.
    • Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. 
    • If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state.
  5. Empty process: A process that doesn't hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it.
    • A process running a service is ranked higher than a process with background activities.


[Thread]


* Main/UI Thread
  • When an application is launched, the system creates a thread of execution for the application, called "main."
  • It is in charge of dispatching events to the appropriate user interface widgets, including drawing events.
  • The thread in which your application interacts with components from the Android UI toolkit (components from the android.widget and android.view packages).
  • By default, the system does not create a separate thread for each instance of a component. All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from that thread.
  • If the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.
  • Is not thread-safe.


* Worker/Background Thread
  • If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads ("background" or "worker" threads).
  • Do not access the Android UI toolkit from outside the UI thread.
  • Android offers several ways to access the UI thread from other threads. ex:
// about Thread
new Thread(new Runnable() {
    Activity.runOnUiThread(Runnable)
}
View.post(Runnable)
View.postDelayed(Runnable, long)

// http://developer.android.com/reference/android/os/AsyncTask.html
public abstract class AsyncTask

// http://developer.android.com/reference/android/os/Handler.html
public class Handler

Using example:
new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();


* AsyncTask
You can then run the task by calling execute() from the UI thread.
public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }
    
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}


  • The method doInBackground() executes automatically on a worker thread.
  • onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread
  • You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread.


* Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread.


[Thread-safe methods]

* Service
  • When a call on a method implemented in an IBinder originates in the same process in which the IBinder is running, the method is executed in the caller's thread.
  • Because a service can have more than one client, more than one pool thread can engage the same IBinder method at the same time. IBinder methods must, therefore, be implemented to be thread-safe.


* Content Provider
  • A content provider can receive data requests that originate in other processes.
  • Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests—the methods query(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider's process, not the UI thread for the process. Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

* These are the another issue need be explored.


* Reference
- Processes and Threads | Android Developers

沒有留言:

張貼留言