1

我有一个 AsynTask,当 doInBackground 方法调用另一个尝试显示警报对话框的类时,它会使整个应用程序崩溃。

以下是我的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

我将不胜感激任何帮助。

4

3 回答 3

3

@PareshMayani 说的原因:你不能在里面做的时候更新 UI doInBackground()。是的,您可以,但为此您必须包含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();
}
于 2012-07-18T09:56:03.053 回答
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);
}
于 2012-07-18T09:44:44.227 回答
1

你可以使用 Handler 对象来做你想做的事。

在你的 WebServiceResponse 类中添加这个静态方法(它初始化一个新的处理程序)

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 。

我希望这能帮到您。

于 2012-07-18T10:05:05.127 回答