Kindle Fire: утечка из PopupMenu$OrientationChangeListener
У меня есть небольшое всплывающее меню, которое привязывает кнопку к панели действий. Это хорошо работает на 3.0/3.1 вкладках Xoom и Galaxy, а также на 4.1 Nexus 7.
Тем не менее, на 7" Fire HD ( этот), я получаю ошибку о приемнике утечки намерений при выходе из приложения. Ошибка возникает, только если меню не было открыто во время этого запуска.
Там нет упоминания о OrientationChangeListener
в одной копии источника, который я нашел; Я подозреваю, что у Amazon есть другая реализация.
Вопросы:
- Кто-нибудь сталкивался с этим?
- Кто-нибудь знает об обходном пути или исправлении?
- (Где) я могу найти исходный код Amazon?
- Наконец, (содрогается) насколько важно, чтобы я не пропускал приемник при выходе из приложения?
Вот меню xml:
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_profile"
android:title="@string/menu_item_profile"
></item>
<item android:id="@+id/menu_logout"
android:title="@string/menu_item_logout"
></item>
</menu>
Здесь я регистрирую это:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
MenuItem login = menu.findItem(R.id.menu_login);
Button button = (Button) login.getActionView().findViewById(R.id.login);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
profileMenu.show();
}
});
// profileMenu is an instance field
profileMenu = new PopupMenu(this, button);
inflater.inflate(R.menu.profile_menu, profileMenu.getMenu());
profileMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// there was code here, but I removed it all and the problem persists
return false;
}
});
return true;
}
Вот полная трассировка стека:
10-21 20:55:28.461: E/ActivityThread(4526): Activity **.app.ListActivity has leaked IntentReceiver android.widget.PopupMenu$OrientationChangeListener@422d77e0 that was originally registered here. Are you missing a call to unregisterReceiver()?
10-21 20:55:28.461: E/ActivityThread(4526): android.app.IntentReceiverLeaked: Activity **.app.ListActivity has leaked IntentReceiver android.widget.PopupMenu$OrientationChangeListener@422d77e0 that was originally registered here. Are you missing a call to unregisterReceiver()?
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:826)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:621)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1072)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1059)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1053)
10-21 20:55:28.461: E/ActivityThread(4526): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:357)
10-21 20:55:28.461: E/ActivityThread(4526): at android.widget.PopupMenu.<init>(PopupMenu.java:81)
10-21 20:55:28.461: E/ActivityThread(4526): at **.app.ListActivity.onCreateOptionsMenu(ListActivity.java:350)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.Activity.onCreatePanelMenu(Activity.java:2558)
10-21 20:55:28.461: E/ActivityThread(4526): at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:398)
10-21 20:55:28.461: E/ActivityThread(4526): at com.android.internal.policy.impl.PhoneWindow.invalidatePanelMenu(PhoneWindow.java:883)
10-21 20:55:28.461: E/ActivityThread(4526): at com.android.internal.policy.impl.PhoneWindow$2.run(PhoneWindow.java:3008)
10-21 20:55:28.461: E/ActivityThread(4526): at android.os.Handler.handleCallback(Handler.java:605)
10-21 20:55:28.461: E/ActivityThread(4526): at android.os.Handler.dispatchMessage(Handler.java:92)
10-21 20:55:28.461: E/ActivityThread(4526): at android.os.Looper.loop(Looper.java:137)
10-21 20:55:28.461: E/ActivityThread(4526): at android.app.ActivityThread.main(ActivityThread.java:4491)
10-21 20:55:28.461: E/ActivityThread(4526): at java.lang.reflect.Method.invokeNative(Native Method)
10-21 20:55:28.461: E/ActivityThread(4526): at java.lang.reflect.Method.invoke(Method.java:511)
10-21 20:55:28.461: E/ActivityThread(4526): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
10-21 20:55:28.461: E/ActivityThread(4526): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
10-21 20:55:28.461: E/ActivityThread(4526): at dalvik.system.NativeStart.main(Native Method)
1 ответ
Я решил эту конкретную проблему, просто создав PopupMenu при первом нажатии кнопки привязки. Поскольку утечка произошла только при выходе из активности перед отображением меню, я решил, что устранение этого состояния - достойный вариант.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
MenuItem login = menu.findItem(R.id.menu_login);
final Button button = (Button) login.getActionView().findViewById(R.id.login);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View item) {
if (profileMenu == null) {
profileMenu = new PopupMenu(ListActivity.this, button);
inflater.inflate(R.menu.profile_menu, profileMenu.getMenu());
profileMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// do something with item
return false;
}
});
}
profileMenu.show();
}
});
return true;
}
Есть один остающийся крайний случай, который вызывает утечку окна PopupMenu. Я опубликую это в новом вопросе и скоро свяжу здесь. Я не думаю, что решу эту проблему, не реализовав PopupMenu с нуля.