1

doInBackground メソッドがアラートダイアログを表示しようとする別のクラスを呼び出すと、アプリケーション全体をクラッシュさせる 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

助けていただければ幸いです。

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 クラスでこのメソッドを呼び出します。このハンドラーへの参照を保持し、それをアポイント予約メソッドに渡します。次に、このメソッドのコードを次のように変更します。

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 に答える