W najnowszej wersji mojej aplikacji niektórzy użytkownicy mają awarię, której nie mogę odtworzyć. Obecnie tylko urządzenia o numerze Samsung
pracujące pod numerem Lollipop
mają problem, ale może to być tylko zbieg okoliczności. Po przeanalizowaniu śladu stosu i odpowiedniego kodu, myślę, że mogłem znaleźć winnego. Aby przetestować moje założenie, że uproszczony kod na poniższym fragmencie:Czy możliwe jest wywołanie metody oddzwaniania po onDestroy?
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button b = new Button(this);
b.setText("Click me!");
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Handler().post(new Runnable() {
@Override
public void run() {
// This is the callback method
Log.d("TAG", "listenerNotified");
}
});
}
});
setContentView(b);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("TAG", "onDestroy");
}
}
Za każdym razem testować powyższym wniosku przez pierwsze dotknięcie Kliknij mnie przycisk, a następnie przycisk Wstecz, listenerNotified
jest drukowany na konsolę przed onDestroy()
.
Nie jestem jednak pewien, czy mogę polegać na tym zachowaniu. Czy Android
daje jakiekolwiek gwarancje dotyczące powyższego scenariusza? Czy mogę bezpiecznie założyć, że mój Runnable
będzie zawsze wykonywany przed onDestroy()
, czy istnieje scenariusz, w którym tak nie jest? W mojej prawdziwej aplikacji jest oczywiście dużo więcej rzeczy (jak inne wątki wysyłane do głównego wątku i więcej operacji występujących w oddzwanianiu). Ale ten prosty fragment wydawał się wystarczający do wykazania mojej troski.
Czy jest to możliwe (możliwe, że z powodu wpływu innych wątków lub wywołań zwrotnych wysłanych do głównego wątku), że otrzymam dane wyjściowe debugowania poniżej?
D/TAG: onDestroy
D/TAG: listenerNotified
Chciałbym to wiedzieć, ponieważ ten wynik byłby możliwy do wyjaśnienia katastrofy.
Dlaczego publikujesz uruchamianie za pomocą programu obsługi? Tymczasem możesz rzucić okiem na http://stackoverflow.com/questions/31432014/onclicklistener-fired-after-onpause –
Kiedy masz asynchroniczne callbacki w ten sposób, zawsze powinieneś sprawdzić callback, jeśli 'Activity' jest jeszcze żywa przed przetwarzanie wywołania zwrotnego. Najprościej to zrobić, wywołując 'isFinishing()', która zwraca 'true', jeśli' Activity' nie jest już "aktywny". –