Android中的ServiceConnectionLeak

Android中的ServiceConnectionLeak,android,android-service,memory-leaks,superclass,Android,Android Service,Memory Leaks,Superclass,我正在尝试使用Android中的服务进行一些基本的数据库操作,但由于某种原因,我得到一个活动泄漏了ServiceConnection错误。我将在底部发布完整的Logcat读数 我必须在多个活动中使用相同的服务,因此我创建了一个超类来处理所有服务任务。看起来是这样的: private MyInterface child; public void onCreate(Bundle savedInstanceState, MyInterface child){ super.onCreate(s

我正在尝试使用Android中的服务进行一些基本的数据库操作,但由于某种原因,我得到一个活动泄漏了ServiceConnection错误。我将在底部发布完整的Logcat读数

我必须在多个活动中使用相同的服务,因此我创建了一个超类来处理所有服务任务。看起来是这样的:

private MyInterface child;

public void onCreate(Bundle savedInstanceState, MyInterface child){
    super.onCreate(savedInstanceState);

    doBindService();
}

public void onResume(){
    super.onResume();

    doBindService();
}

protected void onPause(){
    super.onPause();

    doUnbindService();
}

private boolean bound;
private boolean binding;

ServiceConnection Connection = new ServiceConnection(){

    //called when the service is connected
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(LOGTAG, "Bound to Service");
        bound = true;
        binding = false;
        toServiceMessenger = new Messenger(service);
        while(!commandsForService.isEmpty()){
            sendToService(commandsForService.poll());
        }
    }

    //called when the service is disconnected
    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(LOGTAG, "Unboud from Service");
        bound = false;
        binding = false;
        toServiceMessenger = null;
    }
};

private boolean doBindService(){
    Log.d(LOGTAG, "Attempting to Bind to Service");
    if(!bound && !binding){
        binding = true;
        bindService(new Intent(this, global.FetchService.class), Connection, Context.BIND_AUTO_CREATE);
    }
    return bound;
}

private void doUnbindService(){
    Log.d(LOGTAG, "Attempting to Unbind from Service");
    if(bound && !binding){
        binding = true;
        unbindService(Connection);
    }
}

public void sendToService(Message msg){
    if(bound){
        sendMessageToService(msg);
    }
    else{
        commandsForService.add(msg);
    }
}

private void sendMessageToService(Message msg){
    if(bound){
        msg.replyTo = fromServiceMessenger;
        try {
            toServiceMessenger.send(msg);
        } catch (RemoteException e) {
            Log.d(LOGTAG, "RemoteException communicating with service");
        }
    }
    else{
        Log.d(LOGTAG, "Error: toServiceMessenger null while bound");
    }
}
其思想是,子活动永远不需要担心是否连接到服务,超类应该负责从服务获取数据并返回给子活动

Logcat指向onCreate()-->bindService(新意图(this,global.FetchService.class)、Connection、Context.BIND\u AUTO\u CREATE)中的doBindService();作为导致错误的行。但是,服务只有在活动运行并可见超过15秒后才会泄漏,因此我认为不应该调用onCreate()

下面是日志:

09-02 09:25:40.635: E/ActivityThread(5963): Activity childActivity has leaked ServiceConnection superClass$1@42cb1b70 that was originally bound here
09-02 09:25:40.635: E/ActivityThread(5963): android.app.ServiceConnectionLeaked: Activity childActivity has leaked ServiceConnection superClass$1@42cb1b70 that was originally bound here
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1055)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:949)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ContextImpl.bindService(ContextImpl.java:1472)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ContextImpl.bindService(ContextImpl.java:1464)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.content.ContextWrapper.bindService(ContextWrapper.java:394)
09-02 09:25:40.635: E/ActivityThread(5963):     at superClass.doBindService(FetchActivity.java:253)
09-02 09:25:40.635: E/ActivityThread(5963):     at superClass.onCreate(FetchActivity.java:61)
09-02 09:25:40.635: E/ActivityThread(5963):     at childActivity.onCreate(Showcase_Activity.java:37)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.Activity.performCreate(Activity.java:5066)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.access$600(ActivityThread.java:151)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.os.Looper.loop(Looper.java:155)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.main(ActivityThread.java:5493)
09-02 09:25:40.635: E/ActivityThread(5963):     at java.lang.reflect.Method.invokeNative(Native Method)
09-02 09:25:40.635: E/ActivityThread(5963):     at java.lang.reflect.Method.invoke(Method.java:511)
09-02 09:25:40.635: E/ActivityThread(5963):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
09-02 09:25:40.635: E/ActivityThread(5963):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
09-02 09:25:40.635: E/ActivityThread(5963):     at dalvik.system.NativeStart.main(Native Method)
09-02 09:25:40.635:E/ActivityThread(5963):Activity childActivity已泄漏ServiceConnection超类$1@42cb1b70原来是订在这里的
09-02 09:25:40.635:E/ActivityThread(5963):android.app.ServiceConnectionLeaked:Activity childActivity泄漏了ServiceConnection超类$1@42cb1b70原来是订在这里的
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.LoadedApk$ServiceDispatcher上(LoadedApk.java:1055)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:949)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.app.ContextImpl.bindService(ContextImpl.java:1472)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.app.ContextImpl.bindService(ContextImpl.java:1464)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.content.ContextWrapper.bindService(ContextWrapper.java:394)
09-02 09:25:40.635:E/ActivityThread(5963):在超类.doBindService(FetchActivity.java:253)
09-02 09:25:40.635:E/ActivityThread(5963):在超类.onCreate(FetchActivity.java:61)中
09-02 09:25:40.635:E/ActivityThread(5963):at childActivity.onCreate(Showcase_Activity.java:37)
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.Activity.performCreate(Activity.java:5066)上
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)上
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.ActivityThread.access$600(ActivityThread.java:151)
09-02 09:25:40.635:E/ActivityThread(5963):在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.os.Handler.dispatchMessage(Handler.java:99)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.os.Looper.loop(Looper.java:155)
09-02 09:25:40.635:E/ActivityThread(5963):位于android.app.ActivityThread.main(ActivityThread.java:5493)
09-02 09:25:40.635:E/ActivityThread(5963):位于java.lang.reflect.Method.Invokenactive(本机方法)
09-02 09:25:40.635:E/ActivityThread(5963):位于java.lang.reflect.Method.invoke(Method.java:511)
09-02 09:25:40.635:E/ActivityThread(5963):位于com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
09-02 09:25:40.635:E/ActivityThread(5963):位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
09-02 09:25:40.635:E/ActivityThread(5963):位于dalvik.system.NativeStart.main(本机方法)

任何帮助都将不胜感激。

您在
onCreate()
onResume()
中调用
doBindService()
,尝试在
onResume()
中调用它,以匹配您在
onPause()
中对
doUnbindService()
的调用。您需要为活动使用良好的参考 getActivity()返回当前的一个,您需要在执行绑定的一个上解除绑定

下面是我如何解决问题的:

private Activity mActivity;
    @Override
    public void onStart() {
        super.onStart();
        if (!mBound) {
            startService();
            mActivity = getActivity();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mBound && mActivity != null) {
            mActivity.unbindService(mServiceConnection);
            mActivity = null;
        }
    }

onCreate()
中调用
doBindService()
时,应在
onDestroy()中添加do
UnbindService()


这对我来说很有效。

您会收到此错误,因为您与活动绑定的服务在该活动销毁时不会停止。因此,由于这个原因,您的服务仍然存在于内存中,并且正在消耗资源,而这并没有起到任何作用


要解决此问题,请在
onCreate()
中调用
doBindService()
,并在
onDestroy()中调用
doUnbindService()。在Android O中,引入了以下启动前台服务的功能,而不是
context.startService(…)
。较旧的API不处理前台生命周期,因此需要在
onDestroy(…)
中调用
context?.unbindService(serviceConnection)

新方法确保开发人员必须在调用
ContextCompat.startForegroundService(…)
的五秒钟内创建一个带有
startForeground(notificationId,notification)
的通知,以确保用户即使在应用程序不在视图中也能意识到前台服务正在运行

对于任何运行牛轧糖API级别25或更低的设备,请确保手动解除服务绑定

ie

override fun onDestroy() {
    if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.N_MR1) 
        context?.unbindService(serviceConnection)
}
override-fun-ondestory(){

如果(android.os.Build.VERSION.SDK_INT)我刚刚尝试了这个方法,但没有成功,Logcat现在会指向onResume()中的doBindService。无论如何,我不认为这是一个问题,因为我的布尔人应该确保调用不会同时发生。doBindService同时出现在这两种情况下,以确保a)服务