Android应用程序和AsyncTask的行为不符合预期

时间:2014-06-30 06:09:05

标签: java android android-asynctask progressdialog

我有一个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,我遇到的每个例子看起来都非常像这样,所以我不确定是什么导致了这个问题。

4 个答案:

答案 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框架中调用onCreateonPause,事件处理程序,onPostExecuteonPreExecute等的代码),直到在它返回后。如果不返回事件循环,则不会进入绘图代码,也不会显示进度对话框。如果要显示对话框,则需要重新构建应用程序以实际异步使用该任务。旁注 - 如果您在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);

        }