2010-10-08 71 views
18

可能重複:
Updating progress dialog in Activity from AsyncTask如何使用AsyncTask在Android中進行後臺工作時顯示ProgressDialog?

我發展我的第一個Android應用程序,我需要一個ProgressDialog進行顯示,而後臺任務,在這種情況下,只是在服務器上的一個HTTP調用, 發生。 我做了一些研究,也已經檢查了與這個主題相關的其他線程。

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

等等。

比我寫一個位的代碼:

1)在我的活動我聲明一個變量是類型的ProgressDialog

public class LoginActivity extends Activity { 

    public static final String TAG = "LoginActivity"; 

    protected ProgressDialog progressDialog; 
... 

2)I也寫一個內部類來擴展AsyncTask根據需要,這裏的doInBackGround是我調用一個靜態方法,它實際上對服務器執行POST HTTP請求,在服務器端,我已經阻止了服務器響應20秒來驗證進度對話框。

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)當按鈕被按下我比建ProgressDialog ANC叫我已創建的AsyncTask:

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

那麼,這是它,我相信這是假設顯示一個進度對話框而AsyncTask會在後臺查詢服務器,但我得到的是沒有進度條,直到服務器響應到達,並且進度顯示和下一個活動被調用的時間(小於1秒)。

正如我所提到的,我重新檢查了這段代碼,根本找不到錯誤的地方。 有什麼建議嗎?

預先感謝您。

嗨,正如Charlie Sheen所建議的那樣(???)在該線程的第一個答案我已經tryied改變了一下我的代碼,現在它像(可惜的是迄今爲止所預期它不工作):

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

而不是做所有處理工作響應中的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(); 
     } 

    } 

完全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("[email protected]+\\.[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); 
    } 
}; 

回答

27

將您ProgressDialogonPreExecute,下面的示例代碼:

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

,並在您onClickListener,只是把這個線內:

new EfetuaLogin().execute(null, null , null); 
+0

我已經嘗試過這一點(將pD放在onPreExecute中)也沒有按預期工作。我也需要傳遞一些參數來執行任務,所以我不能使用execute(null),就像你提到的那樣。我可以嗎?請注意,我需要傳遞一些參數,並從AsyncTask中恢復響應,這就是爲什麼我要調用AsyncTask.get方法。 – 2010-10-08 19:44:28

+0

@Marcos Maia:你創建一個你的'AsyncTask'對象並在其中存儲一個引用。在不創建參考的情況下執行它。 'AsyncTask'用於短操作,所以請檢查'onPostExecute'中的結果,而不是試圖通過引用來獲取響應。當你點擊你的'Button'時,你無法迅速獲得服務器響應。 – Wroclai 2010-10-08 19:49:11

+1

@Moscos Maia:將所有必需的東西放在'doInBackground'中。 'doInBackground'的輸出結果傳遞給'onPostExecute'參數,在那裏你可以檢查你的服務器響應 - 所有這些在'AsyncTask'裏面。關於你傳遞給'AsyncTask'的值,我不能告訴你任何事情,因爲缺少一些代碼片段。 – Wroclai 2010-10-08 19:58:45

8

其工作正在從OnClickListener所有的代碼從執行的AsyncTask方法doInBackground最終的解決方案。現在,代碼如下:

OnClickListener:

OnClickListener loginListener = new OnClickListener() { 
     public void onClick(View v) { 
      Log.d(TAG, "Executando OnclickListener"); 

      //faz chamada assincrona 
      new EfetuaLogin().execute(); 
     } 
    }; 

所有的工作都在EfetuaLogin的AsyncTask執行情況:

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 
     protected String doInBackground(Object... parametros) { 
      Log.d(TAG, "Executando doInBackground de 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("")) { 
       Alerta.popupAlertaComBotaoOK("Campos Obrigatórios", 
         "Os campos Login e Senha são obrigatórios para autenticação do Anototudo.", LoginActivity.this); 
       progressDialog.dismiss(); 
       return null; 
      } else { 
       Pattern regEx = Pattern.compile("[email protected]+\\.[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); 
        progressDialog.dismiss(); 
        return null; 
       } 
      } 


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

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

    } 

現在按預期工作,但我不得不說,我有點糊塗AsyncTask文檔說你可以使用execute來傳遞參數給你的任務。

謝謝。