I'm currently doing something like this in the AsyncTask's onPostExecute method, where NewTask is not the current task that's executing:
private class OlderTask extends AsyncTask<String, Void, Integer> {
//other functions (not important)
#Override
protected void onPostExecute(Integer result) {
new NewTask().execute(null, null);
}
}
I'm wondering if this is a bad idea. Will doing so cause GC for the OlderTask to wait for the NewTask? Are there any other possible problems with using such an approach?
And if this is a problem, how can I rectify it?
Unless NewTask is inner non static class in OlderTask it will not prevent GC from collecting OlderTask unless you store reference to it in some other way.
But even if GC will wait until NewTask is done it should not be a big deal unless you save lot of data in OlderTask or create lots of copies of OlderTask.
So if your design requires doing that, it's ok. But it surely cleaner not to have chained tasks.
I use a callback method, So when result comes to onPostExecute I call another AsynkTask from UI, I think it is good idea, Let me know what do you think.
public class PatientSearchController extends AsyncTask < String, Void, String > {
private PatientSearchResultHandler handler = null;
public void onResultHandler(PatientSearchResultHandler handler) {
this.handler = handler;
}
#Override
protected String doInBackground(String...params) {
}
#Override
protected void onPostExecute(String result) {
this.handler.onResultSuccessHandler(result);
}
}
Related
private class CreateGridTask extends AsyncTask<Void, Void, Void> {
private CreateGridTask() {
}
protected Void doInBackground(Void... voidArr) {
GridView.this.grid.create(((WordSearchApplication) GridView.this.getContext().getApplicationContext()).getLexicon());
return null;
}
protected void onPostExecute(Void voidR) {
GridView.this.startTime.setToNow();
GridView.this.onGridReadyListener.onGridReady();
GridView.this.invalidate();
}
}
public interface OnGridReadyListener {
void onGridReady();
}
public interface OnWordFoundListener {
void onWordFound(Word word, int i);
}
Android Studio GridView error getting while doInBackground with AsyncTask method, where i done wrong in code pls and this
You should not create the grid this way.
Instead, you should implement BaseAdapter. If cells have a number of particularly heavy operations, you may use AsyncTask within the adapter. Keep in mind, AsynTask starts a thread that is not attached to the UIThread and should not manipulate the UI until onPostExecute is called (Even then, use caution. Especially with a GridView where views may have been recycled)
I am pretty new to async tasks, but the few I have created for my app entail accessing class level variables and I have had a few null pointer exceptions sometimes in the doInBackground() for these tasks on real-world devices.
I believe this is because these variables should not really ever be accessed from within the async task, but instead passed in through the constructor or params etc. For example if I transition to activity B and an async task is still running from activity A, all of A's variables should become null shouldn't they?
And if accessing these variables should never be used from within the context of an async task, shouldn't the IDE (Android Studio in my case) warn me this is a dangerous action?
Edit: Wow so much help so quickly! Hopefully this will help others in the future too. Here is some code which is roughly what I was thinking about:
public class MyActivity extends ActionBarActivity {
private Context mContext;
private User mUser;
private ProgressDialog mProgressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
mProgressDialog = new ProgressDialog(mContext);
mUser = new User();
new MyAsyncTask.execute();
}
private class MyAsyncTask extends AsyncTask<Params, Integer, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(true);
mProgressDialog.setMessage("My message");
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected Void doInBackground(Params... params) {
Toast.makeText(mContext, "In doInBackground()", Toast.LENGTH_LONG).show();
mUser.someMethodThatTakesTime();
return null;
}
#Override
protected void onPostExecute(Void params) {
mProgressDialog.dismiss();
//Possibly launch another activity
}
}
}
You should definitely avoid using AsyncTask as an Inner Class in your Activity. Inner classes contain implicit strong references to their container class, so you run the risk of getting null pointers like you experienced during the Activity Lifecycle. And it does not just happen if Activity B goes on top of Activity A. It could happen if you rotate the device as well.
The problem is the Activity Lifecycle (which is why your IDE is not giving you warnings). For a configuration change (such as rotation), or in low memory situations, the Activity can be destroyed and recreated. But your AsyncTask will still be tied to the old activity.
There are a lot of threads about this:
https://stackoverflow.com/a/8550351/1856960
https://stackoverflow.com/a/16305144/1856960
You can also look into third party frameworks designed to deal with this:
https://github.com/stephanenicolas/robospice
Google around for more info too, this is hardly an exhaustive list.
I provide you two links.
firstly read and try to understanding
I expected that you will solve any problem about Android Asynctask problems in future.
link 1 Android Asynctask Example
and
link 2 Android Background Processing with Handlers and AsyncTask and Loaders - Tutorial
Best of Luck!
I'm implementing an app that uses many methods that requires an AsyncTask with a waiting dialog.
Actually my approach is to use every time an inner class that extends AsyncTask
something like
private class AsyncOperation extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute(){
pDialog = new ProgressDialog(CurrencyConverterActivity.this);
pDialog.setMessage("Waiting...");
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
...
return null
}
protected void onPostExecute(Void params){
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
//dialogs according status the
//int status is a static variable declared in external class
}
});
}
since with this approach i have to write this inner class too many times and this result in dirty code not well readable, I'm looking for a smarter solution
Could someone help me?
Are you calling the same network each time you use the async task?
If yes, then you can have one class which extends the async and pass the values for each call. You can have response listener to get the response from the method called the async
Something like this:
MainActivity:
First method:
AsyncOperation asyncCall = new AsyncOperation(MainActivity.this, "abc", "bcd");
asyncCall.execute();
Second method:
AsyncOperation asyncCall = new AsyncOperation(MainActivity.this, "aaa", "bbb");
asyncCall.execute();
callback(…){
}
Async Class:
private class AsyncOperation extends AsyncTask<Void, Void, Void> {
AsyncOperation(listener, string, string)
{
}
#Override
protected void onPreExecute(){
pDialog = new ProgressDialog(CurrencyConverterActivity.this);
pDialog.setMessage("Waiting...");
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
...
return null
}
protected void onPostExecute(Void params){
pDialog.dismiss();
listener.callback(…);
}
You can create an AsyncTask in a separate file (not as an inner class) and reuse it many times. AsyncTask doesn't have to be an inner class.
You may need to modify your AsyncTask to take additional parameters if needed to make it reusable.
You can also create a constructor for your AsyncTask with parameters for the values you need to pass into it and use that constructor to instantiate your AsyncTask.
This approach makes sense if the way you use AsyncTasks in different places is the same or at least similar. If you use completely different code in each AsyncTask, you will be better off with separate AsyncTasks (though you may still extract them into separate classes from inner classes).
I have utility class with static methods. Assuming that these methods can fire background task, something like below:
class ExampleAsyncUtil {
public static void doSomeAsyncJob() {
new AsyncTask<Void, Void, Void> () {
#Override
protected Void doInBackground (Void... params) {
//do heavy job here ...
return null;
}
}.execute();
}
}
if then i call the util class method inside activity which then becomes destroyed:
class ExampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ExampleAsyncUtil.doSomeAsyncJob();
}
#Override
protected void onDestroy() {
//should i stop async task in util on destroy ?
super.onDestroy();
}
}
Does it do any harm? (assuming that the background thread does not keep any refrence to activity which called the utility method)
Yes, you should cancel the AsyncTask from your UI. You can leak the AsyncTask otherwise (talking from experience). And, who knows, maybe even block another from being started on the same thread: they keep changing the implementation: http://developer.android.com/reference/android/os/AsyncTask.html. Or, contrary, multiple onCreate() could create duplicate "zombie" AsyncTask's. Anyway, it's not an intended use of AsyncTask: they are supposed to be short-lived and properly controlled. So, there seems to be no real gain in that static business.
I think you should either start a Service and spawn a tread from it or just use AsyncTask traditionally, within the life cycle of your Activity.
There is a good tutorial on asynchronous handling here: http://www.vogella.com/articles/AndroidPerformance/article.html.
I currently have a helper class to perform rudimentary AsyncTasks such as the following. I call the function from an activity as and when needed. The code seems to work fine and I haven't encountered any problems. But, I was wondering if this is a good coding practice or if there were any ramifications that I am unaware of. Any feedback would be gladly accepted and appreciated.
public class OtherUtils {
public static void updatePromptsOption(final boolean showPrompt, final Context context) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Editor preferenceEditor = PreferenceManager.getDefaultSharedPreferences(context).edit();
preferenceEditor.putBoolean(Constants.SHOW_PROMPT, showPrompt).commit();
return null;
}
}.execute();
}
}
I don't see anything wrong with doing things that way. Being a static function, you're not hiding implicit this references that could bite you later. Seems like a reasonable convenience function to me.