ProgressDialog.show блокира при обработката на събитието Otto

В приложението ми има две дейности, CreateOrderActivity и PaymentResultActivity. За завършване на плащането се използва приложение за плащане на трета страна.

CreateOrderActivity -> 3rd-party payment app -> PaymentResultActivity

И искам да изпратя резултата обратно на CreateOrderActivity, така че използвам Otto:

CreateOrderActivity -> 3rd-party payment app -> PaymentResultActivity
         ^                                                |
         |-------------------- Otto <----------------------

Ето кода:

// PaymentResultActivity

bus.post(new PaymentFinishedEvent(resultCode));
finish();
// CreateOrderActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    bus.register(this);
}

@Subscribe
public void onPaymentFinished(PaymentFinishedEvent event) {
    checkPaymentResult(event.resultCode);
}

private void checkPaymentResult(int resultCode) {
    Log.i("checkPaymentResult", "1");
    Request request = buildCheckingPaymenResultRequest();

    Log.i("checkPaymentResult", "2");
    final ProgressDialog progressDialog = ProgressDialog.show(this, "", "Checking...", true);

    Log.i("checkPaymentResult", "3");
    request.execute(new Listener() { ... });
}

Когато стартирам приложението и плащането приключи, PaymentResultActivity се задейства, събитието се публикува в автобуса и методът checkPaymentResult се изпълнява успешно. Но когато направя нова поръчка в приложението отново и завърша плащането, събитието също ще бъде публикувано, но приложението просто ще блокира и няма да провери резултата.

Добавих трите реда за регистриране на грешки в кода по-горе, за да разбера на коя стъпка приложението е блокирало, и се показва, че 1 и 2 се отпечатват в Android Monitor, но 3 никога няма да се отпечата, което означава, че ProgressDialog.show може не се изпълнява успешно и програмата просто се забива там. Не мога да разбера защо кодът може да се провали само при втория опит.

Между другото, режимът на стартиране на PaymentResultActivity е singleTop, който се изисква от приложението на трета страна.


person Beta Kuang    schedule 23.08.2016    source източник


Отговори (1)


Изглежда, че когато Otto задейства събитие обратно към CreateOrderActivity, активността все още е на пауза във фонов режим и не може да извърши никакви операции в потребителския интерфейс (прозорец, изглед и т.н.). Затова добавям флаг в CreateOrderActivity, за да кажа дали трябва да провери резултата от плащането:

public class CreateOrderActivity extends AppCompatActivity {

    ...

    private boolean shouldCheckPaymentResult = false;

    ...
}

И в манипулатора на събития просто задайте флага на true:

@Subscribe
public void onPaymentFinished(PaymentFinishedEvent event) {
    if (event.resultCode == PaymentFinishedEvent.RESULT_SUCCESS) {
        shouldCheckPaymentResult = true;
    }
}

Последната стъпка е да извършите проверката в onResume():

@Override
protected void onResume() {
    super.onResume();

    if (shouldCheckPaymentResult) {
        shouldCheckPaymentResult = false;
        checkPaymentResult();
    }
}
person Beta Kuang    schedule 25.08.2016