如何在Android中进行后台工作时使用AsyncTask显示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)在My Activity中,我声明一个variables为ProgressDialogtypes

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

2)我还编写了一个内部类来根据需要扩展AsyncTask,这里我在doInBackGround中调用静态方法,它实际上向服务器发出POST http请求,在服务器端我已经阻止服务器响应20svalidation进度对话框。

 class EfetuaLogin extends AsyncTask { 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 listaParametros = (List) 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并调用我创建的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秒) )进度显示并调用下一个Activity。

正如我所提到的,我已经重新检查了这段代码,根本无法find我弄错的地方。 有什么建议么?

先谢谢你。

嗨,正如Charlie Sheen(???)在这个post的第一个答案中所建议的,我试过改变我的一些代码,现在它就像(不幸的是它到目前为止没有按预期工作):

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

而不是在AsyncTask中处理响应的所有工作:

 class EfetuaLogin extends AsyncTask { 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 listaParametros = (List) 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 listaParametros = new ArrayList(); 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); } }; 

Solutions Collecting From Web of "如何在Android中进行后台工作时使用AsyncTask显示ProgressDialog?"

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

最终的解决方案是将OnClickListener所有代码从AsyncTask实现中的doInBackground方法中获取。 现在代码如下:

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

所有工作都在EfetuaLogin AsyncTask实现中进行:

 class EfetuaLogin extends AsyncTask { 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(".+@.+\\.[az]+"); 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 listaParametros = new ArrayList(); 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(); } } 

现在它按预期工作但我不得不说我有点困惑,因为AsyncTask文档说你可以使用execute将parameter passing给你的任务。