Java 如何避免广播接收器泄漏

Java 如何避免广播接收器泄漏,java,android,android-broadcast,Java,Android,Android Broadcast,我正在建造一个图书馆,它的结构如下: MySDK{ public static void init(Context context){ registerReceivers(); // Register connectivity BroadcastReceiver here } public static void performAction(){}; } 预期用途是:my library的用户在创建的第一个活动中调用init()。问题是我没有注销Broadcas

我正在建造一个图书馆,它的结构如下:

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

   public static void performAction(){};
}
预期用途是:my library的用户在创建的第一个活动中调用init()。问题是我没有注销BroadcastReceiver,当应用程序关闭时,它会泄漏。我可以创建一个名为deinit()的方法,并要求lib的用户在离开活动时调用它,但有没有更可靠的方法来释放资源

为什么我需要接收器


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

一旦onReceive方法完成(在结束时),就可以注销接收器

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


注册SMSsent/delivered receiver时,它对我很有效。

如果performAction()需要延迟操作,为什么不只注册接收者?这将限制接收器仅在实际有事情等着做的情况下就位。一旦接收器成功刷新其操作队列,它就可以注销接收器本身。

您是否想过扩展android.app.Application并实现以下方法:

void onCreate() 

void onLowMemory()
您可以在onCreate中注册所需的所有BroadcastReceiver,并在onLowMemory中注销它们

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

最后,要让您的应用程序使用此解决方案,您必须将这些信息放入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>

...

如果您在清单中声明广播接收器,android将负责处理注册表

像这样在应用程序标记中注册您的接收器

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

如果您在所有活动中都需要接收者,您应该创建一个注册接收者的服务,您可以查看如何创建服务

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

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;
        }
公共字符串getForegroundApp()引发NameNotFoundException{
RunningTaskInfo=null;
活动管理器am;
am=(ActivityManager)mContext.getSystemService(ACTIVITY\u服务);
列表l=am.getRunningTasks(1000);
系统输出打印LN(l);
迭代器i=l.迭代器();
String packName=新字符串();
String appName=新字符串();
ApplicationInfo appInfo=新的ApplicationInfo();
while(i.hasNext()){
info=i.next();
packName=info.topActivity.getPackageName();
如果(!packName.equals(“com.htc.launcher”)&&!packName.equals(“com.android.launcher”){//这可能是导致问题的原因。不确定。
packName=info.topActivity.getPackageName();
打破
}
info=i.next();
packName=info.topActivity.getPackageName();
打破
}
返回packName;
}

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

广播接收器只在第一个活动中需要还是需要更长时间?@Simon查看更新。我将一直需要接收器。创建一个注册此接收器的服务。我不明白你的问题。你想注销你的收信人,但同时你想让收信人一直在场?!?为了避免注册多个接收器的问题,这非常简单。它也不需要手动启动应用程序来接收通知。服务总是由系统保持运行。在这种情况下,这是一个巨大的资源消耗,服务除了成为接收者的占位符之外,什么都不用做。。。