Antipattern: freezing the UI with an AsyncTask
The worst thing that can happen to your app's responsiveness is an "Application Not Responding" (ANR) dialog.
In my previous post I described how to freeze the UI with a Broadcast Receiver.
It is very important to understand which methods run in Main UI Thread.
In this post we can find an example OF WHAT NOT TO DO WITH AN ASYNCTASK.
We use an AsyncTask to execute background tasks in order to avoid the UI to become unresponsive, but not all methods run on the background thread.
In our AsyncTask class we must override
There are three other optional methods each of which is invoked from the UI thread:
In our BAD example (intentionally bad) we will launch a Async Task.
This means that our AsyncTask blocks any UI handling.
A good way to illustrate and comprehend which methods are invoked from the UI thread is by using a debugger. Put a breakpoint in these 3 methods.
Launch app, click refresh button and the freezing up of the UI is gone!
Here we can see where runs
We can see that it was called on the main UI thread.
...."Application Not Responding" (ANR) dialog...
You should avoid any long tasks in this method,particularly a network call.
When the breakpoint on the
In a similar way we can see how
You can get code from GitHub:
In my previous post I described how to freeze the UI with a Broadcast Receiver.
It is very important to understand which methods run in Main UI Thread.
In this post we can find an example OF WHAT NOT TO DO WITH AN ASYNCTASK.
We use an AsyncTask to execute background tasks in order to avoid the UI to become unresponsive, but not all methods run on the background thread.
In our AsyncTask class we must override
doInBackground()
which is invoked on the background thread.There are three other optional methods each of which is invoked from the UI thread:
onPreExecute
– this is called before doInBackground()onProgressUpdate
– this is called while doInBackground() is executingonPostExecute
– this is called after doInBackground()
In our BAD example (intentionally bad) we will launch a Async Task.
public class AsyncFreezingActivity extends SherlockActivity { protected AsyncTask mAsyncTask = null; private static final String TAG = "AsyncFreezingActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.async); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } /** * */ private void newEvent() { Toast.makeText(this, getString(R.string.text_newevent), 1000).show(); } /** * Launch Async Task */ private void launchAsyncTask() { Toast.makeText(this, getString(R.string.text_asynctask), 1000).show(); new AsyncFreezyTask(this).execute(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getSupportMenuInflater().inflate(R.menu.freezing_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpFromSameTask(this); return true; case R.id.menu_refresh: launchAsyncTask(); return true; case R.id.menu_newevent: newEvent(); return true; } return super.onOptionsItemSelected(item); } }In our example we will take "a long running task" in
onPreExecute
method.This means that our AsyncTask blocks any UI handling.
public class AsyncFreezyTask extends AsyncTask{ private final Activity activity; private static final String TAG = "AsyncFreezyTask"; private ProgressBar progress; private int count = 0; StringBuilder sb; public AsyncFreezyTask(Activity activity) { this.activity = activity; } @Override protected void onPreExecute() { progress = (ProgressBar) activity.findViewById(R.id.asyncTaskProgress); Log.d(TAG, "onPreExecute"); // This is an example of WHAT NOT TO DO !! This method runs // in Main UI Thread networkCall(); //You should make network call in doInBackground() method //This is an example of WHAT NOT TO DO !! try{ Thread.sleep(5000); }catch(Exception e){} Log.d(TAG, "onPreExecute END"); } @Override protected String doInBackground(Void... params) { String ret = null; count = params.length; for (int i = 0; i < count; i++) { publishProgress(i); } if (sb!=null) ret = sb.toString(); return ret; } @Override protected void onProgressUpdate(Integer... values) { progress.setMax(count); progress.setProgress(values[0]); } @Override protected void onPostExecute(String result) { // This is an example of WHAT NOT TO DO !! This method runs // in Main UI Thread parsing(result); Toast.makeText(activity, result, Toast.LENGTH_SHORT).show(); } /** * Network call.... You should make network call in doInBackground() method !!! */ private void networkCall() { // something... } private void parsing(String br) { // something... } }
A good way to illustrate and comprehend which methods are invoked from the UI thread is by using a debugger. Put a breakpoint in these 3 methods.
Launch app, click refresh button and the freezing up of the UI is gone!
Here we can see where runs
onPreExecute
method:We can see that it was called on the main UI thread.
...."Application Not Responding" (ANR) dialog...
You should avoid any long tasks in this method,particularly a network call.
When the breakpoint on the
doInBackground
is suspended in the debugger, we can see that it is not in main UI thread, but in a seperate thread.In a similar way we can see how
onPostExecute()
is invoked from the UI thread.You can get code from GitHub:
https://ngdeveloper.com/asynctask-with-broadcast-receiver-in-android-tutorial-and-example/
ReplyDeletesauclamso_me-1979 Ryan Young https://marketplace.visualstudio.com/items?itemName=itatno-po.Descargar-Maniac-Path-gratuita
ReplyDeleterilapahel
Uoringlosra-Evansville Penny Brooks Install
ReplyDeleteinstall
click here
odadntegmye