Running Alert Dialog While Asynctask is processing - android

I currently have an android application that runs an asynctask when a button on the activity is clicked. While the asynctask is busy processing its task, I want the activity to display an alertdialog (loading...) to let my users know that the app is busy processing the request, and not just frozen or crashed. Currently, I have the code written like this:
LoadingDialogue.java
public class LoadingDialogue {
private Activity activity;
private AlertDialog dialog;
public LoadingDialogue(Activity myActivity){
activity = myActivity;
}
public void startLoadingDialogue(){
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
LayoutInflater inflater = activity.getLayoutInflater();
builder.setView(inflater.inflate(R.layout.loading_dialogue,null));
builder.setCancelable(false);
dialog = builder.create();
dialog.show();
}
public void dismissDialog(){
dialog.dismiss();
}
and this is how I implemented it in my activity:
CustomAsyncTask asyncTask = new CustomAsyncTask();
loadingDialogue.startLoadingDialogue();
String responseString = asynctask.execute().get()
loadingDialogue.dismissDialog();
However, my loading dialog does not show! It works if I just do it without the async task though.
Thanks!

That code is broken in so many ways.
Never use AsyncTask.execute().get(). Doing that gets the result immediately, which turns it from asynchronous to synchronous. Basically at that point there's no reason to make it an async task, just do it in the body. If your response is that you need the result immediately, you don't understand asynchronous programming. Put any code that needs the result in the onPostExecute.
Really forget that get() exists at all. There's one or two cases where it can be useful, but 99% of the time using it is an error.
The android UI only refreshed when the main thread returns to the looper. So doing show dialog, then doing get(), then doing hide it won't work- it won't show until the entire block is done and control is returned to the looper, by which time its hidden again.
Instead, use dialog.show() in onPreExecute and hide in onPostExecute. That will make it work.
It's kind of odd to have a class holding a dialog like that. It's more normal to derive a class from AlertDialog and just show/hide it. Although this isn't necessarily wrong, there's cases where this may be more convenient.

Related

Android show toast before methdod

Because you must include a legal notice when using google maps on android I added the following code to my fragment:
//in oncreate view method
_noticeMaps.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
Toast.makeText(getActivity().getApplicationContext(), "Loading", Toast.LENGTH_LONG).show();
showLegalNotice();
}
});
public void showLegalNotice(){
_legalNotice = GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(getActivity());
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Legal Notice");
builder.setMessage(_legalNotice);
AlertDialog dialog = builder.create();
dialog.show();
}
Because the legal notice takes a long time to be placed in the setMessage the app shows the dialog after a few seconds (5+). Thats why i added the toast before the showLegalNotice to notice the user that its loading. However the toast shows after the dialog is loaded. Why isnt the toast showing before the dialog is loading? I call showLegalNotice AFTER i create the toast. I know i can fix it with threads but I want to understand why the toast is showing after the dialog is created.
The best solution is to put the legalNotice method codes in an AsyncTask. The Toast is shown after the dialog because you are doing the heavy work on the UI thread which is making it busy and that's why the toast is lagging behind.
If you don't know about AsyncTask, you can learn about it here. You can show the Toast in the preExecute() method of the AsyncTask. It will be guaranteed that the toast will be shown before any other action is taken.
UPDATE
Yes, you are right. The code is run in a sequential manner so the Toast should have been shown before the method runs. But try to think in a different way.
The Toast is an system UI component. You call show() on toast and your code moves to the next heavy or long-running task almost instantly.
There is always a slight delay for the toasts to be drawn or initiated on your screen and it also depends on various flavours of Android. So, before the toast starts to draw on the screen, the UI thread gets busy or jammed on performing a long-running task and looses frames.
Just when the long-running task of your method ends, the UI thread gets free once again and is able to resume drawing the toast. That is why, the toast is displayed, but always after the method completed its execution.

Can't dismiss progressDialog from activity callback

I know there are a million similar questions here, but none of the solutions presented there quite addressed the issue I'm having. I have an AsyncTask that loads data from a database. An indeterminate ProgressDialog is displayed while the data is loading (even though in production code it never takes a visibly apparent time to load the database, but just in case someone builds a huge one).
I used to call and dismiss the ProgressDialog directly from the AsyncTask, and it worked fine. The problem is, I'm trying to enforce better separation of concerns and I decided that displaying things to the screen does not fall in the AsyncTask's domain, and really belongs to the activity. So I implemented a callback interface to the activity, and in the activity I have:
private ProgressDialog progressDialog;
#Override
public void onPreExecute() {
progressDialog = ProgressDialog.show(this,"","Loading. . .",true,true);
}
#Override
public void onPostExecute() {
if (progressDialog != null) {
Logger.d("Dismissing progress dialog");
progressDialog.dismiss();
progressDialog = null;
}
}
Logcat shows that I'm reaching that logger line, but the ProgressDialog never dismisses. Is there some reason why I can't do this in a callback?
Most likely what's happening here is that multiple ProgressDialog's are being instantiated.
Therefore, while dismiss() is successfully called, it's not called on the ProgressDialog currently visible on your screen, and you've lost your reference to this visible one since you've overwritten progressDialog with a new object instance.
Try putting Logger.d("New ProgressDialog"); where you are creating a new instance of the ProgressDialog, and you will most likely see this scenario confirmed.
You could probably fix this by using an Array/List to keep track of all of your ProgressDialogs and dismiss the appropriate one when it's corresponding AsyncTask completes, but personally I think this is far more convoluted then your original approach of having each AsyncTask handle their own ProgressDialog's lifecycle.
This work for me:
if(progressDialog == null) {
// initialize your progress dialog object
}
if (progressDialog.isShowing() && progress != null) {
progress.dismiss();
}

Display alert dialog while running an Android test case

I am using Robotium to automate testing of an application. Is there a way I can display an alert box while executing a particular test case.
Thanks.
It is possible to do, nearly everything is possible but before I give you the answer do you have a good reason to do this? I cant easily thing of a good reason why a test should open an alert box but you may know best.
Robotium has the method.
solo.getCurrentActivity();
Using this you can get an Activity Context and with such a thing you can do pretty much anything that you could do in an android activity. The page http://developer.android.com/guide/topics/ui/dialogs.html tells us how to make a dialog, you will notice the first line calls a method to get the currentActivity, instead of that I replaced it with the robotium method above.
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(solo.getCurrentActivity());
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(R.string.dialog_message)
.setTitle(R.string.dialog_title);
// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();
this will create a dialog, then just call the dialogs .show() method to show it on the screen.
Robotium tests do not run on the UI Thread, so any code in a test method will in the best case just not work and in the worst case throw and error and cause your test to fail.
To interact with the UI from inside a test method you need to run your code on the UI Thread. This can be done by writing that code inside a Runnable, and sending that Runnable to the runOnUiThread() method of the current Activity. Robotium's solo class has the getCurrentActivity() method, which will allow this execution. Here's an example of how you'd show a Toast using this technique.
public void testDisplayToastInActivity() throws Exception
{
Runnable runnable = new Runnable
{
#Override
public void run()
{
Toast.makeText(solo.getCurrentActivity(), "Hello World", Toast.LENGTH_LONG).show();
}
}
solo.getCurrentActivity().runOnUiThread(runnable);
}
You can use runOnUiThread() to perform many other actions that interact with your Activity, such as creating Alert Dialogs, if you want something more than a Toast. However, I'd suggest against doing any of this, even though you can. Robotium and other testing frameworks are meant to judge the correctness of your application code's execution, and should not inject any logic or UI modifying behavior beyond interacting with your application the way a user would. Your tests will be cleaner if you take any outpu from your tests and log them to Logcat or a file.

Showing AlertDialog from not UI thread

I'm connecting to bluetooth in background and I want to show alert or toast befor processing socket.
Here is my code
mmSocket.connect();
connectionHandler.post(new Runnable() {
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(BluetoothSampleActivity.this);
builder.setMessage("conneted");
builder.show();
}
});
manageConnectedSocket(mmSocket);
but as I understand alert will be shown only when this will end his work. How can i show alert BEFORE executing manageConnectedSocket(mmSocket);?
P.S.: I tryed runOnUiThread - it didn't help
I suggest to move your logic from a normal Thread to an AsyncTask. Whenever you have to do heavy work but also to interact with the UI, AsyncTask is the best practice.
On the preExecute() method you show the dialog or update UI, on doInBackground you do whatever you need to do and on onPostExecute you dismiss the dialog or re-update the UI.
Here the AsyncTask doc.
En plus, if you need to show a progress of the work that you are doing in background, it comes super easy thanks to the methods publishProgress/onProgressUpdate.

Threads and ProgressDialog

I am developing my first Androïd application and I'm facing a problem when I want to display a ProgressDialog to indicate that a process is being run.
In my application, the user triggers a time consuming task by pressing a Button. The "OnClick" function of my "OnClickListener" is called when the user presses the Button. In this function, here is what I'm currently doing :
- creation and configuration of an instance of the ProgressDialog class,
- creation of a thread dedicated to the time consuming task,
- attempt to display the ProgressDialog using the "show" method,
- start of the thread,
- main Activity suspended (call of the "wait" function)
- wake up of the main Activity by the thread when it is finished
- removal of the ProgressDialog by calling the "dismiss" function.
Everything works fine (the result of the long task is correct) but the ProgressDialog nevers appears. What am I doing wrong?
Thanks in advance for the time you will spend trying to help me.
You should not call wait() to the Main Activity/UI thread, because this is actually freezing the UI including your ProgressDialog, so it has no time to fade in and will never be shown.
Try to use multithreading correctly: http://developer.android.com/resources/articles/painless-threading.html
final Handler transThreadHandler = new Handler();
public void onClick(View v) {
// show ProgressDialog...
new Thread(){
public void run(){
// your second thread
doLargeStuffHere();
transThreadHandler.post(new Runnable(){public void run(){
// back in UI thread
// close ProgressDialog...
}});
}
}.start();
}
I would suggest using AsyncTask, as it's purpose is exactly to handle this kind of problem. See here for instructions how to use it. Note that the linked page in Floern's answer also recommends the use of AsyncTask.
You would need to do the following:
subclass AsyncTask
override it's onPreExecute() method to create and show a ProgressDialog. (You could hold a reference to it in a member of your subclass)
override it's doInBackground() method to execute your time consuming action.
override it's onPostExecute() method to hide your dialog.
in your activity, create an instance of your subclass and call execute() on it.
If you make your subclass an inner class of your activity, you can even use all of your activity's members.

Categories

Resources