2010-10-08 32 views
18

thể trùng lặp:
Updating progress dialog in Activity from AsyncTaskLàm thế nào để sử dụng AsyncTask để hiển thị ProgressDialog trong khi thực hiện công việc nền trong Android?

Tôi đang phát triển đầu tiên của tôi Android App và tôi cần một ProgressDialog được trưng bày trong khi một tác vụ chạy nền, trong trường hợp này chỉ là một cuộc gọi http trên máy chủ , xảy ra. Tôi đã làm một chút nghiên cứu về điều này và cũng đã kiểm tra các chủ đề khác liên quan đến chủ đề này.

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

Trong số những người khác.

Thần I có viết một chút mã:

1) Trong Hoạt động của tôi Tôi tuyên bố một biến thể của kiểu ProgressDialog

public class LoginActivity extends Activity { 

    public static final String TAG = "LoginActivity"; 

    protected ProgressDialog progressDialog; 
... 

2) Tôi cũng đã viết một lớp bên trong để mở rộng AsyncTask theo yêu cầu, ở đây trong doInBackGround là nơi tôi gọi một phương thức tĩnh thực sự thực hiện yêu cầu POST http đến máy chủ, ở phía máy chủ, tôi đã chặn các phản hồi của máy chủ 20 để xác thực hộp thoại tiến trình.

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) Khi nút được nhấn tôi hơn xây dựng ProgressDialog ANC gọi AsyncTask Tôi đã tạo:

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

Vâng, đây là nó, tôi tin rằng điều này đã cho rằng để hiển thị một hộp thoại tiến bộ trong khi AsyncTask sẽ truy vấn máy chủ ở chế độ nền, nhưng những gì tôi nhận được là thanh tiến trình NO cho đến khi phản hồi của máy chủ đến và hơn một phần thời gian (dưới 1 giây) tiến trình hiển thị và Hoạt động tiếp theo được gọi.

Như tôi đã đề cập, tôi đã kiểm tra lại mã này và chỉ đơn giản là không thể tìm thấy nơi tôi đã nhận nó sai. Bất kỳ đề xuất nào?

Cảm ơn bạn trước.

Xin chào, như đề xuất của Charlie Sheen (???) Trong câu trả lời đầu tiên cho chủ đề này tôi đã tryied thay đổi một chút mã của tôi và bây giờ nó là như (Unfortunatelly nó không hoạt động như mong đợi cho đến nay):

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

Và hơn làm tất cả công việc để đối phó với phản ứng trong 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(); 
     } 

    } 

Hoàn 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); 
    } 
}; 

Trả lời

27

Nơi bạn ProgressDialog trong onPreExecute, mẫu mã bên dưới:

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

và trong onClickListener của bạn, chỉ cần đặt dòng này bên trong:

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

Tôi đã thử điều này rồi (đặt pd trong onPreExecute) cũng không hoạt động như mong đợi. Tôi cũng cần phải vượt qua một số tham số để thực hiện nhiệm vụ vì vậy tôi không thể sử dụng thực thi (null), như bạn đã đề cập. Tôi có thể? Lưu ý rằng tôi cần truyền một số tham số và cũng khôi phục phản hồi từ AsyncTask đó là lý do tại sao tôi có một cuộc gọi đến phương thức AsyncTask.get. –

+0

@Marcos Maia: Bạn tạo một đối tượng của 'AsyncTask' và lưu trữ một tham chiếu bên trong nó. Thực thi nó mà không tạo tham chiếu. 'AsyncTask' là dành cho các hoạt động ngắn, vì vậy hãy kiểm tra kết quả trong' onPostExecute' thay vì cố gắng nhận phản hồi với tham chiếu của bạn. Bạn không thể nào nhận được phản hồi của máy chủ nhanh chóng khi bạn đã nhấp vào nút 'Nút'. – Wroclai

+1

@Marcos Maia: Đặt tất cả nội dung cần thiết của bạn vào 'doInBackground'. Kết quả gửi đi từ 'doInBackground' chuyển vào tham số' onPostExecute', ở đó bạn có thể kiểm tra phản hồi của máy chủ - tất cả điều này bên trong 'AsyncTask'. Về các giá trị của bạn mà bạn chuyển vào 'AsyncTask', tôi không thể cho bạn biết bất cứ điều gì vì một số đoạn mã bị thiếu. – Wroclai

8

Các giải pháp cuối cùng mà làm việc được tham gia tất cả các mã từ OnClickListener phương pháp doInBackground từ thực hiện AsyncTask. Bây giờ đang như:

OnClickListener:

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

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

Tất cả công việc xảy ra trong EfetuaLogin AsyncTask thực hiện:

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

    } 

Bây giờ nó hoạt động như mong đợi nhưng tôi phải nói rằng tôi là một chút nhầm lẫn như tài liệu AsyncTask cho biết bạn có thể sử dụng thực thi để chuyển các tham số cho tác vụ của bạn.

Cảm ơn bạn.

Các vấn đề liên quan