Android ProgressDialog while selecting and deselecting checkboxes using AsyncTask - android

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();
}
}

Related

ProgressDialog showing for a fraction of a second, if at all

I am working on a calculator app for my first project with android. Some of the calculations take a while because of how many operands are put in the equation. I'm using mxparser api to evaluate the equation. A progressDialog is supposed to show during my asyncTask, but it only shows for a fraction of a second if at all.
I have tried other solutions on stackoverflow and nothing so far has worked. Any ideas as to why this is occurring?
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText editScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
editScreen = (EditText) findViewById(R.id.calculator_display);
Button btnEq = (Button) findViewById(R.id.btn_equals);
btnEq.setOnClickListener(this);
}
#Override
public void onClick(View v) {
String equation = editScreen.getText().toString();
switch (v.getId()) {
case R.id.btn_equals:
doCalculation(equation);
break;
default:
Log.e("ERROR", "button was not implemented: " + v.getId());
}
}
private void doCalculation(String equation) {
Expression expression = new Expression(equation);
boolean isCorrectSyntax = expression.checkSyntax();
if (isCorrectSyntax) {
new calcAsync(MainActivity.this, equation).execute(expression);
} else {
Toast.makeText(getApplicationContext(), "Error in expression, please check syntax", Toast.LENGTH_LONG).show();
}
}
private class calcAsync extends AsyncTask<Expression, Void, Void> {
private ProgressDialog dialog;
private String equation;
private String answer;
public calcAsync(Context context, String equation) {
this.equation = equation;
}
#Override
protected Void doInBackground(Expression... params) {
Log.d("DEV", "starting calculation");
Double result = params[0].calculate();
String[] r = result.toString().split("\\.");
if (result.equals(Double.NaN) || result.equals(Double.NEGATIVE_INFINITY) || result.equals(Double.POSITIVE_INFINITY)) {
answer = result.toString();
} else if (r[1].length() == 1 && Integer.parseInt(r[1]) == 0) {
answer = r[0];
} else {
answer = result.toString();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.setMessage("Calculating...");
dialog.setTitle("Please wait...");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.show();
Log.d("DEV", "dialog shown");
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (dialog != null) {
Log.d("DEV", String.valueOf(dialog.isShowing()));
dialog.dismiss();
Log.d("DEV", "Dialog dismissed");
}
editScreen.setText(answer);
saveToHistory(equation, answer);
}
}
}
Update 7/14/16:
It seems that the actual calculation itself doesn't take long at all. But from the time it takes after the equals button is pressed, until the result is displayed takes a while. 3 seconds for a long string of 1+1... (33 additions in my testing), longer if the string is longer than that.
Update 7/18/16:
I found out why my progressDialog wasn't showing. In the doCalculation method I am checking the syntax with equation.checkSyntax() before the asyncTask. This is where my delay was coming from, so the asyncTask wasn't doing the bulk of the work. after adding it in the asyncTask, I noticed that it takes considerably longer for the same test case as my previous update.
If you know that the delay occurs from the time the equals button is pressed, why not move the ProgressDialog to start there instead?

android - doInBackground return always false

I'm trying to shows a ProgressDialog while a list is loading data in an AsyncTask, but 'exito' in onPostExecute is never true, and the dialog never dismiss.
I tried to delete the if (exito) but the progressDialog dismiss and the list is charged a few seconds later, and it isn't I want.
I want that progressDialog shows while is loading, and when is loaded, dismiss the progressDialog and change fragment.
Where is my mistake? Thanks
private class ATCargarProductos extends AsyncTask<Void, Integer, Boolean>{
boolean terminado = false;
Bundle bdl;
FragmentTransaction transaction;
ProgressDialog progressDialog;
ArrayList<ItemDetails> results = new ArrayList<ItemDetails>();
public ATCargarProductos(FragmentTransaction transaction){
this.transaction = transaction;
}
#Override
protected Boolean doInBackground(Void... params) {
if (compruebaConexion()) {
rellenaLista(new CallBack() {
#Override
public void onSuccess(final ArrayList<Comida> listaComidas) {
for (int i = 0; i < listaComidas.size(); i++) {
ItemDetails item_details = new ItemDetails(listaComidas.get(i));
if (item_details.getTipo().equals("B")) {
results.add(item_details);
}
}
Fragment fragmentProductos = new FragmentProductos();
bdl = new Bundle(2);
bdl.putInt("tipoProducto", 1);
bdl.putParcelableArrayList("resultados", results);
fragmentProductos.setArguments(bdl);
completado = true;
}
#Override
public void onFail(String msg) {
}
});
return completado;
} else {
return false;
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(getActivity(), R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Cargando lista...");
progressDialog.show();
}
#Override
protected void onPostExecute(Boolean exito) {
super.onPostExecute(exito);
if (exito) {
progressDialog.dismiss();
transaction.commit();
}
}
}
rellenaLista() is asynchronous.
Since it's running on a different thread, return completado; is executed before you reach onSuccess(), and therefore completado is still false.
You don't really need an AsyncTask.
You can do the following:
if (compruebaConexion()) {
// show progress dialog here
rellenaLista(new CallBack() {
#Override
public void onSuccess(final ArrayList<Comida> listaComidas) {
// dismiss dialog
// handle success
}
#Override
public void onFail(String msg) {
// dismiss dialog
// handle failure
}
});
}
I think that the method compruebaConexion()is always false, if you can add to the question the code of this method. I could admit this idea.
Create a class like that. And check your internet connection with it.
public class EZInternetConnection {
public static boolean isNetworkConnected(Context context)
{
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean flag = cm.getActiveNetworkInfo() != null &&
cm.getActiveNetworkInfo().isConnectedOrConnecting();
return flag;
}
}
Usage:
if(EZInternetConnection.isNetworkConnected( context ))
{
//internet connection is ok.
//other codes.
}
else
{
//no internet.
}

Updating table from async task android

I'm following this tutorial
to learn how to make progress bars. I'm trying to show the progress bar on top of my activity and have it update the activity's table view in the background.
So I created an async task for the dialog that takes a callback:
package com.lib.bookworm;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
public class UIThreadProgress extends AsyncTask<Void, Void, Void> {
private UIThreadCallback callback = null;
private ProgressDialog dialog = null;
private int maxValue = 100, incAmount = 1;
private Context context = null;
public UIThreadProgress(Context context, UIThreadCallback callback) {
this.context = context;
this.callback = callback;
}
#Override
protected Void doInBackground(Void... args) {
while(this.callback.condition()) {
this.callback.run();
this.publishProgress();
}
return null;
}
#Override protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
dialog.incrementProgressBy(incAmount);
};
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(context);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
dialog.setProgress(0);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMax(maxValue);
dialog.show();
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
this.callback.onThreadFinish();
}
}
In My Activity:
final String page = htmlPage.substring(start, end).trim();
//Create new instance of the AsyncTask..
new UIThreadProgress(this, new UIThreadCallback() {
#Override
public void run() {
row_id = makeTableRow(row_id, layout, params, matcher); //ADD a row to the table layout.
}
#Override
public void onThreadFinish() {
System.out.println("FINISHED!!");
}
#Override
public boolean condition() {
return matcher.find();
}
}).execute();
So the above creates an async task to run to update a table layout activity while showing the progress bar that displays how much work has been done..
However, I get an error saying that only the thread that started the activity can update its views. I tried changing my Async Task's run to the following:
MainActivity.this.runOnUiThread(new Runnable() {
#Override public void run() {
row_id = makeTableRow(row_id, layout, params, matcher); //ADD a row to the table layout.
}
}
But this gives me synchronization errors.. Any ideas how I can display progress and at the same time update my table in the background?
Currently my UI looks like:
Whatever update that you are doing in the UI do it in progress update, use Global Variables to pass values or use Getter Setter.
Here is a simple example, from one of my current project.
It changes the width of the LinearLayout, which acts as progress bar and also updates the textview with X%. Am updating by calling onProgressUpdate
public class Updater extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
width = getWindowManager().getDefaultDisplay().getWidth();
Log.wtf(tag, "width" + width);
}
#Override
protected Void doInBackground(Void... params) {
while (updated < sleep) {
try {
Thread.sleep(updateEveryXmillSec);
updated = updated + updateEveryXmillSec;
publishProgress();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
mTextView.setText((int) (100 * updated / sleep) + " %");
xwidth = (width * ((int) (100 * updated / sleep)) / 100);
mLayout.setLayoutParams(new RelativeLayout.LayoutParams(xwidth,
height));
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startActivity(new Intent(getApplicationContext(), Main.class));
finish();
}
}
Call new Updater().execute(); to trigger the action.
You should split your UI data from the Row Data. Make a RowObject which contains the data to display in the table:
class RowData {
String program;
String course;
String bookName;
// get/set etc
}
You can fill this object in the UIThreadProgress class run method and push it to a synced list.
In onProcessUpdate() you can than build the View Object based on the synced list and add it to the View Hierachie. You are on the UI thread now, and adding should be possible.
You have to care about a synced list during this. Because the Background Thread and the UI Thread will adding and removing objects at the same time. a synchronized will help here. Depending on the speed of your algorithm to calculate the needed data, a faster approach than the synced list is better. But the Idea is always the same. You have to split your data and the View Operations.

ProgressDialog not shown in AsyncTask

I have a huge database (40MB) on an SDCard. I need fetch data, with LIKE in query, which is very slow.
DB request takes about 5 seconds. Therefore, I need to do it asynchronously and with ProgressDialog.
I tried it with AsyncTask, but problem is with ProgressDialog. It was implemented this way:
private class GetDataFromLangDB extends AsyncTask<String, String, String> {
private final ProgressDialog dialog = new ProgressDialog(TranslAndActivity.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
urDBCursor.close();
curDBCursor = null;
scaAdapter = null;
this.dialog.setMessage("Loading data...");
this.dialog.show();
}
#Override
protected String doInBackground(String... whatSearch) {
String result = "";
if (myDatabaseAdapter != null) {
curDBCursor = myDatabaseAdapter.fetchAll(whatSearch[0]);
}
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
prepareListView();
}
}
The problem is that ProgressDialog is not shown during the DB request.
After finished database query, it flash on screen for a short time. When user tries
to tap on screen during database request, UI is freezed, and after DB request
message about 'not responding' is shown.
I tried it with a thread this way:
public void startProgress(View view, final String aWhatSearch) {
final ProgressDialog dialog = new ProgressDialog(MyActivity.this);
if (curDBCursor != null){
curDBCursor.close();
curDBCursor = null;
}
dialog.setMessage("Loading data...");
dialog.show();
Runnable runnable = new Runnable() {
public void run() {
curDBCursor = myDatabaseAdapter.fetchAll(aWhatSearch);
// dirty trick
try {
Thread.sleep(250); // it must be here to show progress
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
public void run() {
if (dialog.isShowing()) {
dialog.dismiss();
}
prepareListView();
}
});
}
};
new Thread(runnable).start();
}
The result was the same, but when I used the trick with Thread.sleep(250);
ProgressDialog was shown during the database request. But it is not spinning,
it looks freezed during the DB request.
DB stuff is called this way (after tap on search button):
btnSearchAll.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// AsyncTask
new GetDataFromLangDB().execute(edtTextToSearch.getText().toString());
// or Thread
//startProgress(null, edtTextToSearch.getText().toString());
}
});
I found a lot of problems like this in SO, but nothing was useful for me.
Could it be that DB is on SD Card?
I put the definition of the dialog into the AsyncTask Class and it works fine for me.
Take a look at this exampel (You have to change NAMEOFCLASS in the name of your CLASS:
private class doInBackground extends AsyncTask<Integer, Integer, Void> {
final ProgressDialog dialog = new ProgressDialog(NAMEOFCLASS.this) {
#Override
protected void onPreExecute() {
dialog.setCancelable(false);
dialog.setTitle(getString(R.string.daten_wait_titel));
dialog.setIcon(R.drawable.icon);
dialog.setMessage(getString(R.string.dse_dialog_speichern));
dialog.show();
}
#Override
protected void onCancelled() {
dialog.cancel();
}
....
#Override
protected void onProgressUpdate(Integer... values) {
// DO YOUR UPDATE HERE
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
Maybe this SO answer could help you. It looks like similar problem. Try to use AsyncQueryHandler for querying your database
declare you Dialog box on Class (Activity) level like this
private ProgressDialog dialog = null;
show the progress dialog and call the AsyncTask class when you want to start you Busy work..like onButton click or any
dialog = ProgressDialog.show(this,"Sending Email to your account please! wait...", true);
SendingEmailTask task = new SendingEmailTask();
String s = "";
task.execute(s);
create your inner class like
private class SendingEmailTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
//do your work here..
// like fetching the Data from DB or any
return null;
}
#Override
protected void onPostExecute(String str) {
//hide progress dialog here
dialog.dismiss();
}
}
let me know if this help!!

Loading State or Async Task

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();
}
}
}

Categories

Resources