如何避免BroadcastReceiver泄漏

时间:2013-08-26 20:37:53

标签: java android android-broadcast

我正在构建一个具有以下结构的库:

MySDK{
   public static void init(Context context){
      registerReceivers(); // Register connectivity BroadcastReceiver here
   }

   public static void performAction(){};
}

预期用途是:我的库用户在他们创建的第一个 Activity 中调用 init()。问题是我没有取消注册 BroadcastReceiver ,并且当应用关闭时它会泄漏。我可以创建一个名为 deinit()的方法,并要求lib的用户在离开 Activity 时调用它,但是有更可靠的方式来释放资源吗? / p>

为什么我需要接收器吗?

如果没有Internet连接且 performAction()无法发送数据,我会注册接收器以检测连接状态的变化。

5 个答案:

答案 0 :(得分:3)

如果你声明清单android中的广播接收器将负责寄存器的处理。

将接收器注册在应用程序标签中,如下所示

<receiver android:name="class name with package">  
        <intent-filter>
            <action android:name=" corresponding broadcast name" />
        </intent-filter>
</receiver>

答案 1 :(得分:2)

如果performAction()需要推迟操作,为什么不注册接收器?这将限制接收器只有在实际存在等待完成的情况下才能到位。一旦接收器成功刷新其动作队列,它就可以取消注册接收器本身。

答案 2 :(得分:0)

一旦onReceive方法完成(在其结尾处),您可以取消注册接收器。

但我不知道这是否适合你,这取决于你的接收器做什么。

在注册SMSsent /交付的接收器时,它对我有用..

答案 3 :(得分:0)

您是否考虑过扩展android.app.Application并实现这些方法:

void onCreate() 

void onLowMemory()

您可以在onCreate中注册所需的所有BroadcastReceiver,并在onLowMemory中取消注册。

要检索此类的引用,可以调用context.getApplicationContext()并将其强制转换为Application子类。

最后,为了让您的应用程序使用此解决方案,您必须将这些信息放在AndroidManifest.xml中的标记内,如下所示:

<application
  android:allowBackup="true"
  android:icon="@drawable/ic_launcher"
  android:label="@string/app_name"
  android:name="[fully qualified name of your Application subclass]" >
...
</application>

答案 4 :(得分:0)

如果您需要在所有活动中使用接收器,您应该创建一个注册接收器的服务here,您可以看到如何创建服务。

要取消注册接收器,您可以检测用户何时完成应用,知道当前位于前台的包名称。当您不再需要它时,您将取消注册接收器,当用户退出应用程序时,它不会泄漏,因为它现在已创建并附加到服务,而不是应用程序或活动。

public String getForegroundApp() throws NameNotFoundException{ 

        RunningTaskInfo info = null;
        ActivityManager am;
        am = (ActivityManager)mContext.getSystemService(ACTIVITY_SERVICE);
        List<RunningTaskInfo> l = am.getRunningTasks(1000);
        System.out.println(l);
        Iterator <RunningTaskInfo> i = l.iterator();


        String packName = new String();
        String appName = new String();
        ApplicationInfo appInfo = new ApplicationInfo();

        while(i.hasNext()){
            info = i.next();
            packName = info.topActivity.getPackageName();
            if(!packName.equals("com.htc.launcher") && !packName.equals("com.android.launcher")){ //this could be what is causing the problem. not sure.
                packName = info.topActivity.getPackageName();
                break;
            }
            info = i.next();
            packName= info.topActivity.getPackageName();
            break;          
            }
        return packName;
        }

无论如何,我认为你应该创建类似stop()方法的东西,当用户知道退出应用程序并且不再需要库时,让用户调用它来完成你想要的一切。