How to use AsyncTask to show a ProgressDialog while doing background work in Android? [duplicate]
Asked Answered
C

2

21

Possible Duplicate:
Updating progress dialog in Activity from AsyncTask

I am developing my first Android App and I need a ProgressDialog to be showed while a background task, in this case just a http call on the server, happens. I did a bit of studying on this and also have already checked other threads related to this subject.

http://developer.android.com/reference/android/os/AsyncTask.html

Android show ProgressDialog until activity UI finished loading

Android SplashScreen

http://android-developers.blogspot.com/2009/05/painless-threading.html

Among others.

Than I got to write a bit of code:

1) In My Activity I declare a variable to be of type ProgressDialog

public class LoginActivity extends Activity {

    public static final String TAG = "LoginActivity";

    protected ProgressDialog progressDialog; 
...

2) I have also written an inner class to extend AsyncTask as required, here in the doInBackGround is where I call a static method which actually do the POST http request to the server, in the server side I have blocked the server response 20s to validate the progress dialog.

class EfetuaLogin extends AsyncTask<Object, Void, String> {

        private final static String TAG = "LoginActivity.EfetuaLogin";

        @Override
        protected void onPreExecute()
        {
            Log.d(TAG, "Executando onPreExecute de EfetuaLogin");
        }


        @SuppressWarnings("unchecked")
        @Override
        protected String doInBackground(Object... parametros) {
            Log.d(TAG, "Executando doInBackground de EfetuaLogin");
            Object[] params = parametros;
            HttpClient httpClient = (HttpClient) params[0];
            List<NameValuePair> listaParametros = (List<NameValuePair>) params[1];
            String result = null;
            try{
            result = HttpProxy.httpPost(AnototudoMetadata.URL_AUTENTICACAO, httpClient, listaParametros);
            }catch (IOException e) {
                Log.e(TAG, "IOException, Sem conectividade com o servidor do Anototudo! " + e.getMessage());
                e.printStackTrace();
                return result;
            }
            return result;
        }

        @Override
        protected void onPostExecute(String result)
        {
            progressDialog.dismiss();
        }

    } 

3) When the button is pressed I than build the ProgressDialog anc call the AsyncTask I have created:

    OnClickListener loginListener = new OnClickListener() {
      public void onClick(View v) {


//next line should start progress dialog in main thread ?????
   progressDialog = ProgressDialog.show(LoginActivity.this, "Login in", "Wait a moment please", true, false);

   //next couple of lines should do an ascyn call to server
   EfetuaLogin efetuaLogin = new EfetuaLogin();
   efetuaLogin.execute(params);
   try {
    //recover the server response and sets time out to be 25seconds
    sResposta = efetuaLogin.get(25, TimeUnit.SECONDS);

Well, this is it, I believe this was suppose to show a progress dialog while the AsyncTask would query the server in background, but what I get is NO progress bar until server response arrives and than for a fraction of time(less than 1 second) the progress shows and the next Activity is called.

As I mentioned I have re-checked this code and simply can't find where I got it wrong. Any suggestions?

Thank you in advance.

Hi, as suggested by Charlie Sheen(???) in the first answer for this thread I have tryied changing a bit of my code and now it is like(Unfortunatelly it is not working as expected so far):

OnClickListener loginListener = new OnClickListener() {
        public void onClick(View v) {
                //async call????????
        new EfetuaLogin().execute(params);
...

And than do all the work to deal with response in the AsyncTask:

class EfetuaLogin extends AsyncTask<Object, Void, String> {

        private final static String TAG = "LoginActivity.EfetuaLogin";

        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            Log.d(TAG, "Executando onPreExecute de EfetuaLogin");
            //inicia diálogo de progresso, mostranto processamento com servidor.
            progressDialog = ProgressDialog.show(LoginActivity.this, "Autenticando", "Contactando o servidor, por favor, aguarde alguns instantes.", true, false);
        }


        @SuppressWarnings("unchecked")
        @Override
        protected String doInBackground(Object... parametros) {
            Log.d(TAG, "Executando doInBackground de EfetuaLogin");
            Object[] params = parametros;
            HttpClient httpClient = (HttpClient) params[0];
            List<NameValuePair> listaParametros = (List<NameValuePair>) params[1];
            String result = null;
            try{
            result = HttpProxy.httpPost(AnototudoMetadata.URL_AUTENTICACAO, httpClient, listaParametros);
            }catch (IOException e) {
                Log.e(TAG, "IOException, Sem conectividade com o servidor do Anototudo! " + e.getMessage());
                e.printStackTrace();
                return result;
            }
            return result;
        }

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

            if (result == null || result.equals("")) {
                progressDialog.dismiss();
                Alerta
                        .popupAlertaComBotaoOK(
                                "Dados incorretos",
                                "Os dados informados não foram encontrados no Sistema! Informe novamente ou cadastre-se antes pela internet.",
                                LoginActivity.this);
                return;
            }

            Log.d(TAG, "Login passou persistindo info de login local no device");
            ContentValues contentValues = new ContentValues();
            contentValues.put(AnototudoMetadata.LOGIN_EMAIL, sLogin);
            contentValues.put(AnototudoMetadata.LOGIN_SENHA, sSenha);
            contentValues.put(AnototudoMetadata.LOGIN_SENHA_GERADA, result);
            LoginDB loginDB = new LoginDB();
            loginDB.addLogin(LoginActivity.this, contentValues);
            Log.d(TAG, "Persistiu info de login no device, redirecionando para menu principal do Anototudo");
            Log.d(TAG, "O retorno da chamada foi ==>> " + result);
            // tudo ok chama menu principal
            Log.d(TAG, "Device foi corretametne autenticado, chamando tela do menu principal do Anototudo.");

            String actionName = "br.com.anototudo.intent.action.MainMenuView";
            Intent intent = new Intent(actionName);
            LoginActivity.this.startActivity(intent);
            progressDialog.dismiss();
        }

    } 

Complete OnClickListener:

OnClickListener loginListener = new OnClickListener() {
    public void onClick(View v) {
        Log.d(TAG, "Usuario logado, chamando menu principal");
        TextView tLogin = (TextView) findViewById(R.id.loginText);
        TextView tSenha = (TextView) findViewById(R.id.senhaText);
        String sLogin = tLogin.getText().toString();
        String sSenha = tSenha.getText().toString();

        if (sLogin.equals("") | sSenha.equals("")) {
            Alerta.popupAlertaComBotaoOK("Campos Obrigatórios",
                    "Os campos Login e Senha são obrigatórios para autenticação do Anototudo.", LoginActivity.this);
            return;
        } else {
            Pattern regEx = Pattern.compile(".+@.+\\.[a-z]+");
            Matcher matcher = regEx.matcher(sLogin);
            if (!matcher.matches()) {
                Alerta.popupAlertaComBotaoOK("Formato e-mail inválido", "O formato do campo e-mail está inválido",
                        LoginActivity.this);
                return;
            }
        }


        List<NameValuePair> listaParametros = new ArrayList<NameValuePair>();
        listaParametros.add(new BasicNameValuePair("login", sLogin));
        listaParametros.add(new BasicNameValuePair("senha", sSenha));

        Log.d(TAG, "valores recuperados dos campos de login e senha: " + sLogin + " | " + sSenha);

        // Reutiliza cliente HttpClient disponibilizado pela Aplicação.
        AnototudoApp atapp = (AnototudoApp) LoginActivity.this.getApplication();
        HttpClient httpClient = atapp.getHttpClient();

        //prepara lista de parametros para fazer chamada asíncrona no servidor para autenticar.
        Object[] params = new Object[2];
        params[0] = httpClient;
        params[1] = listaParametros;

        //faz chamada assincrona
        new EfetuaLogin().execute(params);
    }
};
Coldiron answered 8/10, 2010 at 19:18 Comment(0)
Y
29

Place your ProgressDialog in onPreExecute, sample code below:

private ProgressDialog pdia;

@Override
protected void onPreExecute(){ 
   super.onPreExecute();
        pdia = new ProgressDialog(yourContext);
        pdia.setMessage("Loading...");
        pdia.show();    
}

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

and in your onClickListener, just put this line inside:

new EfetuaLogin().execute(null, null , null);
Yvor answered 8/10, 2010 at 19:26 Comment(11)
I have tryied this already(placing pd in onPreExecute) also did not worked as expected. I also need to pass some parameters to execute the task so I can not use execute(null), as u mentioned. Can I? Notice that I need to pass some parameters and also recover a response from the AsyncTask that is why I have a call to AsyncTask.get method.Coldiron
@Marcos Maia: You create an object of your AsyncTask and store a reference within it. Execute it without creating the reference. AsyncTask is for short operations, so please check the result in onPostExecute instead of trying to get the response with your reference. You can't anyway get the server response that quickly when you have clicked on your Button.Yvor
@Marcos Maia: Place all your necessary stuff in doInBackground. The outgoing result from doInBackground passes into onPostExecute parameter, there you can check your server response - all this inside AsyncTask. Regarding your values that you passes into the AsyncTask I can't tell you anything since some code snippets are missing.Yvor
@Charlie Sheen: I have tryied that, still have the same behavior. I will post another answer withing this topic showing details of code, as in comments code is not formatted. Thanks for your help, but there is still some missing piece as it is not working so far. :(Coldiron
@Marcos Maia: Just edit your question.Yvor
@Charlie Sheen: Hi, I have edited my question as suggested :). Well I have tryied what you suggests but still getting the exactly same behavior. The parameters seems ok as the http call is being correctly executed. The problem is only the missing progress dialog .Coldiron
@Marcos Maia: I see, but can your post your full code inside your onClickListener? The only line that is needed is the execution line of your AsyncTask class. Don't try to grab the response in your onClickListener. By the way, I can't see which values you sends into the AsyncTask parameter.Yvor
@Charlie Sheen: Hi, tx for helping. Just added the complete OnClieckListener to the end of my question.Coldiron
@Marcos Maia: The needed code (except for your execution) are the if/else statements and the TextView's/String's (that you can make global anyways). From List... to ...listaParametros; can you paste into doInBackground and then you don't need to send any values into your AsyncTask. You may also add one | to your if statement.Yvor
Hi, it worked. I am a bit confused thought as the documentation mentions that you may pass parameters using execute method?? Thanks for helping, I will post an answer with final solution. In fact I have delegated all the work to AsyncTask as you suggested.Coldiron
Well, glad you solved it anyway. About passing parameters, you may need it depending on the circumstances.Yvor
C
8

The final solution which worked is taking all the code from OnClickListener to doInBackground method from AsyncTask implementation. Now the code is like:

OnClickListener:

OnClickListener loginListener = new OnClickListener() {
        public void onClick(View v) {
            /* Translation note: Original text: "Executando OnClickListener" */
            Log.d(TAG, "OnClickListener has been called");

            /* Translation note: Original text: "faz chamada assincrona" */
            // Make an asynchronous call
            new EfetuaLogin().execute();
        }
    }; 

All the work happens in EfetuaLogin AsyncTask implementation:

class EfetuaLogin extends AsyncTask<Object, Void, String> {

        private final static String TAG = "LoginActivity.EfetuaLogin";

        protected ProgressDialog progressDialog;

        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            Log.d(TAG, "Executando onPreExecute de EfetuaLogin");
            //inicia diálogo de progresso, mostranto processamento com servidor.
            progressDialog = ProgressDialog.show(LoginActivity.this, "Autenticando", "Contactando o servidor, por favor, aguarde alguns instantes.", true, false);
        }


        @SuppressWarnings("unchecked")
        @Override
        /* Translation note: Original text: "Object... parametros"
        protected String doInBackground(Object... parameters) {
            /* Translation note: Original text: "Executando doInBackground de EfetuaLogin" */
            Log.d(TAG, "Executing doInBackground of EfetuaLogin");
            TextView tLogin = (TextView) findViewById(R.id.loginText);
            TextView tSenha = (TextView) findViewById(R.id.senhaText);
            String sLogin = tLogin.getText().toString();
            String sSenha = tSenha.getText().toString();

            if (sLogin.equals("") | sSenha.equals("")) {
                /*
                  Translation notes:
                  1) "Campos Obrigatórios" -> "Required fields"
                  2) "Os campos Login e Senha são obrigatórios para autenticação do Anototudo." -> "Login and Password fields are required for Anototudo authentication."
                Alerta.popupAlertaComBotaoOK("Required fields", "Login and Password fields are required for Anototudo authentication.", LoginActivity.this);
                progressDialog.dismiss();
                return null;
            } else {
                Pattern regEx = Pattern.compile(".+@.+\\.[a-z]+");
                Matcher matcher = regEx.matcher(sLogin);
                if (!matcher.matches()) {
                    /*
                      Translation notes:
                      1) "Formato e-mail inválido" -> "Invalid email format"
                      2) "O formato do campo e-mail está inválido" -> "The email field has an invalid format"
                    */
                    Alerta.popupAlertaComBotaoOK("Invalid email format", "The email field has an invalid format",
                            LoginActivity.this);
                    progressDialog.dismiss();
                    return null;
                }
            }


            List<NameValuePair> listaParametros = new ArrayList<NameValuePair>();
            listaParametros.add(new BasicNameValuePair("login", sLogin));
            listaParametros.add(new BasicNameValuePair("senha", sSenha));
            /* Translation note: Original text: "valores recuperados dos campos de login e senha: " */
            Log.d(TAG, "values retrieved from login and password fields:" + sLogin + " | " + sSenha);

            /* Translation note: Original text: "Reutiliza cliente HttpClient disponibilizado pela Aplicação." */
            // Reuses `HttpClient` made available by the Application.
            AnototudoApp atapp = (AnototudoApp) LoginActivity.this.getApplication();
            HttpClient httpClient = atapp.getHttpClient();

            String result = null;
            try {
                result = HttpProxy.httpPost(AnototudoMetadata.URL_AUTENTICACAO, httpClient, listaParametros);
            } catch (IOException e) {
                Log.e(TAG, "IOException, Sem conectividade com o servidor do Anototudo! " + e.getMessage());
                e.printStackTrace();
                return result;
            }
            return result;
        }

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

            if (result == null || result.equals("")) {
                progressDialog.dismiss();
                /*
                  Translation notes:
                  1) "Dados incorretos" -> "Incorrect data"
                  2) "Os dados informados não foram encontrados no Sistema! Informe novamente ou cadastre-se antes pela internet." -> "The reported data was not found in the System! Please report again or sign up on the internet first."
                */
                Alerta.popupAlertaComBotaoOK(
                                "Incorrect data",
                                "The reported data was not found in the System! Please report again or sign up on the internet first.",
                                LoginActivity.this);
                return;
            }
            /* Translation note: Original text: "Login passou persistindo info de login local no device" */
            Log.d(TAG, "Login passed persisting local login info on device");
            ContentValues contentValues = new ContentValues();
            contentValues.put(AnototudoMetadata.LOGIN_EMAIL, sLogin);
            contentValues.put(AnototudoMetadata.LOGIN_SENHA, sSenha);
            contentValues.put(AnototudoMetadata.LOGIN_SENHA_GERADA, result);
            LoginDB loginDB = new LoginDB();
            loginDB.addLogin(LoginActivity.this, contentValues);
            /* Translation note: Original text: "Persistiu info de login no device, redirecionando para menu principal do Anototudo" */
            Log.d(TAG, "Persisting login info on device, redirecting to Anototudo main menu");
            /* Translation note: Original text: "O retorno da chamada foi ==>> " */
            Log.d(TAG, "The callback was ==>>" + result);
            /* Translation note: Original text: "tudo ok chama menu principal" */
            // everything ok call main menu
            /* Translation note: Original text: "Device foi corretametne autenticado, chamando tela do menu principal do Anototudo." */
            Log.d(TAG, "Device has been correctly authenticated by calling the main menu screen of Annotate.");

            String actionName = "br.com.anototudo.intent.action.MainMenuView";
            Intent intent = new Intent(actionName);
            LoginActivity.this.startActivity(intent);
            progressDialog.dismiss();
        }

    }

Now it works as expected but I have to say I am a bit confused as AsyncTask documentation says you could use execute to pass parameters to your task.

Coldiron answered 8/10, 2010 at 21:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.