How to Call onPostExecute only after Completing CallBack Methods of doInBackground - android

I have a class LoginTask which is a subclass of AsyncTask. I used that to execute login functionality. Simply my LoginTask looks like this
class LoginTask extends AsyncTask<JsonObject,Void,String>{
#Override
protected void onPreExecute() {
//Codes to show progressDialog
}
#Override
protected String doInBackground(JsonObject... params) {
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});
return "some message";
}
#Override
protected void onPostExecute(String string) {
super.onPostExecute(string);
if(progressDialog.isShowing()){
progressDialog.dismiss();
//TODO Something
}
}
}
What I want and What was happened :
I want to call onPostExecute Only after getting the result from FutureCallback method But when I debug the app It is directly returning the value and onPostExecute Method called Immediately before FutureCallback method.
I have written code to Execute LoginTask at Login Button pressed Event, I want to show the ProgressDialog each time when Button is pressed, But the problem is ProgressDialog is shown only at the first time, It didn't appear when I pressed the Button second time.
I want to set some message to a variable and return that to onPostExecute method so that I can handle specific tasks based on the value of String parameter, But FutureCallback is called only after executing the whole Task.
Any Kind of Suggestions will be appreciated.

Here you are calling another thread inside asynctask. So whats happening is when the new thread is getting called. Asynctask is not waiting for your ion's thread to complete and so it is going to onPostExecute.
I think you don't need a asynctask here because Ion is already making the request asyncronously. Whatever you are doing inside onPostExecute(), you can put that inside onComplete() of the ion's call.

Do like this,
[Codes to show progressDialog]
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>()
{
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if(progressDialog.isShowing()){
progressDialog.dismiss();
//TODO Something
}
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});

onCompleted() method you are passing in setCallback() method is a callback method that is an asynchronous call so this callback will be invoked when response is returned from server and its takes time that is why your onPostExecute method is called before futureTask.
Ion lib already uses async calls so you do not need to use AsyncTask. You just need to do following:
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});

Related

Why does my progress bar not working properly?

I've been building an app which has Log In functionality. I've tested it but every time i tried to Log In, the progress bar disappeared to quickly (like a quarter second or something), and the response i get from the server is like about 2 seconds after the progress bar disappeared. Here are some of my codes.
My LoginTask inner class :
private class LoginTask extends AsyncTask<Account, Void, Account>{
private String getUsername = username.getText().toString();
private String getPassword = password.getText().toString();
#Override
protected void onPreExecute() {
super.onPreExecute();
//showDialog();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(Account account) {
super.onPostExecute(account);
//dismissDialog();
progressBar.setVisibility(View.GONE);
}
#Override
protected Account doInBackground(Account... accounts) {
getLogin(getUsername, getPassword);
return null;
}
}
Login Retrofit call to server
private void getLogin(String email, String password) {
Call<LoginAuth> call = userService.getLogin(email, password);
call.enqueue(new Callback<LoginAuth>() {
#Override
public void onResponse(Call<LoginAuth> call, Response<LoginAuth> response) {
try {
if (response.body().getToken_type().equals("xxx")) {
Log.i(TAG, "getLogin, Authorized access");
Log.i(TAG, "getLogin, access_token: " + response.body().getAccess_token().toString());
Log.i(TAG, "getLogin, expires_at" + response.body().getExpires_at().toString());
} else {
Log.e(TAG, "getLogin, Unauthorized access" + response.body().getToken_type().toString());
}
} catch (Exception e) {
Log.e(TAG, "getLogin exception " + e.getMessage());
}
}
#Override
public void onFailure(Call<LoginAuth> call, Throwable t) {
Log.e(TAG, "getLogin, onFailure : " + t.getMessage());
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(LoginActivity.this, "Unable to Log In :(", Toast.LENGTH_SHORT).show();
}
});
}
});
}
I want it to work like when the response is fetched, that's the time the progress bar disappeared (not instantly). Did i do something wrong with the code?
As you are using retrofit, there is no necessity to call your api in separate asynctask as retrofit manages it asynchronously. what you should do is show your progressbar before you call api and dismiss it in onResponse and onFailure both. so your code would change to something like below.
private void getLogin(String email, String password) {
progressBar.setVisibility(View.VISIBLE);
Call<LoginAuth> call = userService.getLogin(email, password);
call.enqueue(new Callback<LoginAuth>() {
#Override
public void onResponse(Call<LoginAuth> call, Response<LoginAuth> response) {
progressBar.setVisibility(View.Gone);
//rest of your code
}
#Override
public void onFailure(Call<LoginAuth> call, Throwable t) {
Log.e(TAG, "getLogin, onFailure : " + t.getMessage());
progressBar.setVisibility(View.Gone);
//rest of your code
}
});
}

How to load progress bar in android until response comes from server

Hi In my Application I'm sending one request to server to validate the user,after sending the request I'm storing that value in database and making the status as 1, after some time I'm changing the status to 2 in database.Now my android app should wait till the status becomes 2. For this I'm showing the user in mobile progress bar.But my problem is as soon as I send the request progress bar stops displaying in the mobile.
Here is what I have tried.
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.show();
progressDialog.setTitle("Please Wait");
progressDialog.setMax(100);
e1 = edittext.getText().toString();
//Toast.makeText(MainActivity.this, "" + e1, Toast.LENGTH_SHORT).show();
AsyncHttpClient client = new AsyncHttpClient();
final RequestParams params = new RequestParams();
params.put("sendingJSON", composeJSON());
client.post("http://192.168.43.137/gpstracker/check_user.php", params, new AsyncHttpResponseHandler() {
public void onSuccess(String response) {
Gson gson = new GsonBuilder().create();
try {
progressDialog.dismiss();
JSONArray arr = new JSONArray(response);
for (int i = 0; i < arr.length(); i++) {
JSONObject obj = (JSONObject) arr.get(i);
String general = obj.get("success").toString();
Toast.makeText(getApplicationContext(), ""+general, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void onFailure(int statusCode, Throwable error, String content) {
if (statusCode == 404) {
Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
} else if (statusCode == 500) {
Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",Toast.LENGTH_LONG).show();
}
}
});
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton) {
// what ever you want to do with No option.
}
}
);
alert.show();
}
A good solution in this cases is to work with events. Using events you can notify everywhere that something is happening. In your case, you can send an event when "the status changes to 2 in the database" and dismiss the progress dialog. There is a powerful and easy-to-use library to work with events called eventbus:
https://github.com/greenrobot/EventBus
I hope this helps to clarify!
I would recomend you to use an AsynkTask to do it. You can create the progress dialog in the onPreExecute() method, do what you are trying to do (post action or database update) in doInBackground() and once you have everything you want, in the onPostExecute() you can dismiss the dialog and send the result/data, if you need to, to your activity.
public class yourAsyncTask extends AsynkTask<Params, Params, Params>
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Charging...");
pDialog.setCancelable(true);
pDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
errorMesaje = "Process cancelled";
cancel(true);
}
});
pDialog.show();
}
#Override
protected Void doInBackground(Params... params) {
//Do your things here...
#Override
protected void onPostExecute(Void void) {
super.onPostExecute(void);
//Use an interface to call your activity and pass the data, you will have to change the attribute of the method in order to do it.
// Dismiss your dialog when your requests have finished
pDialog.dismiss();
}
I donĀ“t understand what are you trying to do exactly, if you just want to be sure that the post action is completed before the progress bar goes off, this solution will be fine. You can also call in the doInBackground() to your database and update it.
Hope it's clear enough!

How to use the ion library in Android?

I am using the ion library to download the json object response from php web services.
I am using it this way :
Ion.with(getActivity())
.load("http://amd.com/loginService.php")
.progressBar(progressBar).progress(new ProgressCallback() {
#Override
public void onProgress(long downloaded, long total) {
int mProgress = (int) (100 * downloaded / total);
progressBar.setProgress(mProgress);
}
})
.setMultipartParameter("fb_id", id)
.setMultipartParameter("fb_token", AccessToken.getCurrentAccessToken().toString())
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
#Override
public void onCompleted(Exception e, JsonObject result) {
if (result == null) {
Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
} else {
Log.v("IonResult", result.toString());
progressBar.setVisibility(View.GONE);
}
}
});
Now I want to ask two questions:
How can I show the "please wait" and the progress bar in a good manner? The progress bar should appear and then disappear when the response of server has been achieved.
How to parse the json which I am getting in response? I have logged my results like this
Log.v("IonResult", result.toString());
and I can see the response, but how can I use it and parse it and get the items I want?
Please help, I know it is a basic question, but as I am beginner in Android, please help me improve. Thanks.
I started using Ion recently, so I'm not sure if this is the best way to do that (please, if you know, leave a comment here!).
So, I'm using callbacks to return the value to another class.
public interface ResponseCallback {
public void onSuccess(String result);
public void onError(String result);
}
One example in my code:
public void getChats(final Context context, final String url,final ResponseCallback responseCallback) {
Ion.with(context)
.load(url)
.asString()
.setCallback(new FutureCallback<String>() {
#Override
public void onCompleted(Exception e, String result) {
if (e != null) {
if (responseCallback != null) {
responseCallback.onError(e.toString());
}
Toast.makeText(context, "Error loading chat list.", Toast.LENGTH_SHORT);
return;
}
if (responseCallback != null) {
responseCallback.onSuccess(result);
}
}
});
}
So, when I call getChats(), I implement ResponseCallback methods. I hope it helps, even that I think there's a better way to do that.

Async-http often hangs.

I start a ProgressDialog when I start my async request and on seemingly random occasions the dialogue does not dismiss (code does not fire onSuccess or onFailure). I handle both possible success responses from the server (one of which is an error) and I have a failure block so in theory the ProgressDialog should always dismiss. Can someone tell what event I am missing? Or is there a better structure?
My code structure:
I have a Gateway class that handles all the networking
The calling calls handles the .show() and .dismiss() events for the dialog
Gateway:
public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}
public static void loadItems(final ItemAdapter itemAdapter, int itemID) {
final String url = String.format(Constants.URL_ITEMS, itemID);
post(url, null, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject response) {
try {
if (!response.isNull("items")) {
itemAdapter.updateData(items);
} else if (!response.isNull("error")) {
itemAdapter.signalError(response.getString("error"));
}
} catch (JSONException e) {
itemAdapter.signalError("An unknown error has occurred");
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error)
{
if (error instanceof SocketTimeoutException || error instanceof ConnectTimeoutException) {
itemAdapter.signalError("Connection timeout! Please check that you are connected to the internet");
} else {
itemAdapter.signalError("An unknown error has occurred");
}
}
});
}
The adapter:
public ItemAdapter(Context context, int itemID) {
progressDialog = ProgressDialog.show(context, "Items",
"Loading items", true);
Gateway.loadItems(this, itemID);
}
public void updateData(ArrayList<Items> items) {
progressDialog.dismiss();
this.items = items;
notifyDataSetChanged();
}
public void signalError(String errorMessage) {
progressDialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Error")
.setMessage(errorMessage)
.setNegativeButton("OK", null).show();
}
I have no idea what your code is doing, but your if statements look suspicious.
if (!response.isNull("items")) {
itemAdapter.updateData(items);
} else if (!response.isNull("error")) {
itemAdapter.signalError(response.getString("error"));
}
could it be that none of the two conditions are met? If so, the dialog will not be dismissed. You only dismiss it on exception or if one of the above conditions are met.
I read somewhere that there is a design flaw in the library and people had some problems with the same issue.
But the most reliable solution was to override all the onSuccess and onFailure methods in the JsonHttpResponseHandler. In that way you can be sure that a communication is going on.
Hope this helps
Handle else case also onSuccess method like
#Override
public void onSuccess(JSONObject response) {
try {
if (!response.isNull("items")) {
itemAdapter.updateData(items);
} else if (!response.isNull("error")) {
itemAdapter.signalError(response.getString("error"));
} else {
// Code to dismiss the dialog
}
} catch (JSONException e) {
itemAdapter.signalError("An unknown error has occurred");
e.printStackTrace();
}
}
If your main concern is just closing ProgressDialog .. then try like this .
try{
runOnUiThread(new Runnable() {
public void run() {
progressDialog.dismiss();
}
});
}catch(Exception beauty)
{
// Log error if any ..
}
Hope it helps!

Toast not getting displayed in AsyncTask

The question is simple. Actually When I try to toast message, It is not getting displayed. Could you please guide me to resolve this.
protected String doInBackground(Void... params) {
if (result.equals("200")) {
Toast.makeText(CallArduino,appliance + " Success ",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(CallArduino, "Failed", Toast.LENGTH_SHORT).show();
}
return "success";
}
Toast can't be shown in background thread you should call it within the UI thread, in onPostExecute() for example
You are trying to do a UI operation on a background thread, which is forbidden.
Any UI operation (including displaying a toast) must be done in the UI thread.
You could for instance display your toast in the onPostExecute method:
protected String doInBackground(Void... params) {
// do your background stuff
}
protected void onPostExecute (Result result) {
if (result.equals("200")) {
Toast.makeText(CallArduino,appliance + " Success ",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(CallArduino, "Failed", Toast.LENGTH_SHORT).show();
}
}

Categories

Resources