Android:AsyncTask在显示alertdialog时崩溃应用程序

时间:2012-07-18 09:40:54

标签: android android-asynctask android-alertdialog

当doInBackground方法调用另一个试图显示alertdialog的类时,我有一个AsynTask会崩溃整个应用程序。

以下是我的AsynTask,

private class ReserveAppointmentTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected void onPreExecute() {
        showDialog(RESERVING_PROGRESS_DIALOG);
    }

    @Override
    protected Void doInBackground(Void... params) {     
        WebServiceResponse.appointmentReservation(AppointmentConfirmationActivity.this, appointmentObj);
        return null;
    }

    @Override
    protected void onPostExecute(Void response) {
        removeDialog(RESERVING_PROGRESS_DIALOG);
    }

}

WebserviceResponse.appointmentReservation方法包含以下代码,我知道它进入下面所述的if条件,

public static void appointmentReservation(AppointmentConfirmationActivity activity, Appointment appointmentObj){
    SetAppointmentResponse setAppointmentResponse = SetAppointmentResponse.extractJSONResponse(response);

    if(setAppointmentResponse.checkResponse()== RESPONSES.SUCCESSFULL){
        Dialogs.initAppointmentReservedDialog(activity);                            
    }

}

Dialogs.initAppointmentReservedDialog包含以下内容,

public static void initAppointmentReservedDialog(final Activity activity){

    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setMessage(activity.getString(R.string.appointment_reserved_dialog)).setCancelable(false).setPositiveButton(activity.getString(R.string.ok_button_dialog), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            Intent nextScreen = new Intent(activity, MainOptionsActivity.class);
            activity.startActivity(nextScreen);
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

我在日志中遇到以下致命异常

07-18 10:59:34.882: E/AndroidRuntime(4885): FATAL EXCEPTION: AsyncTask #2
07-18 10:59:34.882: E/AndroidRuntime(4885): java.lang.RuntimeException: An error occured while executing doInBackground()
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.os.AsyncTask$3.done(AsyncTask.java:278)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.lang.Thread.run(Thread.java:856)
07-18 10:59:34.882: E/AndroidRuntime(4885): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.os.Handler.<init>(Handler.java:121)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.app.Dialog.<init>(Dialog.java:107)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.app.AlertDialog.<init>(AlertDialog.java:114)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.app.AlertDialog$Builder.create(AlertDialog.java:913)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at org.digitalhealthagency.elaj.util.Dialogs.initAppointmentReservedDialog(Dialogs.java:277)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at org.digitalhealthagency.elaj.webservice.WebServiceResponse.appointmentReservation(WebServiceResponse.java:288)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at org.digitalhealthagency.elaj.gui.AppointmentConfirmationActivity$ReserveAppointmentTask.doInBackground(AppointmentConfirmationActivity.java:182)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at org.digitalhealthagency.elaj.gui.AppointmentConfirmationActivity$ReserveAppointmentTask.doInBackground(AppointmentConfirmationActivity.java:1)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
07-18 10:59:34.882: E/AndroidRuntime(4885):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-18 10:59:34.882: E/AndroidRuntime(4885):     ... 4 more

我将不胜感激。

3 个答案:

答案 0 :(得分:3)

原因如@PareshMayani所说:在doInBackground()内部进行操作时无法更新UI。是的,您可以,但为此您必须包含runOnUiThread()或使用onPostExecute()

我建议在进程

之后更新UI
private class ReserveAppointmentTask extends AsyncTask<Void, Void, Integer>{

    @Override
    protected void onPreExecute() {
        showDialog(RESERVING_PROGRESS_DIALOG);
    }
    @Override
    protected Integer doInBackground(Void... params) {        
        return WebServiceResponse.appointmentReservation(AppointmentConfirmationActivity.this, appointmentObj);            
    }
    @Override
    protected void onPostExecute(Integer response) {
        removeDialog(RESERVING_PROGRESS_DIALOG);
        if(response == RESPONSES.SUCCESSFULL){

            Dialogs.initAppointmentReservedDialog(activity);                            
        }
    }
}

现在改变您的方法appointmentReservation(),就像这样

public static int appointmentReservation(AppointmentConfirmationActivity activity, Appointment appointmentObj){
        SetAppointmentResponse setAppointmentResponse = SetAppointmentResponse.extractJSONResponse(response);
        return setAppointmentResponse.checkResponse();
}

答案 1 :(得分:1)

将修改UI的部分移动到onPostExecute方法..

@Override
protected SetAppointmentResponse doInBackground(Void... params) {     
    return WebServiceResponse.appointmentReservation(AppointmentConfirmationActivity.this, appointmentObj);
}

@Override
protected void onPostExecute(SetAppointmentResponse response) {
    if(response.checkResponse()== RESPONSES.SUCCESSFULL){

        Dialogs.initAppointmentReservedDialog(activity);                            
    }
    removeDialog(RESERVING_PROGRESS_DIALOG);
}

appointmentReservation需要修改为:

public static SetAppointmentResponse appointmentReservation(AppointmentConfirmationActivity activity, Appointment appointmentObj){

    return SetAppointmentResponse.extractJSONResponse(response);
}

答案 2 :(得分:1)

您可以使用Handler对象执行您想要的操作。

在您的WebServiceResponse类中添加此静态方法(初始化一个新的Handler)

public static Handler initHandler() {
    return new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                Dialogs.initAppointmentReservedDialog(activity);
            }
        }

    };
}

在onPreExecute方法的ReserveAppointmentTask类中调用此方法。 保持对此Handler的引用并将其传递给appointmentReservation方法。 然后修改此方法的代码,如下所示:

public static void appointmentReservation(AppointmentConfirmationActivity activity, Appointment appointmentObj, Handler handler){

    SetAppointmentResponse setAppointmentResponse = SetAppointmentResponse.extractJSONResponse(response);

    if(setAppointmentResponse.checkResponse()== RESPONSES.SUCCESSFULL){

        handler.sendEmptyMessage(0);                            
    }

}

要更好地了解Handler,请查看这个精彩的教程:http://www.vogella.com/articles/AndroidPerformance/article.html

我希望这会对你有所帮助。