Presentation is loading. Please wait.

Presentation is loading. Please wait.

Concurrency in Android

Similar presentations


Presentation on theme: "Concurrency in Android"— Presentation transcript:

1 Concurrency in Android
Part II Concurrency in Android

2 Worker/Background Threads
AsyncTask Loader AsyncTaskLoader CursorLoader

3 AsyncTasks Threading Rules What is AsyncTask
It executes tasks in a background thread It can publish results on the UI thread It should be used for short operations Threading Rules Instances of AsyncTask must be created in UI thread AsyncTask#execute() must be invoked on UI thread. A task can only be executed once. Do not call onPreExecute, doInBackground, onProgressUpdate, onPostExecute manually

4 How To Create AsyncTasks
Subclass AsyncTask MyAsyncTask extends AsyncTask<Params, Progress, Result> { } Three Generic Types Params: the type of the parameters sent to the task upon execution. Use Void if none Progress: the type of the progress units published during background execution. Use Void if none Result: the type of the result of the background computation. Use Void if none.

5 How To Create AsyncTasks
Four Steps onPreExecute(): void executed on UI thread Used for task set up doInBackground(Params … params): Result Executed on the background thread The result must be returned from this Params are passed in from execute() Access params as an array params[0], params[i] It may call publishUpdate(Progress … progs) e.g., publishUpdate(11, 32, 24) if Progress is Integer

6 How To Create AsyncTasks
onProgressUpdate(Progress … progs): void executed on UI thread progs are passed in from publishUpdate() Access progs as an array, progs[0], progs[i] The timing of the execution this callback is undefined after publishUpdate() was called. onPostExecute(Result):void Executed on UI thread The result is the return from doInBackground()

7 How To Start/Stop AsyncTask
Call AsyncTask#execute(Params…) E.g., aMyAsyncTask.execute(“photo1.jpg”, “photo2.jpg”) if Params is String To cancel Call AsyncTask#cancel(boolean myInterruptIfRunning) E.g., aMyAsyncTask.cancel(true) It returns true if successful If doInBackground() has not started, the task is cancelled and doInBackground() would not run else if mayInterruptIfRunning interrupt the thread (raise the flag) else let doInBackground() finish call onCancelled(Result) on UI thread (Result may be null) Returns false if task has completed, or already cancelled, or could not be cancelled. To really stop the task, In doInBackground() Call isCancelled() on a regular basis to see if it is cancelled.

8 Order of Execution AsyncTasks may be executed concurrently or sequentially Before DONUT, tasks were executed serially on a single thread With DONUT, tasks were executed to a pool of threads With HONEYCOMB, tasks are executed on a thread You may request for multiple threads using executeOnExecutor()

9 SimpleAsyncTask Example 1
class BackgroundTask extends AsyncTask<String, Integer, Integer> { private WeakReference<Context> mWeakRefActivity; private WeakReference<ProgressBar> mWeakRefProgressBar; int totalUrls = 0; public BackgroundTask(Context context, ProgressBar progressBar) { this.mWeakRefActivity = new WeakReference<Context>(context); this.mWeakRefProgressBar = new WeakReference<ProgressBar>(progressBar); } // invoked in the UI protected void onPreExecute() { super.onPreExecute(); displayProgress(); // executed in its own thread protected Integer doInBackground(String... urls) { int successCount = 0; totalUrls = urls.length; // Dummy code int i = 0; while ( !isCancelled() && i < totalUrls) { try { Thread.sleep(5000); // sleep 5s - mimicking download } catch (InterruptedException e) { e.printStackTrace(); Log.i("ASYNCTASK: ", urls[i]); // LogCat will display each URL successCount++; publishProgress(i); // the following toast would cause an exception since it is NOT in UI thread //Toast.makeText(mainActivityContext, "Never Displayed", Toast.LENGTH_LONG).show(); return successCount;

10 SimpleAsyncTask Example 2
class BackgroundTask extends AsyncTask<String, Integer, Integer> { // continued from previous slide // invoked in the UI protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); mWeakRefProgressBar.get().setProgress((values[0] + 1) * 10); updateProgress(values[0]+1); } protected void onPostExecute(Integer result) { super.onPostExecute(result); dismissProgressBar(result); private void displayProgress() { Context context = mWeakRefActivity.get(); if (context != null) { Toast.makeText(context, "Started...", Toast.LENGTH_LONG).show(); private void dismissProgressBar(Integer successCount) { Toast.makeText(context, "Done...", Toast.LENGTH_LONG).show(); private void updateProgress(int value) { float percentage = (float)value / totalUrls * 100; String text = "Downloading..."+percentage+"%"; Toast.makeText(context, text, Toast.LENGTH_LONG).show();

11 SimpleAsyncTask Example 3
public class SimpleAsyncTask extends Activity { ProgressBar mProgressBar; BackgroundTask protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_async_task); } public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.simple_async_task, menu); return true; public void onDestroy() { super.onDestroy(); mBackgroundTask.cancel(true); public void startDownloading(View v) { mProgressBar = (ProgressBar)findViewById(R.id.progress_bar); // start the AsyncTask with 10 URLs mBackgroundTask = new BackgroundTask(getApplicationContext(), mProgressBar); mBackgroundTask.execute("url0", "url1", "url2", "url3", "url4", "url5", "url6", "url7", "url8", "url9");

12 SimpleAsyncTask Example 4
Layout file <LinearLayout xmlns:android=" xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".SimpleAsyncTask" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ProgressBar android:layout_width="fill_parent" android:layout_marginRight="5dp" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:text="Download the file" android:onClick="startDownloading"/> </LinearLayout>

13 Loaders Introduced in Android 3.0
They are available to every Activity and Fragment They provide asynchronous loading of data They monitor data source and update automatically They automatically reconnect to the last loader’s cursor when being re-created after configuration changes

14 Loader API Summary LoaderManager LoaderManager.LoaderCallbacks Loader
Each Activit/Fragment has one LoaderManager It Manages one or more loader instances LoaderManager.LoaderCallbacks A callback interface for a client to interact with LoaderManager OncreateLoader(), onLoadFinished(), onLoaderReset() Loader A abstract class that performs asynchronous loading of data AsyncTaskLoader An abstract loader that provide an AsyncTask to the work CursorLoader A subclass of AsyncTaskLoader that queries the ContentResolver and returns a Cursor. Best for loading data from ContentProviders

15 Using loaders in an App Components used with Loaders
An activity or Fragment An instance of LoaderManager An AsyncTaskLoader or CursorLoader to load data from custom source or ContentProvider An implementation of LoaderManager.LoaderCallbacks A way of display the loader’s data, such as SimpleCursorAdapter A data source, such as a ContentProvider when using CursorLoader

16 Start a Loader getLoaderManager().initLoader(Loader_id, Bundle, Callbacks) Loader_id: each id may have a unique id (0, 1, 2 …) bundle: data to be passed on to the Loader Callbacks: object that implements LoaderManager.LoaderCallbacks. initLoader() ensures a loader is created and active If the loader by the id exists, the last one is reused If the loaded data is available, onLoadFinished() will be called right away. Implies that the LoaderCallbacks instance must be created before you call initLoader() If the loader by the id does not exist, it triggers LoaderManager.LoaderCallbacks#onCreateLoader() initLoader() does return the Loader just initialized. Normally you don’t use this returned loader directly Use the LoaderManager and its callbacks to interact with the loader. Call initLoader() in Activity#onCreate() or Fragment#onActivityCreated()

17 Restart a Loader initLoader() does not create a new loader if there is one with the same id Loaders, in particular CursorLoaders, are expected to retain their data after being stopped. This allows the apps to keep their data across the activity or fragments onStop() and onStart() Sometimes you want to discard the old data and start over getLoaderManager.restartLoader(loader_id, bundle, callbacks)

18 LoaderManager: The 3 callbacks
onCreateLoader(loader_id, bundle): Loader Called when a new loader with loader_id needs to be created It returns a Loader to the LoaderManager onLoadFinished(Loader<D> loader, D data) Called when the loader has the requested data available loader.getId() can get the loader’s Id Data is the data loaded. D may be Cursor. When it is cursor, do not close it manually in your code, the LoaderManager manages it. Here you may use the data E.g., mSimpleCursorAdapter.swap(data); Don’t commit fragment transactions in this call since it may be called after the activity’s state has been saved. A fragment transaction can only be created/committed prior to the activity saving its state. onLoaderReset() Called when the loader being reset, the data no longer available. You can release the reference to the data E.g., mSimpleCursorAdapter.swap(null);

19 An Example - 1 Public class CursorLoaderListFragment extends ListFragment implement LoaderManager.LoaderCallbacks<Cursor> { SimpleCursorAdapter mAdapter; void OnActivityCreated(Bundle data) { super.onActivityCreated(data); mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.my_layout, null, // we don’t have data yet, use null new String[] {Contacts.DISPLAY_NAME}, new int[] {R.id.name}, 0}; // since Loader monitors data changes, use 0 // so the adapter would not monitor the data setListAdapter(mAdapter); // prepare the loader getLoaderManager().initLoader(3, null, this); } // return a CursorLoader Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri baseUri = Contacts.CONTENT_URI; String[] projections = new String[] {Contacts.DISPLAY_NAME}; String select = Contacts.DISPLAY_NAME + “ IS NOT NULL ”; String[] selectArgs = null; String sortOrder = null; return new CursorLoader(getActivity(), baseUri, projections, select, selectArgs, sortOrder);

20 An Example - 2 Public class CursorLoaderListFragment extends ListFragmen implement LoaderManager.LoaderCallbacks<Cursor> { ... void onLoadFinished(Loader<Cursor> loader, Cursor data) { // now we have data, put it into the list view // do not try to close the old cursor, android takes care of it mAdapter.swapCursor(data); } // if the cursor is about to be closed void onLoaderReset(Loader<Cursor> loader) { // called when the cursor is to be closed. // release the reference to the cursor mAdapter.swapCursor(null);


Download ppt "Concurrency in Android"

Similar presentations


Ads by Google