I have an activity with a button that starts an AsyncTask:
public void search(View view) {
if (searchTask != null) {
return;
}
searchTask = new SearchTask(this);
searchTask.execute((Void)null);
}
And this is the task:
public class SearchTask extends AsyncTask<Void, Void, Boolean> {
private final Activity activity;
private final ProgressDialog dialog;
public SearchTask(Activity activity) {
this.activity = activity;
this.dialog = new ProgressDialog(activity);
}
#Override
protected Boolean doInBackground(Void... params) {
try {
wait(3000);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
#Override
protected void onPreExecute() {
dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing())
dialog.dismiss();
}
}
I'm not calling get() so I shouldn't be blocking the UI thread. The problem is that the progress dialog is not being shown.
Is this not the correct way to show a dialog within an AsynTask?
wait() causes IllegelMonitorException. to apply a delay in the task Thread.sleep() should be used.
try after removing return; from below code-
public void search(View view) {
if (searchTask != null) {
return;
}
searchTask = new SearchTask(this);
searchTask.execute((Void)null);
}
Related
I have got a little problem while cancellling a AsyncTask, which is in a Fragment which processes some data. If a internet session is expired the AsyncTask should be cancelled and a dialog be shown to inform the user.
However if I cancel the AsyncTask the AlertDialog is not shown, I also noticed that onCancelled()is not being called but the onPostExecute()is still executed.
If someone pls could assist?
Edit: If I use the while method, the AlertDialog is shown but how do I properly cancel the AsyncTask as the code as of tryin doInBackground() still is being executed?
while (!isCancelled()) {
// Do stuff
}
Edit 2: Solved! It seemed the AsyncTask call was not correctly instinciated, below code works and now also onCancelled method is called and onPostExecute declined as it should be.
Cudos for Anudeep Bulla to point me in the right direction.
public class Tb3_Abonnement extends Fragment {
private AsyncTask<Void, Void, Void> task;
...
#Override // If Fragment is visible to user, start asynctask
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// execute AsyncTask
startFetch();
}
}
// Wrap (asynctask call) in a own method
public void startFetch() {
task = new FetchFacturen();
task.execute();
}
private class FetchFacturen extends AsyncTask<Void, Void, Void> {
// Create new AlertDialog
AlertDialog taskDialog = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Mededeling Facturen:")
.setMessage("Uw sessie is verlopen! U dient zich weer opnieuw in te loggen. ")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Start LoginActivity
Intent mainIntent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivity(mainIntent);
getActivity().finish();
}
})
.setIcon(android.R.drawable.ic_dialog_info)
.create();
#Override
protected void onPreExecute() {
if (Helper.minutes <= 0) {
task.cancel(true);
} else {
showProgress(true);
}
}
#Override
protected Void doInBackground(Void... result) {
CharSequence cs1 = "€";
if (isCancelled()) {
util.disconnect();
return null;
}
try {
// The heavy stuff
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onCancelled() { // Correctly called
if(isCancelled()){
Log.e("CANCELLED", "TAB3");
this.taskDialog.show();
}
super.onCancelled();
}
#Override
protected void onPostExecute(Void result) { // Skipped
if(isCancelled()){
this.taskDialog.show();
} else {
setupInvoiceAdapter();
showProgress(false);
}
}
}
Here are the important code parts:
public class Tb3_Abonnement extends Fragment {
private FetchAbbo task;
...
#Override // If Fragment is visible to user, start asynctask
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// execute AsyncTask
task = new FetchAbbo();
task.execute();
}
public class FetchAbbo extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
if (Helper.minutes <= 0) {
task.cancel(true); // Cancel AsyncTask
new AlertDialog.Builder(getActivity()) // Create new AlertDialog
.setCancelable(false)
.setTitle("Mededeling:")
.setMessage("Uw sessie is verlopen! U dient zich weer opnieuw in te loggen. ")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Start LoginActivity
}
})
.setIcon(android.R.drawable.ic_dialog_info)
.show();
}
}
#Override
protected Void doInBackground(Void... result) {
if (!this.isCancelled()) { // Executed
Log.e("FetchAbbo: ", "Cancelled!"); // Printed
util.disconnect();
return null;
}
try {
Log.e("FetchAbbo: ", "still running!");
// Do the heavy stuff
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onCancelled() {
Log.e("CANCELLED", "TAB3"); // Not printed, onCancelled() not called?
super.onCancelled();
}
#Override
protected void onPostExecute(Void result) {
setupTxtViews();
mScrollView.setVisibility(View.VISIBLE); // Set ScrollView visible
}
}
I may be wrong, but I don't seem to understand the logic of showing the dialog in onPreExecute everytime. Why not try this ?
public class FetchAbbo extends AsyncTask<Void, Void, Void> {
AlertDialog taskDialog = new AlertDialog.Builder(getActivity()) // Create new AlertDialog
.setCancelable(false)
.setTitle("Mededeling:")
.setMessage("Uw sessie is verlopen! U dient zich weer opnieuw in te loggen. ")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Start LoginActivity
}
})
.setIcon(android.R.drawable.ic_dialog_info)
.create();
#Override
protected void onPreExecute() {
if (Helper.minutes <= 0) {
task.cancel(true); // Cancel AsyncTask
}
}
#Override
protected Void doInBackground(Void... result) {
if (!this.isCancelled()) { // Executed
Log.e("FetchAbbo: ", "Cancelled!"); // Printed
util.disconnect();
return null;
}
try {
Log.e("FetchAbbo: ", "still running!");
// Do the heavy stuff
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onCancelled() {
Log.e("CANCELLED", "TAB3"); // Not printed, onCancelled() not called?
if(this.isCancelled()){
this.taskDialog.show();
}
super.onCancelled();
}
#Override
protected void onPostExecute(Void result) {
if(this.isCancelled()){
this.taskDialog.show();
} else {
setupTxtViews();
mScrollView.setVisibility(View.VISIBLE); // Set ScrollView visible
}
}
}
I want to show a progressDialog on my page when the user clicks on the button.On click of button i am sorting my results that is a List.Now how can we show a progressDialog on click of a button.Please suggest me
This function i am using to sort that data :
public void sortByDate(View v) {
Collections.sort(tripParseData.getDetails());
setData(tripParseData);
}
After #Monica Suggestion
public void sortByDate(View v) {
new LoadData().execute();
}
class LoadData extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
Collections.sort(tripParseData.getCoroprateBookingDetails());
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progressDialog.dismiss();
setApprovalDetailsData(tripParseData);
}
}
you have to call progressdiolog.show before the long calculation starts and then the calculation has to run in a separate thread. A soon as this thread is finished, you have to call pd.dismiss() to close the prgoress dialog.
here you can see an example:
the progressdialog is created and displayed and a thread is called to run a heavy calculation:
Override
public void onClick(View v) {
pd = ProgressDialog.show(lexs, "Search", "Searching...", true, false);
Search search = new Search( ... );
SearchThread searchThread = new SearchThread(search);
searchThread.start();
}
and here the thread:
private class SearchThread extends Thread {
private Search search;
public SearchThread(Search search) {
this.search = search;
}
#Override
public void run() {
search.search();
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
displaySearchResults(search);
pd.dismiss();
}
};
}
Don't forget to vote me up :)
Paste This Class in ur activity and call new LoadData().execute to start the prgress dialog :
class LoadData extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
ProgressDialog pg=new ProgressDialog(ChartsActivity.this);
pg=pg.show(ChartsActivity.this, "Loding", "Plz Wait...");
}
#Override
protected Void doInBackground(Void... params) {
sortByDate();
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
pg.dismiss();
}
}
I have not tested it but I think it can help you.
Declare these two objects in your class and member variables.
Thread thread = null;
ProgressDialog bar = null;
Use this logic on your button click listener it can work in your case. I have not tested it but It will give you Idea how things should work. you can also use handlemessage in place of runonuithread
if (thread == null
|| (thread != null && !thread.isAlive())) {
thread = new Thread(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//DISPLAY YOUR PROGRESS BAR HERE.
bar = ProgressDialog.show(getApplicationContext(), "LOADING..", "PLEASE WAIT..");
}
});
// SORT COLLECTION HERE
runOnUiThread(new Runnable() {
#Override
public void run() {
//CLOSE YOUR PROGRESS BAR HERE.
bar.dismiss();
}
});
}
});
thread.start();
}
Hope this will help you.
try to use AsyncTask http://developer.android.com/reference/android/os/AsyncTask.html
Sample code:
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
//Show UI
//Start your progress bar
showProgress();
}
#Override
protected Void doInBackground(Void... arg0) {
// do your sorting process
return null;
}
#Override
protected void onPostExecute(Void result) {
//Show UI
//dismiss your progress bar
hideProgress();
}
};
task.execute((Void[])null);
Show and hide progress code
public void showProgress() {
progressDialog = ProgressDialog.show(this, "",
"Loading. Please wait...");
progressDialog.setCancelable(false);
}
public void hideProgress() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
I have a asynctask and I want to make it to be canceled after some time, 60 sec for example.
I think I have to it inside a while statemant, but I dont know how to count the time.
Here is my idea:
public class ThreadWithAutoCancel extends AsyncTask<Void, Void, Void> {
public ThreadWithAutoCancel(int timeOut) {
WatchDog watchDog = new WatchDog(this);
watchDog.execute(timeOut);
}
#Override
protected Void doInBackground(Void... params) {
// Do the job
return null;
}
class WatchDog extends AsyncTask<Integer,Void,Void>{
private long startTime;
private AsyncTask task;
public WatchDog(AsyncTask taskToStop){
task = taskToStop;
}
#Override
protected void onPreExecute(){
startTime = System.currentTimeMillis()/1000;
}
#Override
protected Void doInBackground(Integer... params) {
while(System.currentTimeMillis()/1000 < startTime+params[0]){
}
task.cancel(true);
return null;
}
}
}
After starting the AsyncTask, hold a reference to it and call cancel on it 60 seconds later, perhaps on a UI Thread Handler. Inside your doInBackground method you will have to make sure you return if isCancelled returns true. I hope the following snippet will help:
public class MyActivity extends Activity {
private Handler mHandler;
private AsyncTask<?, ?, ?> mTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
}
#Override
protected void onPostResume() {
super.onPostResume();
mTask = new MyCustomTask();
mTask.execute(1, 2, 3);
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mTask.cancel();
}, 60L);
}
}
And inside your custom task:
public class MyCustomTask extends AsyncTask<Integer, Float, String> {
#Override
protected String doInBackground(Integer... params) {
String output = "";
for (Integer i : params) {
// Check status for each param
if (isCancelled()) {
return output;
}
...
}
}
#Override
protected void onCancelled(String result) {
// This bit runs on the UI thread
...
}
You can do this using handler. For example this code will show "Completed" on TextView with R.id.mytext after asynctask will execute for 60 seconds:
final int FINISH = 1;
Thread waitingThread;
MyAsyncTask myAsyncTask;
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == FINISH)
{
myAsyncTask.cancel(true);
((TextView) findViewById(R.id.mytext)).setText("Completed");
}
};
};
// ...
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
waitingThread = new Thread(new Runnable() {
#Override
public void run() {
try {
TimeUnit.SECONDS.sleep(60);
mHandler.sendEmptyMessage(FINISH);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
waitingThread.start();
}
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
while (true) {
// do something
}
}
}
I have a thread that run several operations once and I would like to stop it when the user cancels the ProgressDialog.
public void run() {
//operation 1
//operation 2
//operation 3
//operation 4
}
This thread runs only once, so I can't implement a loop to check if he thread should still be running.
Here is my ProgressDialog :
//Wait dialog
m_dlgWaiting = ProgressDialog.show(m_ctxContext,
m_ctxContext.getText(R.string.app_name),
m_ctxContext.getText(R.string.msg_dlg_analyse_pic),
true, //indeterminate
true,
new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
m_bRunning = false;
}
});
As I don't know how to stop the thread, would it be correct to sequence the thread's operations through a loop to see if it should still be running, or is there a better way ?
public void run() {
int op = 0;
while(m_bRunning) {
switch(op) {
case 0 :
//operation 1
break;
case 1 :
//operation 2
break;
case 2 :
//operation 3
break;
case 3 :
//operation 4
break;
}
op++;
}
}
Even with this solution, if there are too much operations in the thread, it could be hard to sequence the operations. Is there a better way to achieve this ?
Use callbacks or AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
#Override
protected void onPreExecute()
{
this.dialog = new ProgressDialog(context);
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(true);
this.dialog.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
// cancel AsyncTask
cancel(false);
}
});
this.dialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
// do your stuff
return null;
}
#Override
protected void onPostExecute(Void result)
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
#Override
protected void onCancelled()
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
};
task.execute();
You can use Asynctask like below
FetchRSSFeeds fetchRss = new FetchRSSFeeds()
fetchRss.execute();
private class FetchRSSFeeds extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
/**
* Write your RUN method code here
*/
if (isCancelled()) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
}
}
And when you want to cancel your background process do below
if (fetchRss.getStatus() == AsyncTask.Status.RUNNING) {
fetchRss.cancel(true);
}
I am developing an application in android, where i need to display a splash screen and at the same time there will be server communication. The problem here is when i launch the app, first application is communicating with the server and then it is displaying the splash screen. I want to both server communication and splash screen at the same time.
The following is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
try {
Thread thread = new Thread(this);
thread.start();
thread.join();
//Attractions
CommonMethods.getSystemOutput("Response Json Array String Attractions:::"+jArrayMobileAttractions);
attractionsDate = JsonParsing.getLatestDate(jArrayMobileAttractions);
attractionsDate = getDate(attractionsDate);
CommonMethods.getSystemOutput("Attractions Date:::::"+attractionsDate);
//Categories
CommonMethods.getSystemOutput("Response Json Array String Categories:::"+jArrayCategories);
categoryDate = JsonParsing.getLatestDate(jArrayCategories);
categoryDate = getDate(categoryDate);
CommonMethods.getSystemOutput("Category date:::"+categoryDate);
//Contacts
CommonMethods.getSystemOutput("Response Json Array String Contacts:::"+jArrayContacts);
contactsDate = JsonParsing.getLatestDate(jArrayContacts);
contactsDate = getDate(contactsDate);
CommonMethods.getSystemOutput("Contacts Date:::"+contactsDate);
} catch (Exception e) {
CommonMethods.getSystemOutput("Exception in Splash screen thread:::"+e);
}
}
public void run() {
// if (attractionsDate == null) {
jArrayMobileAttractions = RequestHandler.getJSONfromURL(Constants.MOBILE_ATTRACTIONS_URL);
jArrayCategories = RequestHandler.getJSONfromURL(Constants.CATEGORY_URL);
jArrayContacts = RequestHandler.getJSONfromURL(Constants.CONTACTS_URL);
// } else {
// jArrayMobileAttractions = RequestHandler.getJSONfromURL(Constants.MOBILE_ATTRACTIONS_URL+"?lastupdateddate="+attractionsDate);
// }
}
You can use the AsynchTask Manager in which it has a method
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// Do Server Interaction Here
return response;
}
#Override
protected void onPreExecute(String result) {
//Show your Splash Screen
}
#Override
protected void onPostExecute(String result) {
//Gone the Splash Screen view
}
}
For this purpose it will be better start from "SplashActivity" - in onCreate() start new Thread for communication with server, and when all communication finished - call startActivityForResult(mainActivityIntent). For correct behavior back button finish splash activity on finish main activity. Approximate code:
public class SplashActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup view for activity
new Thread(new Runnable() {
public void run() {
// do here some long operation
startActivityForResult(new Intent(SplashActivity.this, MainActivity.class), 0);
}
}).start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
finish();
}
}
I had the same thing to do and I did it this way and it works just fine. I had to show the splashscreen and download some file from the server, unzip it, move files insto proper directories and then start the apps main screen. Here is the code, I used AsyncTask.
So, you have three AsyncTask classes, one for each task and in the onPostExecute() I call the next AsyncTask. I can't say if this is the best way but it works for me.
I removed unneccessary code but for clarity I left a call to a dialog where I ask a user ih he wants to proceed with downloading as it may take a while. Also I check if FIRST_RUN is true just so I know if I should download the package since for my app I need to do it only the first time, so if it is true I do the spashscreen activities and if it is false I proceed to MAINAPP activity.
Hope it helps.
public class SplashScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
SharedPreferences settings = getSharedPreferences(PREFS_NAME,0);
boolean firstRun = settings.getBoolean("FIRST_RUN", true);
if (firstRun) {
showDialog(INITIAL_DLG);
} else {
startActivity(new Intent(appContext, MAINAPP.class));
}
}
/***
* First entry after YES on Dialog!
*/
protected void initialize() {
messageTV.setVisibility(TextView.VISIBLE);
progressBar.setVisibility(ProgressBar.VISIBLE);
downloadThread = new DownloadFiles();
downloadThread.execute();
}
protected void rollback() {
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
switch (id) {
case INITIAL_DLG:
builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.app_setup)
.setCancelable(false)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
initialize();
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDlg = builder.create();
return alertDlg;
default:
return null;
}
}
protected class DownloadFiles extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//file download
} catch (Exception e) {
result = false;
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
unzipThread = new DecompressZipFile();
unzipThread.execute();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
messageTV.setText("Step 1/4:Downloading data...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
}
protected class DecompressZipFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//unzip files
return true;
} catch(Exception e) {
return false;
}
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (values[0]<0) progressBar.setMax(values[0]*-1);
else progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
moveDBThread = new MoveDBFile();
moveDBThread.execute();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
messageTV.setText("Step 2/4:Decompressing data...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
}
protected class MoveDBFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//moving files
return true;
} catch (Exception e) {
globalE = e;
finish();
return false;
}
}
#Override
protected void onPreExecute() {
messageTV.setText("Step 3/4:Shufflin'...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
getSharedPreferences(PREFS_NAME,0).edit().putBoolean("FIRST_RUN", false).commit();
startActivity(new Intent(appContext, MAINAPP.class));
} else {
rollback();
}
}
}
}