I retreive data from server by means of external class which contains AsyncTask:
public class GetTask extends AsyncTask<String, Void, JSONObject> {
private Context context;
ProgressDialog dialog;
public GetTask(Context cxt) {
context = cxt;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
dialog.setTitle("Load...");
dialog.setMessage("Data...");
dialog.show();
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(String... url) {
// code for retreive data
return jArray;
}
protected void onPostExecute(JSONObject object) {
dialog.dismiss();
super.onPostExecute(object);
}
}
I call this task from my activity:
Tasks task = new Tasks();
JSONObject json = task.new GetTask(this).execute(ServerURL).get();
My data retrieved successfully but ProgressDialog show after super.onPostExecute(object); method, why?
P.S. dialog show after:
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
on internal Looper.class
Sorry my english is bad. ))
I found the solution, need use callback and not use .get() method. I call my task:
callTask(linkODeatails, obj);
callTask:
void callTask(String link, String object){
task.new GetTask(this).execute(link + object);
}
I create interface:
public interface AsyncTaskCompleteListener {
public void onTaskComplete(JSONObject result);
}
And added on my task:
private Activity activity;
private AsyncTaskCompleteListener callback;
public GetTask(Activity act){
this.activity = act;
this.callback = (AsyncTaskCompleteListener)act;
}
them called:
callback.onTaskComplete(result, object);
Related
Sorry for asking this but I recently started develop android and new to Java.
Currently I am able to "Toast" onPostExecute results in "BackgroundWorkerLocation.java". What I need is to somehow pass these results back to "MainActivty.java" from where I execute this class.
MainActivity.java
String type = "get_location";
String tLatitude = String.valueOf(latitude);
String tLongitude = String.valueOf(longitude);
BackgroundWorkerLocation backgroundWorkerLocation = new BackgroundWorkerLocation(getApplicationContext());
backgroundWorkerLocation.execute(type, tLatitude, tLongitude);
// I need "Results" here
BackgroundWorkerLocation.java
public class BackgroundWorkerLocation extends AsyncTask<String,Void,String> {
Context context;
BackgroundWorkerLocation(Context ctx){
context = ctx;
}
#Override
protected String doInBackground(String... params) {
// Some background work
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Currently I am able to Toast "RESULT" here
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
You'll need to create an interface that you can use as a callback:
interface MyCallback {
void onResult(String result);
}
In your activity you create an anonymous implementation of this callback.
Pass it into your ASyncTask.
String type = "get_location";
String tLatitude = String.valueOf(latitude);
String tLongitude = String.valueOf(longitude);
BackgroundWorkerLocation backgroundWorkerLocation = new BackgroundWorkerLocation(getApplicationContext(), new MyCallback() {
#Override
public void onResult(String result) {
// I need "Results" here
}
});
backgroundWorkerLocation.execute(type, tLatitude, tLongitude);
When the ASyncTask completes, you call the "onResult" method of the callback.
public class BackgroundWorkerLocation extends AsyncTask<String,Void,String> {
Context context;
private final MyCallback myCallback;
BackgroundWorkerLocation(Context ctx, MyCallback myCallback){
context = ctx;
this.myCallback = myCallback;
}
#Override
protected String doInBackground(String... params) {
// Some background work
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Currently I am able to Toast "RESULT" here
myCallback.onResult(result);
}
}
This is how you can share data between two classes.
Note that because the callback implementation is anonymous, it has a reference to your Activity, therefore if your task lives longer than your activity it can cause a memory leak. (your next problem :-))
I am newbie to android and facing issue on Progress dialog,though myriad question and answers are here but none is working for me.Any help will be greatly appreciated.
I want to show a spinning wheel on my login page of app,all my Async Task activties are in different class and I am passing the activity reference to my HttpClientHelper class which is handling Async Task.No progress dialog appears when i click on Login button.
Most of the answers have mentioned to implement the Async Task in Activity class but i have created a utility class which is handling the POST/GET in background.
Hence in thin non activity class i dont have the reference of Context so i passed LoginActivity.this in HttpClientHelper constructor.
AM i doing something wrong here.Due to multiple use of POST/Get i can implement them in each activity.
Please find the sample files these are not actual code I am posting the steps
public class LoginActivity extends AppCompatActivity {
btnSignIn.setOnClickListener(new View.OnClickListener() {
HttpClientHelper httpClientHelper = new HttpClientHelper(LoginActivity.this);
JSONObject json = httpClientHelper.postJSON(apiURL
, params);
...... rest of the code
}
}
Here is the HttpClientHelper
public class HttpClientHelper {
private Activity activity;
private static HttpURLConnection urlConnection;
private static String result;
private static JSONObject jsonObject = null;
public HttpClientHelper(){
}
public HttpClientHelper(Activity activity){
this.activity=activity;
}
public JSONObject postJSON(String url, Map<String, String> params) {
Params param = new Params(url, params);
PostAsyncTask myTask = new PostAsyncTask();
try {
jsonObject = myTask.execute(param).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return jsonObject;
}
private class PostAsyncTask extends AsyncTask<Params, String, JSONObject> {
JSONObject json = null;
ProgressDialog progressDialog;
public PostAsyncTask(){
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressDialog = new ProgressDialog(activity);
progressDialog.setTitle("Login");
progressDialog.setMessage("Loading..Please Wait");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected JSONObject doInBackground(Params... args) {
json = HttpClientHelper.getJSONFromURL(args[0].url, args[0].params);
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
super.onPostExecute(json);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
}
Progress dialogue is associated with UI and any updates in view is not recommended to put inside a AsyncTask. UI updates or changes should occur in the UI thread.
In your case, the desired result can be achieved by setting a listener to the AsyncTask. Simply add a listener class and implement the listener in the activity class.
Here's an example.
HttpResponseListener.java
public interface HttpResponseListener {
public void httpResponseReceiver(String result);
}
Now in your LoginActivity implement the interface like this:
public class LoginActivity extends AppCompatActivity implements HttpResponseListener {
// rest of your code
// initialize your progress dialogue here and execute the asynctask
progressDialogue.show();
myTask.execute();
myTask.mHttpResponseListener = this;
#Override
public void httpResponseReceiver(String result) {
if(result == null)progressDialogue.dismiss();
else {
// Use result to serve your purpose
progressDialogue.dismiss();
}
}
}
Now in your AsyncTask class, set the result in post execute.
private class PostAsyncTask extends AsyncTask<Params, String, JSONObject> {
JSONObject json = null;
ProgressDialog progressDialog;
public HttpResponseListener mHttpResponseListener;
public PostAsyncTask(){
}
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(Params... args) {
json = HttpClientHelper.getJSONFromURL(args[0].url, args[0].params);
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
super.onPostExecute(json);
mHttpResponseListener.httpResponseReceiver("OK");
}
#Override
protected void onCancelled() {
mHttpResponseListener.httpResponseReceiver(null);
}
}
This question already has answers here:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
(17 answers)
Closed 7 years ago.
I have been using async tasks to hit a web server and updating controls using the result. This has drawbacks, namely it makes the async methods specific to controls and stops me using the returned string again.
How do i return the resulting string from a async call onPostExecute? How do i call it? I cant seem to get my code able to do that. There should be no issues with threading as i have a dialog that freezes the UI until job is done.
My typical asyncTask code is as follows
class GetDataFromServer extends AsyncTask<String, String, String>
{
* */
// Progress Dialog
private ProgressDialog qDialog;
private Context context;
private String dialogString;
private ArrayList<String[]> newLoginResult;
// JSON parser class
String url_newGame ="http://xxxxxx.php";
public myAsyncMethos(String dialogMessage, Context con)
{
this.qDialog = new ProgressDialog(con);
this.dialogString = dialogMessage;
this.context = con;
}
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute()
{
super.onPreExecute();
qDialog = new ProgressDialog(this.context);
qDialog.setMessage(this.dialogString);
qDialog.setIndeterminate(false);
qDialog.setCancelable(false);
qDialog.show();
}
#Override
protected JSONObject doInBackground(String... args)
{
//MAKE SERVER CALL and cast to JSONOBject
return jsonNewUser;
}
public void onPostExecute(JSONObject jsonString)
{
// dismiss the dialog after getting response
qDialog.dismiss();
//I WANT TO RETURN A STRING HERE BUT KEEP GETTING SYNTAX ERRORS BEFORE RUNTIME
}
}
I would personally add a callback to your class, then once onPostExecute is run, fire off your callback to the listener on the main class.
class GetDataFromServer extends AsyncTask<String, String,JSONObject>
{
// Progress Dialog
private ProgressDialog qDialog;
private Context context;
private String dialogString;
private ArrayList<String[]> newLoginResult;
private InformComplete myCallback;
public GetDataFromServer(String dialogMessage, Context con,InformComplete callback)
{
this.qDialog = new ProgressDialog(con);
this.dialogString = dialogMessage;
this.context = con;
this.myCallback=callback;
}
#Override
protected void onPreExecute()
{
// set up your dialog
}
#Override
protected JSONObject doInBackground(String... args)
{
JSONObject jsonNewUser=new JSONObject();
return jsonNewUser;
}
public void onPostExecute(JSONObject jsonString)
{
qDialog.dismiss();
myCallback.PostData(jsonString);
}
public interface InformComplete
{
public void PostData(JSONObject result);
}
}
Then from your calling class, you'd have something like this...
private void callTheAsyncThing
{
GetDataFromServer gds=new GetDataFromServer("please wait", this, letMeKnow);
gds.execute(params);
}
private InformComplete letMeKnow=new InformComplete()
{
public void PostData(JSONObject result)
{
// we now have the data in the calling class
}
};
You can't return a value in methods from AsynTask cause it used to return a void element. So, you can instance global var foe example, and set the value to it. Like...
`
class GetDataFromServer extends AsyncTask<String, String, String>
{
* */
// Progress Dialog
private ProgressDialog qDialog;
private Context context;
private String dialogString;
private ArrayList<String[]> newLoginResult;
private String value;
// JSON parser class
String url_newGame ="http://xxxxxx.php";
public myAsyncMethos(String dialogMessage, Context con)
{
this.qDialog = new ProgressDialog(con);
this.dialogString = dialogMessage;
this.context = con;
}
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute()
{
super.onPreExecute();
qDialog = new ProgressDialog(this.context);
qDialog.setMessage(this.dialogString);
qDialog.setIndeterminate(false);
qDialog.setCancelable(false);
qDialog.show();
}
#Override
protected JSONObject doInBackground(String... args)
{
//MAKE SERVER CALL and cast to JSONOBject
return jsonNewUser;
}
public void onPostExecute(JSONObject jsonString)
{
// dismiss the dialog after getting response
qDialog.dismiss();
value = "Whatever you want";
}
public void setValue(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
}`
And then use it. There is one way to return something. Btw you can't change return.
the method of onPostExecute is not Programmer call,it called by AsyncTask instance.if you want to return a result from a async task,you can send a parameter into GetDataFromServer ,and in method of onPostExecute,you give him the new value,and then,you can use Handler to send a message.
Your return JSONObject in doInBackground method while you try to get string in onPostExecute method.
public void onPostExecute(JsonObject jsonString)
{
// dismiss the dialog after getting response
qDialog.dismiss();
//I WANT TO RETURN A STRING HERE BUT KEEP GETTING SYNTAX ERRORS BEFORE RUNTIME
}
I am quite new to Android Development. I am working in a app where i need to make a lot of async calls to api. For each and every API call, I have to write the similar looking AsyncTask class over and over again. So, is there any way to make these Async Calls modular?
yes it is possible use Listener and AsyncTask with parameterized constructor
Check it
Create an interface
public interface OnTaskCompletListerner {
void oncompleteListerner(String name);
}
create an AsyncTask class as follows
public class AsyncTaskModuler extends AsyncTask<Void, Void, String> {
private Context context;
private HashMap<String, String> data;
private String URL;
private OnTaskCompletListerner taskdone;
public AsyncTaskModuler(Context ctx,HashMap<String, String> data,String url,OnTaskCompletListerner taskdone){
this.context=ctx;
this.data=data;
this.URL=url;
this.taskdone=taskdone;
}
#Override
protected String doInBackground(Void... params) {
//Do the task here and return the value if needed
return null;
}
#Override
protected void onPostExecute(String result) {
taskdone.oncompleteListerner(result);
}
and call it in your activity like this
public class CallAync extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String url="";
HashMap<String, String> data=new HashMap<String, String>();
AsyncTaskModuler moduler=new AsyncTaskModuler(CallAync.this, data, url, completListerner);
moduler.execute();
}
OnTaskCompletListerner completListerner=new OnTaskCompletListerner() {
#Override
public void oncompleteListerner(String name) {
}
};
}
Create an general async task and pass your url as param to it .Hence you can reuse the same async task for all your api calls
public class myTask extends AsyncTask<Void, Void, Void> {
String muUrl;
public myTask(Context context, Activity activity,
String url) {
contxt = context;
myUrl=url;
}
#Override
protected Void doInBackground(Void... params) {
makeApiCalls();
return null;
}
}
Start the task in the following way :
new myTask(this, this, urlStr).execute();
EDIT
How can I perform different logic onPostExecute() ?
You can add another param in the constructor of myTask.
Ex.
public MyTask(Context context, Activity activity,
String url,String postExecuteAction) {
}
In your post executes just check of each case in if else and perform the respective task
Dummy Background class
private class BackGroundClass extends AsyncTask<String, Void, Bitmap> //<arg to do InBackground,,returntype of do inBackground and arg of onPostExecut>
{
public BackGroundClass()
{
}
#Override
protected void onPreExecute() //forground work in UI thread prior to doInbackground
{
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... urls) //background work in parallel thread
{
Bitmap b=null;
// your background work
return b;
}
#Override
protected void onPostExecute(Bitmap result) //forground work in UI thread post to doInbackground
{
super.onPostExecute(result);
if(result!=null)
{
//use bitmap image in result
}
else
{
//Image is not available
}
}
}
Calling for one parellel execution
new BackGroundClass().execute(StringArg1,stringArg2,StringArg3);
Calling for multiple parellel execution
when tou need to call more than one background task at same time
new BackGroundClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
Called from single activity
use this as an inner class to your activity for making it easy to share variable if not called from more than one activity
Called from more than one activity
use constructor to pass activity context,and other variable
new BackGroundClass(constructor arguments).execute(StringArg1,stringArg2,StringArg3);
new BackGroundClass(constructor arguments).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
I currently have a class UserFunctions that does all my user actions e.g. register, login etc. In the UserFunctions class there's a JSONParser object that does all the actual HTTP calls and returns the JSONObject.
public class UserFunctions {
private JSONParser jsonParser;
private static String registerURL = Constants.registerUrl;
// constructor
public UserFunctions(){
jsonParser = new JSONParser();
}
public JSONObject register(){
// getting JSON Object
JSONObject json = jsonParser.getJSONFromUrl(registerURL);
// return json
return json;
}
...
}
and then in my event handler of my activity classes I just do UserFunctions.register().
My question is, I now want to do all these calls in a background thread and at the same time show a ProgressDialog. I know running in the background thread is achieved with the AsyncTask.
But how should I achieve this design such that I can still do UserFunctions.register() in my Activity class, everything to be done in a background thread and a progressDialog shown.
Ok for this there are two parts the progress dialog and the async task, you need to move your JSONparser into the actual async task. If you want to use multiple progress dialogs just call them before calling the asynctask and close them when it returns
private class JsonRetriever extends AsyncTask<Url, Void, JSONObject>{
private JSONParser jsonParser;
private ProgressDialog dialog;
public JsonRetriever(Context c){
dialog= new ProgressDialog(c);
jsonParser= new JSONParser();
}
protected void onPreExecute() {
dialog.setMessage("Starting retrieval");
dialog.show();
}
protected JSONObject doInBackground(Url... params) {
try{
return jsonParser.getJSONFromUrl(params[0]);
}catch(Exception e){
return false;
}
return true;
}
protected void onPostExecute(final JSONObject success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
Then to call this just do
public JSONObject register(){
return new JSONRetriever(this).execute(registerURL).get();
}
Do as the following:
1)Declare you dialog in activity class like this:
ProgressDialog dialog;
2)then declare you AsyncTask as below:
private class RegisterUser extends AsyncTask<String,Integer,String>{
String nessage="";
#Override
protected void onPreExecute(){
dialog = ProgressDialog.show(context, "Registering user",
"Please wait.....");
}
#Override
protected String doInBackground(String... params) {
// provide yourcode to register the user then return message
return message="you are registered";
}
protected void onPostExecute(String result) {
dialog.dismiss();
if (result.equlas("you are resgisted"))
// optinal if you want to do as below
// do something here showing toast or any thing of your prefreance
}
}
Would this help you?
#Override
public void onCreate(Bundle savedInstanceState) {
new MyAsyncTask(this).execute();
}
privateclass MyAsyncTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Context context;
public ProgressTask(Context context) {
this.context= context;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
protected Boolean doInBackground(final String... args) {
// do you registering or whether here
// in this model you can return a boolean to the PostExecute.
}
}
Have a look at publishProgress() from the AsyncTask-Class i think its what you are looking for.
This method is used for updating the UI, when the Background-Thread done some Work. You can call it when ever you want it in the doInBackground()-Method.