Common class for AsyncTask in Android?
A clean way to use AsyncTask to get a result would be to use a callback interface.
Here is a simple example of this concept:
interface AsyncTaskCompleteListener<T> {
public void onTaskComplete(T result);
}
then in your B class :
class B implements AsyncTaskCompleteListener<String> {
public void onTaskComplete(String result) {
// do whatever you need
}
public void launchTask(String url) {
A a = new A(context, this);
a.execute(url);
}
}
you should now add the following code to your A class:
class A extends AsyncTask<String, Void, String> {
private AsyncTaskCompleteListener<String> callback;
public A(Context context, AsyncTaskCompleteListener<String> cb) {
this.context = context;
this.callback = cb;
}
protected void onPostExecute(String result) {
finalResult = result;
progressDialog.dismiss();
System.out.println("on Post execute called");
callback.onTaskComplete(result);
}
}
This way, you don't need to wait explicitely for your task to complete, instead, your main code (which is probably the main UI thread), is waiting in the normal android event loop, and the onTaskComplete method will be automatically called, allowing to handle the task result there.
public AsyncTask to be called from several classes
Some time ago I've asked a similar question
One AsyncTask for multiple Activities
and the solution I found was answered in another question:
Common class for AsyncTask in Android?
Basically, what you need is an interface
.
I've going to explain the basics, although you should check the original answer by @SirDarius.
You could create an interface like this:
interface AsyncTaskCompleteListener<T> {
public void onTaskComplete(T result);
}
And implements that interface in all classes you need to use the AsynTask
, then, in your generic Asynstask
you need to have a callback AsyncTaskCompleteListener
and call it from your onPostExecute
class B implements AsyncTaskCompleteListener<JSONObject> {
public void onTaskComplete(JSONObject result) {
// do whatever you need
}
public void launchTask(String url) {
ApiCaller a = new ApiCaller(context, ArrayList<NameValuePair> params, this);
ApiCaller.execute(url);
}
}
class ApiCaller extends AsyncTask<String, Void, String> {
private AsyncTaskCompleteListener<String> callback;
public ApiCaller(Context context, ArrayList<NameValuePair> params, AsyncTaskCompleteListener<String> cb) {
this.context = context;
this.callback = cb;
}
protected void onPostExecute(String result) {
finalResult = result;
progressDialog.dismiss();
System.out.println("on Post execute called");
callback.onTaskComplete(result);
}
}
How to make a generic AsyncTask?
I think what you are talking about is already answered here In this answer it has a same topic's discussion, Although i also know some blogs that can help you to make it more conceptually clear read them,
Links:
https://trinitytuts.com/reusable-asynctasks-class-in-android/
http://cyriltata.blogspot.in/2013/10/android-re-using-asynctask-class-across.html
Call AsyncTask from another class
You can make a separate abstract package private class, extending AsyncTask
and implementing doInBackground()
method:
abstract class MyAsyncTask extends AsyncTask<Void, Void, String> {
@Override
final protected String doInBackground(Void... progress) {
// do stuff, common to both activities in here
}
}
And in your activities just inherit from MyAsyncTask
(new class probably should be private, by the way), implementing onPostExecute()
and onPreExecute()
methods:
public class Activity_1 extends BaseActivity {
...
new Async1().execute();
...
private class Async1 extends MyAsyncTask {
@Override
protected void onPreExecute(){
// Activity 1 GUI stuff
}
@Override
protected void onPostExecute(String result) {
// Activity 1 GUI stuff
}
}
}
If onPreExecute
and onPostExecute
contain some common actions as well, you can apply the following pattern:
abstract class MyAsyncTask extends AsyncTask<Void, Void, String> {
public interface MyAsyncTaskListener {
void onPreExecuteConcluded();
void onPostExecuteConcluded(String result);
}
private MyAsyncTaskListener mListener;
final public void setListener(MyAsyncTaskListener listener) {
mListener = listener;
}
@Override
final protected String doInBackground(Void... progress) {
// do stuff, common to both activities in here
}
@Override
final protected void onPreExecute() {
// common stuff
...
if (mListener != null)
mListener.onPreExecuteConcluded();
}
@Override
final protected void onPostExecute(String result) {
// common stuff
...
if (mListener != null)
mListener.onPostExecuteConcluded(result);
}
}
and use it in your activity as following:
public class Activity_1 extends BaseActivity {
...
MyAsyncTask aTask = new MyAsyncTask();
aTask.setListener(new MyAsyncTask.MyAsyncTaskListener() {
@Override
void onPreExecuteConcluded() {
// gui stuff
}
@Override
void onPostExecuteConcluded(String result) {
// gui stuff
}
});
aTask.execute();
...
}
You can also have your Activity
implement MyAsyncTaskListener
as well:
public class Activity_1 extends BaseActivity implements MyAsyncTask.MyAsyncTaskListener {
@Override
void onPreExecuteConcluded() {
// gui stuff
}
@Override
void onPostExecuteConcluded(String result) {
// gui stuff
}
...
MyAsyncTask aTask = new MyAsyncTask();
aTask.setListener(this);
aTask.execute();
...
}
I wrote the code from the head, so it might contain errors, but it should illustrate the idea.
How to create a common AsyncTask class for webservice call in an android app?
Create Interface
which will be use as callback.
public interface MyCallBack {
void onResult(HTTPServiceTags requestTag);
}
In your Activity
implements that interface-
public class Xyz extends Activity implements MyCallBack {
@override
public void void onResult(HTTPServiceTags requestTag) {
// Do your work
}
}
Pass that interface in your AsyncTask's constructor-
public WebServiceRequest(MyCallBack callBack) {
this.mCallBack = callBack; // Assign it to global variable
}
Then in onPostExecute
call it -
@Override
protected void onPostExecute(Boolean result) {
if (result) {
mCallBack.onResult(requestTag);
}
}
Android: AsyncTask recommendations: private class or public class?
Inner classes are good for representing objects that are meant to be private or somehow intimately tied to the enclosing class. Occasionally there are technical reasons for using inner classes (e.g., simulating closures). They also cut down on namespace pollution.
One disadvantage of inner classes is that if they access private members (fields or functions) of the enclosing class, the compiler will generate accessor functions to those members. Language purists will argue whether this breaking of encapsulation is a Good Thing or a Bad Thing. The access functions add a bit of overhead to each access (which usually isn't a factor, but there it is). Another disadvantage is that it makes the source file more complex and therefore harder to manage. (I've occasionally been stung by editing a function in the inner class while thinking it was in the outer class, and vice versa.) Finally, inner classes tend not to be reusable, while separate classes can often be parameterized to have multiple uses.
These pros and cons are off the top of my head. I'm sure others will have additional thoughts.
UPDATE:
In this Google IO video the inner AsyncTask option is clearly marked as wrong option.
AsyncTask Android example
Ok, you are trying to access the GUI via another thread. This, in the main, is not good practice.
The AsyncTask executes everything in doInBackground()
inside of another thread, which does not have access to the GUI where your views are.
preExecute()
and postExecute()
offer you access to the GUI before and after the heavy lifting occurs in this new thread, and you can even pass the result of the long operation to postExecute()
to then show any results of processing.
See these lines where you are later updating your TextView:
TextView txt = findViewById(R.id.output);
txt.setText("Executed");
Put them in onPostExecute()
.
You will then see your TextView text updated after the doInBackground
completes.
I noticed that your onClick listener does not check to see which View has been selected. I find the easiest way to do this is via switch statements. I have a complete class edited below with all suggestions to save confusion.
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity implements OnClickListener {
Button btn;
AsyncTask<?, ?, ?> runningTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = findViewById(R.id.button1);
// Because we implement OnClickListener, we only
// have to pass "this" (much easier)
btn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
// Detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
if (runningTask != null)
runningTask.cancel(true);
runningTask = new LongOperation();
runningTask.execute();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// Cancel running task(s) to avoid memory leaks
if (runningTask != null)
runningTask.cancel(true);
}
private final class LongOperation extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We were cancelled; stop sleeping!
}
}
return "Executed";
}
@Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// You might want to change "executed" for the returned string
// passed into onPostExecute(), but that is up to you
}
}
}
Android common async task with multiple callers
If it needs to be received in all Activity's then you'd probably want to use a broadcast instead of a callback.
Android docs for BroadcastReceiver
And since you only want broadcasts within your app you'll also want to use it with the LocalBroadcastManager
This tutorial covers everything you'd need for this.
Sample
Add a BroadcastReceiver to each Activity like so
BroadcastReceiver rec = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//all events will be received here
//get message
String message = intent.getStringExtra("message");
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(rec, new IntentFilter("event"));
To send a Broadcast.
Instead of caller.asyncResponse(message);
Intent intent = new Intent("event");
// add data
intent.putExtra("message", message);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Related Topics
Update Fragment from Viewpager
Android Appcompat 21 Elevation
Resolved Versions for App (22.0.0) and Test App (21.0.3) Differ
Initializing Games Client in Android
Android Custom Dropdown/Popup Menu
Notifydatasetchange Not Working from Custom Adapter
Alphabetindexer with Custom Adapter Managed by Loadermanager
How to Do a Simple Search in String in Firebase Database
Cannot Get Folderid That I Just Created on Google Drive
How to Strike Through Text in an App Widget
What's "Tools:Context" in Android Layout Files
How to Get Device Id for Admob
Listview Scroll to the End of the List After Updating the List
How to Add a Notification Badge/Count to Application Icon on Sony Xperia Devices