Hata: BinderProxy @ 45d459c0 geçerli değil; etkinliğiniz çalışıyor mu?


144

Bu hata nedir ... stackoverflow topluluğunda bu hata hakkında herhangi bir tartışma bulamadık Ayrıntılı: -

10-18 23:53:11.613: ERROR/AndroidRuntime(3197): Uncaught handler: thread main exiting due to uncaught exception
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@45d459c0 is not valid; is your activity running?
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.ViewRoot.setView(ViewRoot.java:468)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.Dialog.show(Dialog.java:239)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.vishal.contacte.Locationlistener$MyLocationListener.onLocationChanged(Locationlistener.java:86)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:179)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:112)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:128)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Looper.loop(Looper.java:123)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.ActivityThread.main(ActivityThread.java:4363)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invokeNative(Native Method)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invoke(Method.java:521)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at dalvik.system.NativeStart.main(Native Method)

bu bağlantıyı kontrol et: Android - [Arka Plan Konularından İletişim Kutularını Görüntüleme] ( dimitar.me/android-displaying-dialogs-from-background-threads )
Naveen

Bağlantınız kabul edilen cevaba benziyor, ancak çok daha iyi açıklandı. Bunun için teşekkürler
LuckyMalaka


Yanıtlar:


343

Bu, büyük olasılıkla Etkinlik yok edilirken arka plan iş parçacığının yürütülmesinden sonra bir iletişim kutusu göstermeye çalıştığınız için olur.

Diyaloğu çağıran etkinlik bir sebepten ötürü bir iletişim kutusu göstermeye çalıştığında bazı hatalar zaman zaman bu uygulamalarımdan bildirildiğini görüyordum. İşte benim için bunu çözen:

if(!((Activity) context).isFinishing())
{
    //show dialog
}

Bunu birkaç yıldır Android'in eski sürümlerindeki sorunu çözmek için kullanıyorum ve o zamandan beri çökmeyi görmedim.


1
Aslında bu hile yapar! ancak bu gerçekleşse bile iletişim kutusunu açmanın bir yolu var mı? Bu olduğunda iletişim kutusunun nasıl yönetileceğinden emin değilim. Baska öneri? Şimdiden teşekkürler!
Carla Urrea Stabil

@CarlaStabile merhaba! Bu gerçekleştiğinde bir iletişim kutusu göstermeyi düşünebilmemin tek yolu, bitmeyen bir etkinlik için geçerli bir Bağlam elde edebilmeniz olabilir - bu kodu nereye çağırdığınıza ve bir başka bir bitirme faaliyetinden bağlam.
DiscDev

8
Milyonlarca kez teşekkürler! Benim için, İletişim kutusu gösterilmeden önce geri düğmesine bastığımda kilitlenme (yukarıdaki hata mesajıyla) gerçekleşecekti. Farklı bir etkinlikte olmama rağmen kod devam edecek ve göstermeye çalışacaktı. Ama bu kazayı durdurdu ve yeni aktiviteye kolaylıkla gittim!
Azurespot

1
Birçok benzer soru var, ama hiçbirinde bu önerilmedi. Şahsen bu benim senaryom için tek doğru çözümdü.
fillobotto

bunun için kotlin versiyonu nedir? isFinishing () yeterli olacak mı?
Alok Rajasukumaran

12

Aynı sorunla karşılaştım ve yukarıdaki DiscDev tarafından önerilen kodu aşağıdaki gibi küçük değişikliklerle kullandım:

if (!MainActivity.this.isFinishing()){
    alertDialog.show();
}

ben değişti çünkü (Etkinlik) bağlam ortalama benim durumum için MainActivity.this oldu. Ayrıca kullanıcı profili bağlantısı hakkında haklısın, ama yukarıda bulabileceğini düşündüm.
Hamza Polat

4

iletişim kutusu iş parçacığı nedeniyle bu sorunu trowing ise bunu UI iş parçacığında böyle yapmalısınız: -

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                dialog.show();

            }
        });

2

Bu hata, artık var olmayan bir bağlamın iletişim kutusunu gösterirken oluşur.

Aramadan önce .show()etkinliğin / içeriğin bitmediğinden emin olun

if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
    alert.show();
}

1

countDownTimerUygulamamda bir hata varken bu hatayla karşılaştım . Uygulamamda GameOver'ı çağıran bir yöntem vardı.

public void onFinish() {
     GameOver();
}

ama aslında kullanıcının yanlış bir tıklama (zaman bir tıklama oyunu nedeniyle) zaman dolmadan önce bitmiş olabilir. 20 saniye sonra Game Over iletişim kutusuna baktığımda, zaman dolduktan sonra iptal etmeyi unuttum countDownTimer, iletişim kutusu tekrar belirdi. Veya herhangi bir nedenle yukarıdaki hata ile çöktü.


1

Bunun çözümü oldukça basit. İletişim Kutusunu görüntülemeden önce Faaliyetin bitiş aşamasından geçip geçmediğini test etmeniz yeterlidir:

  private Handler myHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    switch (msg.what) {
      case DISPLAY_DLG:
        if (!isFinishing()) {
        showDialog(MY_DIALOG);
        }
      break;
    }
  }
};

burada daha fazlasını gör


1

Benim durumumda sorun, Contextsınıfta genişleyen referans olarak zayıf tutulmasıydı Handler. Sonra geçiyordu Messenger, bu bir sayesinde, işleyici sarar Intentbir etmek Service. Etkinlik onResume()yöntem ekranda görünen her zaman bunu yapıyordum .

Anladığınız gibi, Messenger alanları (bağlam dahil) ile serileştirildi, çünkü nesneleri Intentserileştirmek için - kullanarak nesneleri geçirmenin tek yolu bu . Messenger hizmete aktarıldığı anda, etkinliğin kendisi başka bir durumda olduğu gibi iletişim kutularını göstermeye hala hazır değildi (onResume () olarak adlandırılır, bu etkinlik zaten ekranda olduğundan kesinlikle farklıdır). Bu yüzden, habercinin serileştirilmesi kaldırıldığında, etkinlik gerçekte ekrandayken içerik hala devam ediyordu. Ayrıca, serileştirme orijinal nesneden tamamen farklı olan yeni nesne için bellek ayırır.

Çözüm, her ihtiyacınız olduğunda hizmete bağlanmak ve 'setMessenger (Messenger messenger)' gibi bir yöntemi olan bir bağlayıcıyı döndürmek ve hizmete bağlandığınızda çağırmaktır.


1

Bu sorunu WeakReference<Activity>bağlam olarak kullanarak çözüyorum. Kaza bir daha asla ortaya çıkmadı. İşte Kotlin'de bir örnek kod:

İletişim kutusu sınıfı:

class DialogManager {

        fun showAlertDialog(weakActivity: WeakReference<Activity>) {
            val wActivity = weakActivity.get()
            wActivity?.let {
                val builder = AlertDialog.Builder(wActivity, R.style.MyDialogTheme)
                val inflater = wActivity.layoutInflater
                val dialogView = inflater.inflate(R.layout.alert_dialog_info, null)
                builder.setView(dialogView)

                // Set your dialog properties here. E.g. builder.setTitle("MyTitle")

                builder.create().show()
            }
         }

}

Ve iletişim kutusunu şöyle gösterin:

 val dialogManager = DialogManager()
 dialogManager.showAlertDialog(WeakReference<Activity>(this@MainActivity))

Super-duper çarpışmalara karşı korunmak istiyorsanız. Kullanım yerine builder.create().show():

val dialog = builder.create()
safeShow(weakActivity, dialog)

Bu safeShowyöntem:

private fun safeShow(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (!dialog.isShowing && !(wActivity).isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }

Bu, iletişim kutusunu güvenli bir şekilde kapatmak için kullanabileceğiniz benzer bir yöntemdir:

private fun safeDismissAlertDialog(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (dialog.isShowing && !wActivity.isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }

0

aramak istediğiniz iletişim kutusunun yeni bir örneğini oluşturmaya ne dersiniz? Aslında aynı problemle daha yeni tanıştım ve yaptığım da bu. yerine:

if(!((Activity) context).isFinishing())
{
    //show dialog
}

buna ne dersin?

 YourDialog mDialog = new YourDialog();
 mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
                        }

iletişim kutusunu göstermek güvenli olup olmadığını kontrol etmek yerine, sadece iletişim kutusunu göstermek için yeni bir örnek oluşturmamızın daha güvenli olduğunu düşünüyorum .

Benim gibi, benim durumumda bir örnek oluşturmaya çalıştım ( Fragment onCreate'den ) ve bu iletişim kutusunun örneğini adaptörList'in başka bir içeriğinde çağırdım ve bu da "etkinliğiniz çalışıyor" hatasıyla sonuçlanacaktır . Ben sadece bir örnek (onCreate itibaren) oluşturmak ve sonra yok edilir, çünkü başka bir bağdaştırıcı listesinden çağırmaya çalıştım çünkü eski örnekten iletişim çağırıyor çünkü olduğunu düşündüm.

Çözümümün bellek dostu olup olmadığından emin değilim, çünkü profil oluşturmaya çalışmadım, ancak işe yarıyor (çok fazla örnek oluşturmazsanız kesinlikle güvenlidir)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.