Android App Development - 07 Threading

Embed Size (px)

Citation preview

  1. 1. Threading
  2. 2. Threading When a component is started and no other component has been created for the same application, the system creates a new process. When a component is started and other components of the same application are created, the component runs in the same process of others. Each process consists of one or more Thread. There is a Main Thread for each process. All components in the same process are performed in the Main Thread. The unique identifier of the process in the system is defined by the package declared in the Manifest. Processes
  3. 3. Threading By default, all components of an application are executed in the same process. This management should not be changed, but you can start every single component in a custom process by defining its unique identifier in the Manifest: Es. Gestione dei Processi
  4. 4. Threading The system manages the processes trying to keep them as long as possible, but when the system needs memory to start another process it must delete some of them. To determine which of them can bedeleted, the system manages a hierarchy of importance of the processes. There are 5 importance levels to do this: Foreground Processes Visible Processes Service Processes Background Processes Empty Processes Process LifeCycle
  5. 5. Threading Android UI Toolkit is not thread-safe: the Main Thread is the onlyone that can handle GUI (this is also called the UI Thread). All components run in the same process and share the same Main Thread. For this, long operations like HTTP calls or DB query must be executed on a secondary thread, and not on the Main Thread because these would block the GUI. Until Android 2.3.x this was possible (although after a few seconds the user displayed an Application Not Responding Dialog), while from HoneyComb if you run this type of operation on the Main Thread is generated a NetworkOnMainThreadException. Main Thread
  6. 6. Threading The long running operations must be carried out on a secondary thread called Background Thread or Worker Thread. public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b =loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start(); } This sample code violates a platform rule because it changes the UI from a Secondary Thread. Background Thread
  7. 7. Threading To change the UI from a background thread, you can use the following methods: Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) Handler.post(Runnable) public void onClick(View v) { 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(); } Background Thread
  8. 8. Threading With the increasing complexity of operations, this type of management becomes more and more complicated and difficult to maintain. To simplify this management Android provides the AsyncTask object. A AsyncTask runs the code that runs in the background thread and the one in the Main Thread. public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png"); } private class DownloadImageTask extends AsyncTask { protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); } } AsyncTask
  9. 9. Threading A AsyncTask is defined by 3 generics types and 4 steps: Types: Params: input type Progress: update type Result: result type Steps: onPreExecute: MT executed before the secondary thread to show the user a possible graphical update doInBackground: BT long running operations to be executed in background. It can invoke the publishProgress(Progress...) method to notify the MT the updating progress (invoking onProgressUpdate()) onProgressUpdate: MT it0s used to show the progress to the user onPostExecute: MT it handles the result returned by the doInBackground() method AsyncTask
  10. 10. Threading Rules to use a AsyncTask (otherwise an IllegalStateException is thrown): It must be instantiated on Main Thread It must be started on Main Thread (AsyncTask.execute()) The steps cannot be invoked manually It can be executed only one time Until GingerBread (Android 2.3.x) the AsyncTask execution created more Threads in Thread Pool for a parallel execution. From HoneyComb (Android 3.0) every Task is executed serially in a Background Thread to limit errors. If you want to use parallelized tasks you need to use: AsyncTask.executeOnExecutor(THREAD_POOL_EXECUTOR) AsyncTask - Regole
  11. 11. Threading private class DownloadFilesTask extends AsyncTask { @Override protected void onPreExecute() { setProgressPercent(0); } @Override protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); if (isCancelled()) break; } return totalSize; } @Override protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } @Override protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } AsyncTask - Example
  12. 12. Threading LIMIT: When a task is executed in an Activity and Activity Recreation occurs, the Task is deleted along with the rest of the Activity and must then be rebooted again and restarted. SOLUTION 1: the use of application context instead of the Activity one SOLUTION 2: the use of Loaders LIMIT: A AsyncTask hasn't got a method to retrieve the result. SOLUTION 1: the use of an interface SOLUTION 2: the implementation of a Task as an Activity anonymous inner class SOLUTION 3: the use of Loaders AsyncTask - Limits
  13. 13. Threading They are available since HoneyComb (Android 3.0): Available for every single Activity or Fragment Useful for asynchronous loading of data They handle data source and send new results if they change Independents from Activity or Fragment lifecycle: they store result data not to be restart after Activity recreation. Loaders
  14. 14. Threading LoaderManager: Utility class used to manage every Loader instance of an Activity or Fragment. There is only one LoaderManager a Activity or Fragment. LoaderManager.LoaderCallbacks: a callback interface to retrieve the result data Loader: abstract class that executes the operations. There are Loader subclasses to simplify AsyncTask or Cursor management or you can develop your custom Loader. AsyncTaskLoader: Loader subclass that uses a AsyncTask to execute the operations CursorLoader: AsyncTaskLoader subclass to execute queries of a ContentProvider Loaders - Classes
  15. 15. Threading There is only one LoaderManager for Activity or Fragment, then typically Activity.onCreate() or Fragment.onActivityCreated() initializes a new Loader or retrieve a previously initiated one. public void onCreate(Bundle savedInstanceState) { getLoaderManager().initLoader(0, null, this); } LoaderManager.initLoader() parameters: Int: unique ID to identify the Loader instance Bundle: Key-Value Pair to pass any additional parameter LoaderManager.LoaderCallbacks: result managing instance. Loaders - Start
  16. 16. Threading The call to LoaderManager.initLoader() means that a Loader is initiated and active. There are 2 cases: If the specified ID already exists, the last Loader is reused If the ID doesn't exist, the LoaderManager.LoaderCallbacks.onCreateLoader() is invoked so a new Loader instance is created. If you want to force the reload of an already used Loader you can use the LoaderManager.restartLoader() method using the same ID: getLoaderManager().restartLoader(0, null, this); Loaders - Avvio
  17. 17. Threading LoaderManager.LoaderCallbacks methods: onCreateLoader(): it returns a new Loader with the specified ID onLoadFinished(): it's called when an already run Loader has finished its operations and it returns the result onLoadReset(): called when an already active Loader is reloaded so the old data is no longer needed. Loaders - Callbacks
  18. 18. Threading public class WeatherDetailProviderLoader extends AsyncTaskLoader { private String location; public WeatherDetailProviderLoader(Context context, String location) { super(context); this.location = location; } @Override public Forecast loadInBackground() { return WeatherProviderUtils.query(getContext(), location); } } Loaders - Example
  19. 19. Threading public class WeatherFragment extends Fragment implements LoaderCallbacks { @Override public void onActivityCreated(Bundle savedInstanceState) { getLoaderManager().initLoader(0, null, this); } @Override public Loader onCreateLoader(int arg0, Bundle arg1) { return new WeatherDetailProviderLoader(getActivity(), location)); } @Override public void onLoadFinished(Loader arg0, Forecast result) { adaptWeather(result); } @Override public void onLoaderReset(Loader arg0) { adaptWeather(null); } } Loaders - Example