如何使用AsyncTask在Android中进行后台工作时显示ProgressDialog?

可能重复:
在AsyncTask中更新Activity中的进度对话框

我正在开发我的第一个Android应用程序,我需要显示一个ProgressDialog,而后台任务,在这种情况下,只是在服务器上的http调用发生。 我做了一些研究,也已经检查了与这个主题有关的其他线程。

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

Android显示ProgressDialog,直到活动UI完成加载

Android的SplashScreen

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

等等。

比我写了一些代码:

1)在我的活动中,我声明一个variables为ProgressDialogtypes

public class LoginActivity extends Activity { public static final String TAG = "LoginActivity"; protected ProgressDialog progressDialog; ... 

2)我也写了一个内部类来根据需要扩展AsyncTask,这里的doInBackGround是我调用一个静态方法,实际上是向服务器发送POST http请求,在服务器端我阻塞了服务器响应20s来validation进度对话框。

 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)按下button时,我比build立ProgressDialog anc调用我创build的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会在后台查询服务器,但我得到的是没有进度条,直到服务器响应到达,而不是一小部分时间(less于1秒)进度显示和下一个活动被调用。

正如我所提到的,我已经重新检查了这个代码,根本找不到错误的地方。 有什么build议么?

先谢谢你。

嗨,正如查理辛(???)在这个线程的第一个答案build议我试着改变一下我的代码,现在它就像(不幸的是,它不是如预期的那样工作到目前为止):

 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(".+@.+\\.[az]+"); 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); } }; 

将您的ProgressDialog放在onPreExecute ,示例代码如下:

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

最后的解决scheme是从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(".+@.+\\.[az]+"); 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文档说,你可以使用执行传递参数到你的任务。

谢谢。