Kindle Fire的:PopupMenu的$ OrientationChangeListener泄漏 [英] Kindle Fire: PopupMenu$OrientationChangeListener leak

查看:328
本文介绍了Kindle Fire的:PopupMenu的$ OrientationChangeListener泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有在操作栏按钮锚一点弹出菜单。这适用于3.0 / 3.1的Xoom和Galaxy标签,和4.1的Nexus 7。

然而,在一个7火HD(这个),我得到一个关于泄露的意图接收错误退出应用程序时,只有在该运行期间未打开菜单时发生错误。

OrientationChangeListener 的没有提及<一个href=\"http://www.java2s.com/Open-Source/Android/android-platform-apps/Gallery3D/com/cooliris/media/PopupMenu.java.htm\"相对=nofollow>我发现源的一个副本;我怀疑亚马逊有不同的实现。

问题


  • 有没有人遇到过吗?

  • 有谁知道一种解决方法或修复?

  • (这里的)可以找到亚马逊的源$ C ​​$ C?

  • 最后,(不寒而栗的)有多重要,我不应用程序退出泄漏接收器?

这是菜单的xml:

 &LT;?XML版本=1.0编码=UTF-8&GT?;
&LT;菜单
  的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android&GT;
    &LT;项目机器人:ID =@ + ID / menu_profile
        机器人:标题=@字符串/ menu_item_profile
        &GT;&LT; /项目&GT;
    &LT;项目机器人:ID =@ + ID / menu_logout
        机器人:标题=@字符串/ menu_item_logout
        &GT;&LT; /项目&GT;&所述; /菜单&gt;

这是我注册的:

  @覆盖
公共布尔onCreateOptionsMenu(菜单菜单){
    super.onCreateOptionsMenu(菜单);
    MenuInflater吹气= getMenuInflater();
    inflater.inflate(R.menu.main_menu,菜单);    菜单项登录= menu.findItem(R.id.menu_login);
    Button按钮=(按钮)login.getActionView()findViewById(R.id.login)。
    button.setOnClickListener(新View.OnClickListener(){
        公共无效的onClick(视图v){
            profileMenu.show();
        }
    });
    // profileMenu是一个实例字段
    profileMenu =新PopupMenu的(这一点,按钮);
    inflater.inflate(R.menu.profile_menu,profileMenu.getMenu());
    profileMenu.setOnMenuItemClickListener(新PopupMenu.OnMenuItemClickListener(){
        公共布尔onMenuItemClick(菜单项项){
            //有code在这里,但我删除了这一切,问题仍然存在
            返回false;
        }
    });    返回true;
}

下面是完整的堆栈跟踪:

  20 10-21:55:28.461:E / ActivityThread(4526):活动** app.ListActivity渗漏IntentReceiver android.widget.PopupMenu$OrientationChangeListener@422d77e0这原是在这里注册。你缺少unregisterReceiver()的调用?
10-21 20:55:28.461:E / ActivityThread(4526):android.app.IntentReceiverLeaked:活动** app.ListActivity渗漏,最初这里注册IntentReceiver android.widget.PopupMenu$OrientationChangeListener@422d77e0。你缺少unregisterReceiver()的调用?
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.LoadedApk $ ReceiverDispatcher&LT;&初始化GT;(LoadedApk.java:826)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:621)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1072)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.ContextImpl.registerReceiver(ContextImpl.java:1059)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.ContextImpl.registerReceiver(ContextImpl.java:1053)
10-21 20:55:28.461:E / ActivityThread(4526):在android.content.ContextWrapper.registerReceiver(ContextWrapper.java:357)
10-21 20:55:28.461:E / ActivityThread(4526):在android.widget.PopupMenu&LT;&初始化GT;(PopupMenu.java:81)
10-21 20:55:28.461:E / ActivityThread(4526):在** app.ListActivity.onCreateOptionsMenu(ListActivity.java:350)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.Activity.onCreatePanelMenu(Activity.java:2558)
10-21 20:55:28.461:E / ActivityThread(4526):在com.android.internal.policy.impl.PhoneWindow preparePanel(PhoneWindow.java:398)
10-21 20:55:28.461:E / ActivityThread(4526):在com.android.internal.policy.impl.PhoneWindow.invalidatePanelMenu(PhoneWindow.java:883)
10-21 20:55:28.461:E / ActivityThread(4526):在com.android.internal.policy.impl.PhoneWindow $ 2.run(PhoneWindow.java:3008)
10-21 20:55:28.461:E / ActivityThread(4526):在android.os.Handler.handleCallback(Handler.java:605)
10-21 20:55:28.461:E / ActivityThread(4526):在android.os.Handler.dispatchMessage(Handler.java:92)
10-21 20:55:28.461:E / ActivityThread(4526):在android.os.Looper.loop(Looper.java:137)
10-21 20:55:28.461:E / ActivityThread(4526):在android.app.ActivityThread.main(ActivityThread.java:4491)
10-21 20:55:28.461:E / ActivityThread(4526):在java.lang.reflect.Method.invokeNative(本机方法)
10-21 20:55:28.461:E / ActivityThread(4526):在java.lang.reflect.Method.invoke(Method.java:511)
10-21 20:55:28.461:E / ActivityThread(4526):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:784)
10-21 20:55:28.461:E / ActivityThread(4526):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
10-21 20:55:28.461:E / ActivityThread(4526):在dalvik.system.NativeStart.main(本机方法)


解决方案

我刚才所创建的弹出菜单时,其锚点按钮首先是pressed解决了这个特殊的问题。由于显示菜单之前退出活动时泄漏发生只,我想消除的状态是一个不错的选择。

  @覆盖
公共布尔onCreateOptionsMenu(菜单菜单){
    super.onCreateOptionsMenu(菜单);
    MenuInflater吹气= getMenuInflater();
    inflater.inflate(R.menu.main_menu,菜单);    菜单项登录= menu.findItem(R.id.menu_login);
    最后Button按钮=(按钮)login.getActionView()findViewById(R.id.login)。
    button.setOnClickListener(新View.OnClickListener(){
        公共无效的onClick(查看项目){
            如果(profileMenu == NULL){
                profileMenu =新的PopupMenu(ListActivity.this,按钮);
                inflater.inflate(R.menu.profile_menu,profileMenu.getMenu());
                profileMenu.setOnMenuItemClickListener(新PopupMenu.OnMenuItemClickListener(){
                    公共布尔onMenuItemClick(菜单项项){
                        //做一些项目
                        返回false;
                    }
                });
            }
            profileMenu.show();
        }
    });
    返回true;
}

有一个导致被泄露的弹出菜单的窗口,其余边缘情况。我会后,在一个新的问题,在这里很快联系起来。我不认为我会解决一个没有从头开始重新实现PopupMenu的,虽然。

I have a little popup menu that anchors on a button in the action bar. This works well on 3.0/3.1 Xoom and Galaxy tabs, and a 4.1 Nexus 7.

However, on a 7" Fire HD (this one), I get an error about a leaked intent receiver when exiting the application. The error occurs only if the menu was not opened during that run.

There is no mention of OrientationChangeListener in the one copy of the source I've found; I suspect Amazon has a different implementation.

Questions:

  • Has anyone encountered this?
  • Does anyone know of a workaround or a fix?
  • (Where) can I find Amazon's source code?
  • Finally, (shudder) how important is it that I don't leak a receiver on application exit?

Here is the menu 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>

This is where I register it:

@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;
}

Here is the full stack trace:

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)

解决方案

I've solved this particular problem by just creating the PopupMenu when its anchor button is first pressed. Since the leak only occurred when exiting the activity before showing the menu, I figured eliminating that state was a decent option.

@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;
}

There is one remaining edge case that causes the PopupMenu's window to be leaked. I'll post that in a new question and link it here shortly. I don't think I'll solve that one without reimplementing PopupMenu from scratch, though.

这篇关于Kindle Fire的:PopupMenu的$ OrientationChangeListener泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆