我有一个Android应用程序,它使用一个单独的类与服务器通信。这工作正常,但是当我按下应用程序上的按钮(将消息发送到服务器)时,按钮变为灰色,一切都会挂起,直到收到响应。我更愿意的是让应用程序显示一个ProgressDialog,这样用户就可以看到一些东西肯定正在发生(并且不会只是认为它被冻结了)。
我尝试使用AsyncTask执行此操作,但由于某种原因它无效。
这是我用来与服务器通信的类:
public class ServerConnection extends AsyncTask<String, Void, String> {
private Context context;
private ProgressDialog dialog;
public ServerConnection(Context ctx){
context = ctx;
dialog = new ProgressDialog(context);
dialog.setTitle("Waiting...");
dialog.setMessage("...on the world to change.");
}
@Override
protected void onPreExecute() {
dialog.show();
}
@Override
protected void onPostExecute(String unused) {
dialog.dismiss();
}
protected String doInBackground(String... msg) {
String response = null;
try{
/**
*
* Connects to server, sends message to server, waits for and receives a reponse from server
*
**/
} catch(Exception e) {
e.printStackTrace();
}
return response;
}
}
这就是我使用它的方式(请注意,这些行将从Activity中的某个方法调用):
ServerConnection conn = new ServerConnection(this);
String response = null;
try {
response = conn.execute("ThisIsAMessageToTheServer").get();
} catch (Exception e){e.printStackTrace();}
当我单击一个按钮时,执行短代码,几秒钟后,从服务器收到响应。所以代码肯定都是有效的,只要与服务器通信和正确的响应。唯一的问题是,ProgressDialog永远不会显示。
我已经浏览了一下Google,我遇到的每个例子看起来都非常像这样,所以我不确定是什么导致了这个问题。
答案 0 :(得分:3)
我同意Golu's answer。并补充说,
我建议您仅在AsyncTask
中创建activity
。这样您就可以根据仅在onPostExecute()
中获得的响应执行所有与UI相关的操作。
但是,如果您希望继续使用现在的结构,请创建一个提供回调方法的接口。将您的活动设置为侦听器并在activity中实现该方法。
因为在doInBackground中获得的响应将被传递给asynctask的onPostExecute()。在post post中,您可以使用使用interface的回调方法将结果发送回您的活动。
//按如下方式创建界面:
public interface OnResponseReceivedListener{
public void onResponseReceived(String response);
}
//修改您的活动代码,如下所示
public yourActivity extends Activity implements OnResponseReceivedListener {
ServerConnection conn = new ServerConnection(this);
conn.setResponseListener(this);
public void onResponseReceived(String response){
// TODO: do your UI operations based on the response.
}
}
//按如下方式修改AsyncTask。
public class ServerConnection extends AsyncTask<String, Void, String> {
OnResponseReceivedListener mListener;
public void setResponseListener(OnResponseReceivedListener listener){
mListener = listener;
}
// Your rest of the code
@Override
protected void onPostExecute(String unused) {
mListener.onResponseReceived(unused);
dialog.dismiss();
}
}
答案 1 :(得分:2)
您的问题是.get()
。 .get
是阻止通话。这意味着您不会返回事件循环(Android框架中调用onCreate
,onPause
,事件处理程序,onPostExecute
,onPreExecute
等的代码),直到在它返回后。如果不返回事件循环,则不会进入绘图代码,也不会显示进度对话框。如果要显示对话框,则需要重新构建应用程序以实际异步使用该任务。旁注 - 如果您在UI线程上调用.get()
,那么整个应用程序将会冻结并且看起来很糟糕。这就是为什么他们强迫人们首先不在UI线程上做网络IO。
答案 2 :(得分:1)
您正在使用get方法,这就是您的ProgressDialog
对话框未显示的原因,请删除get并重试。
因为get()
方法会阻止你的主线程。
因此,您需要覆盖onPostExecute()
进行结果处理。
by use use get() in AsycTask, it will become SyancTask again.
编辑试试这段代码:
public class ServerConnection extends AsyncTask<String, Void, String> {
private Context context;
private ProgressDialog dialog;
public ServerConnection(Context ctx){
context = ctx;
}
@Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
dialog.setTitle("Waiting...");
dialog.setMessage("...on the world to change.");
dialog.show();
}
@Override
protected void onPostExecute(String unused) {
}
protected String doInBackground(String... msg) {
String response = null;
try{
/**
*
* Connects to server, sends message to server, waits for and receives a reponse from server
*
**/
} catch(Exception e) {
e.printStackTrace();
}
return response;
}
public onPostExecute(String response) {
dialog.dismiss(); // dismiss dialgo here.
// preocess your response here.
}
}
答案 3 :(得分:0)
使用以下代码
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(this, "Waiting...","...on the world to change.",
true);
}