I'm writting an application which use Android phone like client and connect to java server via TCP Socket.
My problem is: I used a service to send/receiver message to java server with asynctask to keep connection, but when i need to send request and wait for respone from server, i use another asynctask to do this, but the second asynctask can not run.
Here my code
Asynctask in Server (Connect - Keep receiver message)
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
Log.d(TAG1,"connectTask - in asycn task- 3");
//we create a TCPClient object and
mmTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
Log.d(TAG1,"connectTask - in asycn task- 4");
publishProgress(message);
}
});
if (LocalData.isConnectsuccess == false)
{
try {
Log.d(TAG1,"connectTask - in asycn task- 5");
mmTcpClient.run("172.16.10.37", 44444);
Log.d(TAG1,"Services started - in asycn task- 6");
}
catch (Exception e)
{
Log.e(TAG1,""+e);
}
}
return null;
}
#Override
protected void onProgressUpdate(final String... values) {
super.onProgressUpdate(values);
Log.e(TAG1,"Onprogressupdate" + values[0]);
LocalData.strreceiver = values[0];
Intent intt = new Intent(ConnectService.this, Customdialog.class);
intt.putExtra("mess", LocalData.strreceiver);
intt.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intt);
}
}
And the second asynctask which use for Login Activity
class ASlogin extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SigninActivity.this);
pDialog.setMessage("Logging in");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
Log.d(Tag2, "pdialog show");
}
/**
* getting All products from url
* */
protected String doInBackground(String... message) {
// Building Parameters
Log.d(Tag2, "Doinbackground");
try {
if (LocalData.isConnectsuccess == true) {
Log.d(Tag2, "Send-1");
JSONObject jslogin = new JSONObject();
try {
jslogin.put("tag","login");
jslogin.put("email", edtEmailSignIn.getText().toString());
jslogin.put("password", edtPasswordSignIn.getText()
.toString());
Log.d(Tag2, "Put Json-2");
} catch (JSONException e) {
Log.e(Tag2, "JSON failed" + e);
}
mTcpClient.sendMessage(jslogin.toString());
Log.d(Tag2, "JsonString: " + jslogin.toString());
}
else {
Log.e(Tag2, "Connect not success" + LocalData.isConnectsuccess);
}
} catch (Exception e) {
Log.e(Tag2, "Fail parse Json" + e);
}
return null;
}
#Override
protected void onProgressUpdate(String... message) {
super.onProgressUpdate(message);
pDialog.dismiss();
OJResponsive strreturn = new OJResponsive();
try{
strreturn = JSonparse.getrespon(LocalData.strreceiver);
}
catch (Exception e)
{
alertmess("Login fail" + e);
Log.e(Tag2,"Json parse failed"+e);
}
if (strreturn.getResult()=="success")
{
Toast.makeText(SigninActivity.this, "Login success", Toast.LENGTH_SHORT).show();
Intent inhctr = new Intent(SigninActivity.this,HomeControlActivity.class);
startActivity(inhctr);
finish();
}
else alertmess("Login fail");
Log.e(Tag2,"Login fail"+e);
}
}
the Second asycntask just run at onPreExecute() and stop at showprocessdialog.
So any help for me ? or any better solutions in this case ?
Thanks you.
Try to use
AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
instead
AsyncTask execution is handled differently in different versions of android.
Have a look a this answer: fetching data in parallel
Related
I have same stock item , I want to send local database to ApiService, But when I send also I want to update ProgressBar message. I tried the code below but it just shows when all proccessing is finishing.
ProgressDialog progress= new ProgressDialog(this);
progress.setTitle(getResources().getString(R.string.progress_exporting));
progress.setMessage("0/0");
when click button I call below method
public void Export() {
runOnUiThread(new Runnable() {
#Override
public void run() {
findViewById(R.id.btnExportOnlineWithStocktaking).setEnabled(false);
progress.show();
}
});
UpdateUI(send, total);
try {
switch (_stocktakingType) {
case Division: {
switch (_onlineExportType) {
case Item: {
isExport = ExportDivisionStocktakingItems(stocktakingId);
}
break;
}
} catch (Exception ex) {
}
}
// ExportDivisionStocktaking method
public boolean ExportCustomStocktakingItems(int stocktakingId) {
result = Boolean.parseBoolean(SendCustomStocktakingItems(stocktakingId,countResults).responseString);
}
My call back method
public ResponseModel SendCustomStocktakingItems(int selectedDivision, List<ExtensionServiceStocktakingItem> countResults) throws ExecutionException, InterruptedException {
return new SendCustomStocktakingItemsService(flag -> true).execute(String.valueOf(selectedDivision), countResults.toString()).get();
}
//AsyncTask method
public class SendDivisionStocktakingItemsService extends AsyncTask<String, Void, ResponseModel> {
public AsyncResponseSendDivisionStocktakingItems delegate = null;
public SendDivisionStocktakingItemsService(AsyncResponseSendDivisionStocktakingItems delegate) {
this.delegate = delegate;
}
#Override
protected ResponseModel doInBackground(String... parameters) {
RequestHandler requestHandler = new RequestHandler();
JSONObject params = new JSONObject();
try {
params.put("stocktakingItems", parameters[1]);
} catch (JSONException e) {
e.printStackTrace();
}
ResponseModel responseModel = requestHandler.getRequestPostString(UHFApplication.getInstance().apiUrl
+ "/api/MobileService/SendDivisionStocktakingItemsPost?stocktakingID="
+ parameters[0],
parameters[1]);
return responseModel;
}
#Override
protected void onPreExecute() {
UpdateUI(send,total);
super.onPreExecute();
}
#Override
protected void onPostExecute(ResponseModel responseModel) {
super.onPostExecute(responseModel);
if (HttpURLConnection.HTTP_OK == responseModel.httpStatus) {
delegate.processFinish(true);
} else {
delegate.processFinish(false);
}
}
}
//UICalled method
public void UpdateUI(int send, int total) {
runOnUiThread(() -> {
progress.setMessage(send + "/" + total);
Log.d("Send Data : ", send + "/" + total);
if (send == total) {
progress.dismiss();
Toast.makeText(getApplicationContext(), "Succsess", Toast.LENGTH_SHORT).show();
}
});
}
//Update
//Ok I have a simle example how can I use. Below code when I click button I wan to open progress firstly and after that for loop is working and update progres message. I try it but not working.
Firstly For loop is working and after that progres opened.
public void ExportTry(){
UpdateUI(send,total);
runOnUiThread(new Runnable() {
#Override
public void run() {
btnExport.setEnabled(false);
progress.show();
}
});
for(int i=0;i<1000000;i++){
UpdateUI(i,1000000);
}
}
You are missing the part of AsyncTask that will allow you to show progress messages while doInBackground is running. Take a look at onProgressUpdate and publishProgress on the same page.
publishProgress
void publishProgress (Progress... values)
This method can be invoked from doInBackground(Params...) to publish updates on the UI thread while the background computation is still running. Each call to this method will trigger the execution of onProgressUpdate(Progress...) on the UI thread. onProgressUpdate(Progress...) will not be called if the task has been canceled.
I have an activity that calls JSON data from a foreign database.
Below is my ideal case for my app:
The JSON data is parsed and inserted into an SQLite database on Android
Next activity is started and the newly inserted data is read from the SQLite database
What actually happens:
The JSON data is parsed and inserted into an SQLite database on Android
The next activity is started while data is still being inserted and returns zero when reading from the desired databse for my ListArray in that activity.
How do I force Android to wait until database insertion is completed before starting the next activity?
EDIT
My doInBackground looks as follows:
#Override
protected String doInBackground(String... params) {
StringRequest strReq = new StringRequest(Request.Method.GET,
str, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
JSONArray jObjInside = jObj.getJSONArray("service_prov_services");
for (int i = 0; i < jObjInside.length(); i++) {
// Now store the user in SQLite
try {
// JSONObject user = jObj.getJSONObject("user");
String service_prov_type = jObj.getString("service_prov_type");
String service_prov_name = jObj.getString("service_prov_name");
String addr_street = jObj.getString("addr_street");
String addr_num = jObj.getString("addr_number");
String addr_plz = jObj.getString("addr_plz");
String addr_city = jObj.getString("addr_city");
JSONObject elem = jObjInside.getJSONObject(i);
if(elem != null){
String service_id = elem.getString("service_id");
String service_type = elem.getString("service_type");
String service_measure = elem.getString("service_measure");
// Inserting row in userServiceProvServices table
db.addUserServiceProvServices(service_id, service_prov_type,
service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure);
Log.d("post_url for service", addr_plz );
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getActivity().getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
Log.d("test string to appcntr",strReq.toString());
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
return params[0];
}
onPostExecute looks as follows:
#Override
protected void onPostExecute(String Result) {
//super.onPostExecute(Result);
pdLoading.dismiss();
//this method will be running on UI thread
Log.d(TAG, "Stamp: " + Result);
Bundle args = new Bundle();
args.putString("stampID", Result);
ProviderServiceListFragment frag = new ProviderServiceListFragment();
frag.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame,
frag)
.commit();
}
With the way I am doing it now, my next Fragment is already called, although the data has not finished being entered into the database. This means the ListArray in the follwoing Fragment is empty because of the missing database data.
I worked on this for a month and finally figured it out for myself (stupid nube I am..) So here is a piece of code inserting a record to sqlite.
On the chosen event ("onClick actionbutton1") a new AsyncTask is created with doInBackground, onPreExecute and onPostExecute.
onPreExecute will setMessage() and show() the progressDialog which will start spinning
onPostExecute will handle the new/next Activity
READ BELOW FOR doInBackground!!
actionButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog progressDialog = new ProgressDialog(AddUpdateEvf.this);
new AsyncTask<Void, Void, Boolean>() {
protected Boolean doInBackground(Void... params) {
doOneThing();
return null;
}
#Override
protected void onPreExecute() {
progressDialog.setMessage("Processing...");
progressDialog.show();
}
protected void onPostExecute(Boolean result) {
evaluationFormOps.close();
progressDialog.dismiss();
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(AddUpdateEvf.this);
alertDialogBuilder.setMessage("Added to Database...")
.setCancelable(false)
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
i = new Intent(AddUpdateEvf.this, ViewProduct.class);
i.putExtra(EXTRA_ADD_UPDATE, "View");
i.putExtra(EXTRA_PRODUCT_ID, hiddenTextId.getText().toString());
i.putExtra(EXTRA_PRODUCT_NO, productNo_tv.toString());
startActivity(i);
dialog.dismiss();
finish();
}
});
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
}.execute();
}
});
Note this snippet in the above code called in doInBackground():
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
Note: The makeDbRequest() handles the insert to sqlite by setting the values and then passing it to another class which handles the cursor and puts the values etc.
Heres a small snippet of relevant code in that class (which you should already have mastered...):
public Evf addEvf(Evf evf, String dBsuccess){
ContentValues values = new ContentValues();
values.put(TableHelper.PRODUCT_IDE,evf.getPRODUCTId());
values.put(TableHelper.CSCORE,evf.getcScore());
values.put(TableHelper.FSCORE,evf.getfScore());
values.put(TableHelper.TSCORE,evf.gettScore());
values.put(TableHelper.WEIGHT,evf.getWeight());
values.put(TableHelper.TEMP,evf.getTemp());
values.put(TableHelper.STATUS,evf.getStatus());
values.put(TableHelper.TIMESTAMP, String.valueOf(evf.getTimeStamp()));
values.put(TableHelper.LOADED, dBsuccess);
long insertid = database.insert(TableHelper.TABLE_EVFS,null,values);
evf.setEvfId((int) insertid);
return evf;
}
So above you can see the Id of, in my case evaluationform(Evf), being set to the insert id. This happens after the insert and you can set any value in your object class (the one with getters and setters...Evf())
Finally, use the do...while statement above to "listen" for the value being set in the object class
This can obviously only happen if the insert was finished and the onPosteExecute takes care of the rest
Hope it helps, crit is welcome, PEACHES!!
Use AsyncTask to process the Database insertion process & then use the onPostExecute method to move away from the current activity.
private class ProcessDatabase extends AsyncTask<String, String, String> {
String sampleData;
#Override
protected String doInBackground(String... params) {
//Call your Database Insert method here.
//In this example, I am inserting sampleData to the DB
return null;
}
#Override
protected void onPostExecute(String result) {
//This gets triggered when the process is complete
}
}
You can start the AsyncTask by adding the following code in your onCreate or where ever you want to start the DB Insertion process:
//in this case I am just passing a string, You can create your own
//custom class & send that as well
ProcessDatabase.execute(myData);
Refer this link for more information. Good luck!
The StringRequest is an Asynchronous request, so upon the executing the those lines onPostExecute will called immediately, so there is no guarantee that the sql update will complete before the next activity is launched.
Call the nextActivity at the end of the onResponse callback method of the StringRequest which way you can guarantee to insert the data to db first and then call the nextActivity.
private void makeJsonRequest(String str) {
StringRequest strReq = new StringRequest(Request.Method.GET,
str, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
JSONArray jObjInside = jObj.getJSONArray("service_prov_services");
for (int i = 0; i < jObjInside.length(); i++) {
// Now store the user in SQLite
try {
// JSONObject user = jObj.getJSONObject("user");
String service_prov_type = jObj.getString("service_prov_type");
String service_prov_name = jObj.getString("service_prov_name");
String addr_street = jObj.getString("addr_street");
String addr_num = jObj.getString("addr_number");
String addr_plz = jObj.getString("addr_plz");
String addr_city = jObj.getString("addr_city");
JSONObject elem = jObjInside.getJSONObject(i);
if (elem != null) {
String service_id = elem.getString("service_id");
String service_type = elem.getString("service_type");
String service_measure = elem.getString("service_measure");
// Inserting row in userServiceProvServices table
db.addUserServiceProvServices(service_id, service_prov_type,
service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure);
Log.d("post_url for service", addr_plz);
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
goNextActivity();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getActivity().getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
Log.d("test string to appcntr", strReq.toString());
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
private void goNextActivity(){
//this method will be running on UI thread
ProviderServiceListFragment frag = new ProviderServiceListFragment();
frag.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame,
frag)
.commit();
}
In my Android async task class, I'm fetching data from an Azure server to local database inside DoinBackground method
But before finishing the DoinBackground method, it's executing the OnPostExecute method
Inside OnPostExecute method I am disabling the ProgressBar
Help me to solve this issue.
My code:
public class AsyncTaskSync_UserGroupMappingTableClass extends AsyncTask<String, String, Boolean>
{
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... values)
{
try
{
mToDoTable_Form5_SPINNER_DataTable456_ServerAzure
.execute(new TableQueryCallback<FormsObjectTable2TaskHopsSPinnerValues>() {
public void onCompleted(List<FormsObjectTable2TaskHopsSPinnerValues> result, int count, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
if (!result.equals("")) {
for (int i = 0; i < result.size(); i++) {
/*Table 5 SPinner Data Table*/
IdValue_TableValue5 = result.get(i).getId();
ImeiStringval1_TableValue5 = result.get(i).getImeINumberValOne();
Spinner_IDStringVal1_TableValue5 = result.get(i).getSpinner_id_StringOne();
Spinner_data_StringVal1_TableValue5 = result.get(i).getSPinner_data_Value_StringOne();
Log.i("From SErver DataBase", " Spinner : " + ImeiStringval1_TableValue5 + " : " + Spinner_IDStringVal1_TableValue5 + " : " + Spinner_data_StringVal1_TableValue5);
Asynxfor_DATAinsert5_SpinnerTable(IdValue_TableValue5, ImeiStringval1_TableValue5, Spinner_IDStringVal1_TableValue5, Spinner_data_StringVal1_TableValue5);
}
} else {
Log.i("Data Retrieval Not Found", "No Data In Server For Specific IMEI......!");
}
} else {
Log.i("SOme Exception", "Data Retrieval From Server FORMTABLE1 Data......!");
exception.printStackTrace();
}
}
});
}
catch (Exception e)
{
e.printStackTrace();;
Log.i("Data Retrieval", "Exception Occur......!");
}
// PrgDialog.dismiss();
return null;
}
#Override
protected void onPostExecute(Boolean results)
{
try
{
Log.i("DONE ", "Data Sync Done Successfully 5 Spinner Values");
PrgDialog.dismiss();
}
catch (Exception e)
{
e.printStackTrace();
Log.i("Exception ", "Post Excecute");
}
}
};
Edit 1
My Logcat message:
// From OnPostExecute first Executing also disabling the Progressbar
DONE: Data Sync Done Successfully Form Master 1
// From Doinbackground
From Server database
The requests you are doing inside doInBackground are made asynchronusly that's means that doInBackground is already execute before you get the TableQueryCallback. In other words It's a thread which is launching another thread. I think you do not need to surround it in an AsyncTask, you could handle your respond on TableQueryCallback.onCompleted() with a Handler or an Interface.
I am working on a task that calls my AsyncTask , once the async task is executed , I wait for 20 seconds to get the data from server , if it is still loading I am cancelling it (handling timeout)
public void handleServerTimeOut() {
getStore = new GetStore();
getStore.execute();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (getStore != null && getStore.getStatus() != AsyncTask.Status.FINISHED) {
boolean result = getStore.cancel(true);
Log.e(TAG, " handleServerTimeOut() reached 20 seconds");
Log.e(TAG, "" + result);
}
}
}, 20000);
}
AsyncTask
class GetStore extends AsyncTask<Void, Void, String> {
String status, message;
JSONArray jsonArray;
String buildingIdGuest, buildingIdUser, finalBuildingID;
#Override
protected void onPreExecute() {
super.onPreExecute();
if (isCancelled()) {
return;
} else {
buildingIdUser = utilClass.getSharePerefernce(getActivity(), KEY_BUILDING_ID_USER, "");
buildingIdGuest = utilClass.getSharePerefernce(getActivity(), KEY_BUILDING_ID_GUEST, "");
if (buildingIdUser.equals("0") || buildingIdUser.equals("")) {
finalBuildingID = buildingIdGuest;
} else {
finalBuildingID = buildingIdUser;
}
error_flag = 0;
gridView.setVisibility(View.VISIBLE);
error_layout.setVisibility(View.INVISIBLE);
img_no_internet.setVisibility(View.INVISIBLE);
img_no_results.setVisibility(View.INVISIBLE);
img_server_error.setVisibility(View.INVISIBLE);
progressDialog.setMessage("Getting nearby stores ...");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
progressDialog.show();
}
}
#Override
protected String doInBackground(Void... params) {
if (NetworkCheck.isNetworkAvailable(getActivity())) {
try {
jsonObj = userFunction.getStores(OS, MAKE, MODEL, finalBuildingID);
Log.e(TAG, jsonObj.toString());
status = jsonObj.getString("status");
message = jsonObj.getString("message");
if (status.equalsIgnoreCase("success")) {
jsonArray = jsonObj.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
gridModel = new GridModel();
gridModel.setId(jsonArray.getJSONObject(i).getString("id"));
gridModel.setStore_name(jsonArray.getJSONObject(i).getString("name"));
gridModel.setImage_name(jsonArray.getJSONObject(i).getString("image_name"));
gridListData.add(gridModel);
}
Log.e(TAG, "****** = " + gridListData.toString());
} else if (status.equalsIgnoreCase("invalid parameters")) {
error_flag = 2;
Log.e(TAG, "invalid parameters");
} else if (status.equalsIgnoreCase("no stores")) {
error_flag = 3;
Log.e(TAG, "No Data");
}
Log.e(TAG, "****** status " + status);
return String.valueOf(jsonObj);
} catch (Exception e) {
error_flag = 1; // Handling server timeout.
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.dismiss();
return;
}
});
Log.e(TAG, e.toString());
}
} else {
Log.e(TAG, "Network Error");
error_flag = 1;
}
return null;
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
Log.e(TAG, " **** error **** " + error_flag);
if (error_flag == 1) {
gridView.setVisibility(View.GONE);
error_layout.setVisibility(View.VISIBLE);
img_no_internet.setVisibility(View.VISIBLE);
} else if (error_flag == 2) {
gridView.setVisibility(View.GONE);
error_layout.setVisibility(View.VISIBLE);
img_server_error.setVisibility(View.VISIBLE);
txtError.setVisibility(View.VISIBLE);
txtError.setText(message);
} else if (error_flag == 3) {
gridView.setVisibility(View.GONE);
error_layout.setVisibility(View.VISIBLE);
img_no_results.setVisibility(View.VISIBLE);
}
gridAdapter = new GridAdapter(getActivity(), gridListData);
gridView.setAdapter(gridAdapter);
if ((progressDialog != null) && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
I also wanted to cancel my AsyncTask when the user cancels the ProgressDialog
You are checking isCancelled() only once in your AsyncTask - in the onPreExecute() method. At the time you call cancel() on your task instance, this check has already been evaluated and this is why the async task is still completing and updating the UI.
To deal with the issue, I suggest you include more checks for cancellation, using the isCancelled() method. One obvious place to include such a check is in the onPostExecute() method, right before you update the UI. You could also include a check before making the actual request to the server, after receiving the response, etc.
I have wrote an app to run an AsyncTask and part of the code is listed as follow. The problem is when the AsyncTask start by execute the code - "new AddImageTask().execute();" in the thread handler, the task will start and everything seems right. However, eventually the app will stay in "doInBackground" method after all code in "doInBackground" method has been executed. The task can't go to "onPostExecute" method. (i.e. can't dismiss the dialog...) What get wrong?
Thanks for the help......
private Handler handleFetchResult = new Handler() {
#Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
Log.d(TAG, "Start handle fetch result");
try {
JSONArray ja = new JSONArray(fetchResult);
Log.d(TAG, "JSON Array Length = " + ja.length());
JSONObject jo = new JSONObject();
for (int i = 0; i < ja.length(); i++) {
jo = ja.getJSONObject(i);
PhotoURLs.add(PAT_url + jo.getString("filePath"));
Log.d(TAG, PhotoURLs.get(i));
}
} catch (JSONException e) {
Log.d(TAG, "Fetch result error: " + e.getLocalizedMessage());
e.printStackTrace();
}
//TODO: display thumbnail
new AddImageTask().execute();
}//void handleMessage
};//Handler handleFetchResult
class AddImageTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
loadThumbnailDialog.show(SitePhotoGallery.this, "Fetch thumbnails from server",
"Loading...", true, true);
Log.d("AddImageTask.onPreExecute","onPreExecute");
}
#Override
protected Void doInBackground(Void... unused) {
// TODO Auto-generated method stub
for (String url : PhotoURLs) {
String filename = url.substring(url.lastIndexOf("/") + 1, url.length());
String thumburl = url.substring(0, url.lastIndexOf("/")+1);
imgAdapter.addItem(LoadThumbnailFromURL(thumburl + filename));
publishProgress();
}
Log.d("AddImageTask.doInBackground","doInBackground");
return null ;
}
#Override
protected void onProgressUpdate(Void... unused) {
super.onProgressUpdate();
imgAdapter.notifyDataSetChanged();
Log.d("AddImageTask.onProgressUpdate","OnProgressUpdate");
}
protected void onPostExecute(Void... unused) {
super.onPostExecute(null);
loadThumbnailDialog.dismiss();
Log.d("AddImageTask.onPostExecute","onPostExecute");
}
}
I think it's because onPostExecute() should take a Void parameter and not a Void... parameter. (You should also specify #Override as Soxxeh pointed out in his/her comment above.)