Loading State or Async Task - android

I have an activity that loads an xml file, but when the app is invoked without reply in 1 or 2 seconds, I wonder if I can put some kind of loading not to appear that the app crashed, thanks.

The rule of thumb is, if you do anything, use AsyncTask, otherwise your application will eventually crash on long network delays or large files.
private class doSomethingTask extends AsyncTask<SomeData,Integer,SomeData[]> {
private ProgressDialog dialog;
protected SomeData[] doInBackground(SomeData... values) {
int count = values.length;
for( int i=0; i<count; i++) {
publishProgress(count,i+1);
// do something here
....
//
if( isCancelled() ) return null;
}
return values;
}
protected void onPreExecute()
{
// show progress bar or something
dialog = new ProgressDialog(context);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage(context.getString(R.string.downloading));
dialog.show();
}
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
dialog.setMax(values[0]);
dialog.setProgress(values[1]);
}
protected void onPostExecute(SomeData[] result) {
// kill progress bar here
if( this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
}

Related

Android asynctask show progress dialog until function has finished

I know this answer has already been answered multiple times but I cannot get it to work properly. It's starts with activity A where a user needs to login via the function authenticate. When the user hits the button login I want the progressdialog to appear until the function authenticate has got a response. While success you go to another activity where you can navigate through the app.. Anyway sometimes when the internet is slow or if you're on mobile internet I still see activity A for a few seconds doing nothing while the auth function is going on. When it's done the system hops to activity B.
I tried using sleep thread thingy but that's not the point.. I want the progressdialog to appear when the user hits login and dissapear when the auth function has been finished.
With the help of AsyncTask I sometimes see the dialog for one flash of a second but not how it should be.. I also want to use asynctask for loading my listviews but the dialog isn't doing what it should.
Here my AsyncTask code
public class HeavyWorker extends AsyncTask<String, Context, Void> {
private ProgressDialog dialog;
public HeavyWorker() {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(AuthenticationActivity.this);
dialog.setMessage("Gettting data");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Void doInBackground(String... params) {
authenticate(username, password, autoLogin);
return null;
}
#Override
protected void onPostExecute(Void result) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
}
And where I call the asynctask
builder.setTitle(R.string.dialog_authenticate)
.setIcon(R.drawable.ic_launcher)
.setView(viewInflater)
.setPositiveButton(R.string.dialog_button_login,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
EditText ETusername = (EditText) viewInflater.findViewById(R.id.username);
EditText ETpassword = (EditText) viewInflater.findViewById(R.id.password);
CheckBox optionAutoLogin = (CheckBox) viewInflater
.findViewById(R.id.autoLogin);
checkAutoLogin = 0;
if (optionAutoLogin.isChecked()) checkAutoLogin = 1;
username = ETusername.getText().toString();
password = ETpassword.getText().toString();
new HeavyWorker().execute();
//authenticate(ETusername.getText().toString(), ETpassword.getText().toString(), checkAutoLogin);
}
})
Any help or advice is appreciated.
Are you finishing the activity A when authentication success? In that case, you could skip onPostExecute
The Documentation gives you quite a good example: You can post the Progress in the onProgressUpdate(...) And can update it from doInBackground via publishProgress(int i)
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
//DO YOUR PROGRESSBAR THINGS HERE
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

Can't cancel Async task in android

I need to cancel my asyncthread . In my application I am doing some heavy calculations, and I want to give user ability to cancel calculations(and then retry). I read on forums, that you can't just stop task from what is it doing, and that you need to check if task isCancelled=true inside your DoinBackground code. But that doesn't work for me.
Task itself is working great and it outputs correct data if I leaved it to end on itself.
In my App first I call function naredi_pdf_start(view), then when the task is running, if I call close_pdf1(view), it gives me an error.(I am changing views and app can't find my pdf_text1 Textview when calling publishProgress- null pointer exception). I really dont know how to use task.cancel(true) method (in my case: start_pdf.cancel(true))).
Here is my code:
String progress_pdf;
naredi_pdf start_pdf;
public void naredi_pdf_start(View view) {
start_pdf=new naredi_pdf();
start_pdf.execute();
}
public void close_pdf1(View view) {
if(start_pdf!=null) {
Log.v("not null","not null");
start_pdf.cancel(true);
setContentView(R.layout.other_view); //This is where
//I don't have TextView pdf_text1
}
}
private class naredi_pdf extends AsyncTask<Void, String, Void> {
protected Void doInBackground( Void... ignoredParams ) {
progress_pdf="Calculating Statistical Data";
//A LOT OF CODING
for(int i = 0; i < 1; i++) {
if(isCancelled()) {
break;
}
else {
publishProgress("Calculating team statistics");
}
}
//MORE OF CODING
for (int i = 0; i < 1; i++) {
if (isCancelled()) {
break;
}
else {
publishProgress("Calculating player's BIO");
}
}
//MORE OF CODING
for (int i = 0; i < 1; i++) {
if (isCancelled()) {
break;
}
else {
publishProgress("Calculating player's individual performance");
}
}
return null;
}
protected void onPostExecute( Void array ) {
//saving to database
}
protected void onProgressUpdate(String... values) {
progress_pdf=values[0]+"\n"+progress_pdf;
if (isCancelled()) {
}
else {
TextView pdf_text1 = (TextView) findViewById (R.id.pdf_text1);
pdf_text1.setText(progress_pdf);
// dialog(view);
}
}
}
Your problem is not that you can't cancel the AsyncTask. You probably get NullPointerException because your call to setContentView() goes through before AsyncTask.cancel() has been successful. A onProgressUpdate() gets called, only to find that the layout is now changed and there is no Viewwith id=R.id.pdf_text1!
From documentation on AsyncTask.
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
Since onCancelled() runs on the UI thread, and you are certain that no subsequent calls to onProgressUpdate() will occure, it's is a great place to call setContentView().
Override onCancelled() in you AsyncTask
private class naredi_pdf extends AsyncTask<Void, String, Void> {
protected Void doInBackground( Void... ignoredParams ) { // YOUR CODE HERE}
protected void onPostExecute( Void array ) { // YOUR CODE HERE}
protected void onProgressUpdate(String... values) {// YOUR CODE HERE}
// ADD THIS
#Override
protected void onCancelled() {
// Do not call super.onCancelled()!
// Set the new layout
setContentView(R.id.other_layout);
}
}
Change close_pdf1()
public void close_pdf1(View view) {
if(start_pdf!=null) {
Log.v("not null","not null");
start_pdf.cancel(true);
}
}
And you should have an AsyncTask that automatically changes your layout when cancelled. Hopefully you should not encounter any NullPointerException either. Haven't tried the code though :)
Edit
If you feel fancy, follow Rezooms advice on using return.
for(int i = 0; i < 1; i++) {
if(isCancelled()) {
return null;
}
.
.
.
}
The return statement cancels the execution of the doInBackground method, not break.
isCancelled is a propietary method of AsyncTask class.
You should define a private boolean property on your extended class, do something like this
private class myAsyncTask extends AsyncTask<Void, String, Void> {
private boolean isTaskCancelled = false;
public void cancelTask(){
isTaskCancelled = true;
}
private boolean isTaskCancelled(){
return isTaskCancelled;
}
protected Void doInBackground( Void... ignoredParams ) {
//Do some stuff
if (isTaskCancelled()){
return;
}
}
protected void onPostExecute( Void array )
{
//Do something
}
protected void onProgressUpdate(String... values)
{
//Do something
}
}

How do you clear a determinate progress bar for reuse?

I have an Activity with a button that starts a long running task. I perform the task using an AsyncTask and display a determinate ProgressBar that is updated as the task progresses. Everything works fine the first time the task is run, but on subsequent runs the dialog appears, but is already at 100% and 100/100. I'm overriding both onCreateDialog and onPrepareDialog in my Activity. I presumed that using setProgress(0) would reset the dialog, but this isn't working. I use showDialog in the AsyncTask's onPreExecute method and dismissDialog in the AsyncTask's onPostExecute. The only way I've been able to get the dialog to reset is by using removeDialog in onPostExecute, but I would rather not recreate the dialog as I'm going to be reusing several times. The relevant code is below. This is on API level 10.
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(ProtoBufSerializationTestActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(true);
progressDialog.setMax(100);
progressDialog.setMessage("Testing...");
return progressDialog;
default:
return null;
}
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
switch (id) {
case PROGRESS_DIALOG:
ProgressDialog tmp = (ProgressDialog)dialog;
tmp.setProgress(0);
tmp.setSecondaryProgress(0);
return;
default:
Log.e("test", "Unknown dialog requested");
}
}
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
#Override
protected void onPreExecute() {
showDialog(PROGRESS_DIALOG);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dismissDialog(PROGRESS_DIALOG);
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.incrementProgressBy(1);
}
Edit After taking #Arhimed's suggestion I ended up with the following code. It is much simpler. I could have used DialogFragment, but I don't think it is necessary in this case.
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ProtoBufSerializationTestActivity.this, "Serialization Test", "Testing...", false);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dialog.dismiss();
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
dialog.incrementProgressBy(1);
}
}
Actually Arhimed is right and you can't do it but you can force progress bar to come to its zero state with 'dirty' way.For me the client wanted progress bar to zero its value no matter what,in case if user leave that activity,but in my case the progress was still there,and only was reseting from start.I had custom progress drawable and setProgress did not help me at all.So what i did was to call this method before actually setting the REAL drawable setProgressDrawable(null) this is dirty way clearing,but it do what you want,and afterwards just call same method with your own progressdrawable so it feels like it has been refreshed.Thats it..no other way you can achieve this unfortunately.
It is impossible to use ProgressDialog in that way. Your AsyncTask should create a new instance each time.
Actually setProgress(0) refreshes the display only if the progress is started.
So, you can force the refresh by calling onStart before setProgress, like this :
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
ProgressDialog progress = (ProgressDialog)dialog;
progress.onStart();
progress.setProgress(0);
}

ProgressDialog within AsyncTask not updated

I am having a problem with ProgressDialog UI being frozen when I start the action in the AsyncTask.
My problem is somewhat different than the bunch of other similar question because the my background task consists of two parts:
- first part (loadDB()) is related to the database access
- second part (buildTree()) is related to building the ListView contents and is started with runOnUiThread call
The progress dialog is correctly updated during the 1st part of the task, but not during the 2dn part.
I tried moving the buildTree part in the AsyncTask's onPostExecute but it doesn't help, this part of the code still causes the progress to freeze temporarily until this (sometimes quite lengthy) part of the work is done. I can not recode the buildTree part from scratch because it is based on external code I use.
Any tips on how to resolve this? Is there a method to force updating some dialog on screen?
The code goes here:
public class TreePane extends Activity {
private ProgressDialog progDialog = null;
public void onCreate(Bundle savedInstanceState) {
// first setup UI here
...
//now do the lengthy operation
new LoaderTask().execute();
}
protected class LoaderTask extends AsyncTask<Void, Integer, Void>
{
protected void onPreExecute() {
progDialog = new ProgressDialog(TreePane.this);
progDialog.setMessage("Loading data...");
progDialog.show();
}
protected void onPostExecute(final Void unused) {
if (progDialog.isShowing()) {
progDialog.dismiss();
}
}
protected void onProgressUpdate(Integer... progress) {
//progDialog.setProgress(progress[0]);
}
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
//long UI thread operation here, blocks progress!!!!
runOnUiThread(new Runnable() {
public void run() {
buildTree();
}
});
return null;
}
}
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
progDialog.setProgress(0);
//add tree item here
}
}
}
Don't run your whole buildTree() method inside the UI thread.
Instead, run only the changes you want to make to the UI in the UI thread:
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
buildTree();
return null;
}
And then:
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
progDialog.setProgress(0);
runOnUiThread(new Runnable() {
public void run() {
// update your UI here and return
}
});
// now you can update progress
publishProgress(i);
}
}
You should call AsyncTask's publishProgress method and not the progDialog.setProgress(0); as you call.
Also the buildTree shouln't run on the UI thread since it will block it.
run the logic from the doInBackground method.
note that you don't actually build the ListView, rather you should build it's data model.
look here
something like this:
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
buildTree();
}
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
publishProgress(i); //for exmple...
//add tree item here
}
}

Android ProgressDialog while selecting and deselecting checkboxes using AsyncTask

I'm a newbie to Android and I'm having some problems with the AsyncTask class. I have a lot of (over 100) check boxes which I want to select or deselect with a "select all" check box.
Unfortunately this takes quite some time, noticeable for the user, so I want to use the ProgressDialog to show that the selecting is in progress.
Now I know that updates of the UI elements are supposed to be done in the UI thread so I have the selecting code in the onProgressUpdate method but the ProgressDialog doesn't show up not until the processing (select or deselecting all checkboxes) is finished...
How is this supposed to be done? Is there any workaround or any other solution? I also tried to go through all the check boxes in the doInBackground() method but I get lots of weird errors (I guess it's because of the UI).
This is my code:
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
private ProgressDialog Dialog = new ProgressDialog(Preferences.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
}
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
//Dialog.show();
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.cancel();
}
}
What if you create and show the dialog before executing the AsyncTask? That's the way it usually is used:
private ProgressDialog Dialog;
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
Dialog = new ProgressDialog(Preferences.this);
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.dismiss();
}
}

Categories

Resources