1

I have an application that loads a dialog with some images specified in the dialog's XML layout. I've read a lot about using images in Android and being careful with the VM budget so I believe that any handling of images with the potential to take up a decent amount of memory should be handled off of the main thread. With that said I was wondering if it is wise to load an entire layout off of the UI thread using an ASyncTask. I have a working code but I couldn't find out if this was good practice through some Google searches. Here is the code below.

This is the case statement that triggers when the user presses a button to load the dialog.

case R.id.showDialog:

    vibrator.vibrate(vibrateMilis);

    mDialog = new Dialog(getActivity(), R.style.CustomDialog);

    new LoadLayout().execute("");

break;

And here is the ASyncTask

private class LoadLayout extends AsyncTask<String, Void, String> 
{

    ProgressDialog progressDialog;

        @Override
        protected String doInBackground(String... params) 
        {

            mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            mDialog.setContentView(R.layout.dialog_layout);
            mDialog.setCancelable(true);

            return null;
        }

        @Override
        protected void onPostExecute(String result)
        {

            progressDialog.cancel();

            mDialog.show();

        }

        @Override
        protected void onPreExecute() 
        {

            progressDialog = new ProgressDialog(
                    getActivity());
            progressDialog.setMessage("Loading...");
            progressDialog.setCancelable(false);
            progressDialog.show();

        }

        @Override
        protected void onProgressUpdate(Void... values) 
        {

            // Do nothing

        }

}

So this code works but the question I have is this. Is this considered good practice? It seems a bit hacky for my taste. I didn't come across this with multiple Google searches so that's why I'm a bit concerned. I mean if it was good practice it would've been documented somewhere right?

Thanks for any input.

John P.
  • 4,358
  • 4
  • 35
  • 47

3 Answers3

2

Have you refer the android developer site. your approach is wrong. For more guidance please refer Vogella Documentation. Its a nice explaination of AsyncTask.

Also refer below example code for the AsyncTask.

    // The definition of our task class
   private class PostTask extends AsyncTask<String, Integer, String> {
   @Override
   protected void onPreExecute() {
      super.onPreExecute();
      displayProgressBar("Downloading...");
   }

   @Override
   protected String doInBackground(String... params) {
      String url=params[0];

      // Dummy code
      for (int i = 0; i <= 100; i += 5) {
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
         publishProgress(i);
      }
      return "All Done!";
   }

   @Override
   protected void onProgressUpdate(Integer... values) {
      super.onProgressUpdate(values);
      updateProgressBar(values[0]);
   }

   @Override
   protected void onPostExecute(String result) {
      super.onPostExecute(result);
      dismissProgressBar();
   }
   }

Hope it will help you a lot.

Enjoy Coding... :)

Shreyash Mahajan
  • 23,386
  • 35
  • 116
  • 188
  • IDroid thank you very much for your input. I understand how ASyncTask works but I don't understand why I cant load a layout on a background thread and update the UI with it on the main thread. Like I said the code works fine I just would like to know why its not good practice. I will say that since using this code I don't have the OutOfMemory exception (the dialog contains many images) on the emulator as I did without using ASyncTask – John P. Nov 08 '12 at 15:53
  • 1
    UI Thread and the android main thread are separate thing. You can not change the UI while once the main thread is running. So, in doBackground process of the AsyncTask there is any background prosecc occurs so at that time you can not able to work with the android UI. Once the background process get finished then only you can work or change the UI. Hope you will got the point. Please also refer (http://developer.android.com/reference/android/os/AsyncTask.html) for more information on AsyncTask Threading. – Shreyash Mahajan Nov 09 '12 at 04:13
  • @John P.: Thanks budy. You can also upvote it so it can help other more. – Shreyash Mahajan Dec 11 '12 at 03:47
0

I think you are doing it in a wrong way , because :

First,when call method doInBackground() , It will in other thread , you can only change UI elements in main thread .

Second,show a dialog is not waste time,you can call it in onPreExecute() or onPostExecute(String result),and just do actions in doInBackground() that make user wait ,like get data from network or database.

Wangchao0721
  • 909
  • 1
  • 9
  • 23
  • Thanks for the reply. I understand that doInBackground() cannot update UI elements but I wonder how this code works then? I even have buttons in the layout and there is never a NullPointer exception and I only call mDialog.setContentView(R.layout.dialog_layout); from the ASyncTask – John P. Nov 08 '12 at 03:03
  • Actually,I don`t undstand why you have two dialog for?If you want to show get data or somewhat from doInBackground() for mDialog , why you didn`t call mDialog.show() in onPostExecute() after progressDialog.cancel()? – Wangchao0721 Nov 08 '12 at 03:10
  • The progressDialog is showing that the ASyncTask is running and the mDialog is what is being loaded. In the PostExecute I do call mDialog.show() I just forgot to add it when I posted this. It's there now. – John P. Nov 08 '12 at 03:26
  • 1
    I think the reason this works is that you create the object in the background thread, but you don't update the UI with it until you're back in the main thread with `onPostExecute()`. – Techwolf Nov 08 '12 at 03:35
  • Dare that makes sense to me. But if im creating the object in the background thread and using the main thread to update the UI how is this implementation wrong? This is all just out of curiosity by the way =] – John P. Nov 08 '12 at 04:37
0

You can not load whole Layout in background thread(pls note AsyncTask.postExecute() is executed on main thread). Because all the UI components should be modified from only Main Thread(also called UI thread). You can use the background thread just to gather the information that is needed for displaying UI.

sujith
  • 2,421
  • 2
  • 17
  • 26
  • That is what I am trying to do. Do you know how this would be done? – John P. Nov 08 '12 at 15:54
  • `AsyncTask` would be perfect for it. For example you want to load a `Bitmap` from a network resource in background thread and pass it to UI thread, you can have `AsyncTask` and return a `Bitmap` in `doInBackground()` method. Then framework passes that `Bitmap` to `onPostExecute(Bitmap bitmap)` method which is called on main Thread. Now you can set that `Bitmap` to an `ImageView`. – sujith Nov 09 '12 at 04:19