Ошибка: BinderProxy @45d459c0 недействителен; работает ли ваша деятельность?
Что это за ошибка... я не нашел обсуждения этой ошибки в сообществе stackoverflow. Подробно: -
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 [email protected] 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)
Ответы
Ответ 1
Это, скорее всего, происходит потому, что вы пытаетесь показать диалог после выполнения фонового потока, а активность уничтожается.
Я видел, что эта ошибка сообщалась раз в то время из некоторых моих приложений, когда активность, вызывающая диалог, заканчивалась по той или иной причине, когда она пыталась показать диалог. Вот что решило это для меня:
if(!((Activity) context).isFinishing())
{
//show dialog
}
Я использую это, чтобы обойти эту проблему в более старых версиях Android уже несколько лет, и с тех пор не видел аварии.
Ответ 2
проверьте эту ссылку:
Android - Отображение диалогов из фоновых потоков
Ответ 3
Я столкнулся с той же проблемой и использовал код, предложенный DiscDev выше, с небольшими изменениями следующим образом:
if (!MainActivity.this.isFinishing()){
alertDialog.show();
}
Ответ 4
Я столкнулся с этой ошибкой, когда у меня было countDownTimer
в моем приложении. У него был метод, вызывающий GameOver в моем приложении как
public void onFinish() {
GameOver();
}
но на самом деле игра может закончиться до того, как время закончилось из-за неправильного щелчка пользователя (это была игра с щелчком). Поэтому, когда я смотрел диалоговое окно Game Over, например, 20 секунд, я забыл отменить countDownTimer
, поэтому раз время было, диалог снова появился. Или по какой-то причине с ошибкой выше.
Ответ 5
Исправить это довольно просто. Просто проверьте, проходит ли Activity на своей заключительной стадии перед отображением диалога:
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DISPLAY_DLG:
if (!isFinishing()) {
showDialog(MY_DIALOG);
}
break;
}
}
};
подробнее здесь
Ответ 6
В моем случае проблема заключалась в том, что Context
оставался слабой ссылкой в классе, расширяющем Handler
. Затем я передавал Messenger
, который оборачивает обработчик, через Intent
на Service
. Я делал это каждый раз, когда активность появлялась на экране в onResume()
.
Итак, как вы понимаете, Messenger был сериализован вместе со своими полями (включая контекст), потому что это единственный способ передавать объекты с помощью Intent
- их сериализация. В тот момент, когда Messenger был передан в службу, само действие все еще не было готово для отображения диалогов, поскольку оно находится в другом состоянии (как говорится на Resume(), которое абсолютно отличается от того, когда действие уже находится на экране). Поэтому, когда мессенджер был десериализован, контекст все еще находился в состоянии возобновления, в то время как действие фактически уже было на экране. Кроме того, десериализация выделяет память для нового объекта, который полностью отличается от исходного.
Решение состоит в том, чтобы просто связываться со службой каждый раз, когда вам это нужно, и возвращать связыватель, у которого есть метод, такой как 'setMessenger (Messenger messenger)', и вызывать его, когда вы привязаны к службе.
Ответ 7
если диалог вызывает эту проблему из-за потока, вы должны выполнить это в потоке пользовательского интерфейса следующим образом:
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.show();
}
});
Ответ 8
Я WeakReference<Activity>
эту проблему, используя WeakReference<Activity>
в качестве контекста. Крушение никогда не появлялось снова. Вот пример кода в Котлине:
Диалог менеджер класса:
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()
}
}
}
И вы показываете диалог следующим образом:
val dialogManager = DialogManager()
dialogManager.showAlertDialog(WeakReference<Activity>([email protected]))
Если вы хотите быть супер-защищенным от сбоев. Вместо builder.create().show()
используйте:
val dialog = builder.create()
safeShow(weakActivity, dialog)
Это метод safeShow
:
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
}
}
}
}
}
Это аналогичный метод, который вы можете использовать для безопасного закрытия диалогового окна:
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
}
}
}
}
}
Ответ 9
Эта ошибка возникает, когда вы показываете диалог для контекста, который больше не существует.
Перед вызовом .show()
убедитесь, что действие/контекст не заканчивается
if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
alert.show();
}
Ответ 10
В моем случае я забыл прокомментировать finish();
Ответ 11
как насчет создания нового экземпляра этого диалога, который вы хотите вызвать? Я на самом деле только что встретил ту же проблему, и это то, что я делаю. так, а не:
if(!((Activity) context).isFinishing())
{
//show dialog
}
как насчет этого?
YourDialog mDialog = new YourDialog();
mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
}
поэтому вместо того, чтобы просто проверять, безопасно или нет показывать диалог, я думаю, что гораздо безопаснее, если мы просто создадим новый экземпляр для показа диалога.
Как и я, в моем случае я попытался создать один экземпляр (из фрагмента onCreate) и вызвать экземпляр этого диалогового окна в другом содержимом адаптера, и это приведет к ошибке "ваша деятельность запущена" - ошибка. Я думал, что это потому, что я просто создаю один экземпляр (из onCreate), а затем он уничтожается, поэтому, когда я пытался вызвать его из другого адаптера, я вызывал диалог из старого экземпляра.
Я не уверен, является ли мое решение дружественным к памяти или нет, потому что я не пытался его профилировать, но оно работает (конечно, безопасно, если вы не создаете слишком много экземпляров)