简体   繁体   English

使用onRetainCustomNonConfigurationInstance进行服务泄漏

[英]Service Leaking with onRetainCustomNonConfigurationInstance

Problem 问题
In my Activity, my bound Service leaks. 在我的Activity中,我的绑定服务泄漏。 But this only happens after the first screen orientation change. 但这只发生在第一次屏幕方向改变之后。 On the second (and following) changes of the screen orientation, the service does not leak. 在屏幕方向的第二次(和以下)更改中,服务不会泄漏。 I can't unbind the service in onPause because the Service needs to run in foreground (if you unbind the service, foreground is stopped). 我无法在onPause取消绑定服务,因为服务需要在前台运行(如果取消绑定服务,前台停止)。 Also, after rotation, the service still works (I can still call methods of the service). 此外,在轮换后,服务仍然有效(我仍然可以调用服务的方法)。

Environment 环境
I am developing for midSdkVersion=8 and targetSdkVersion=18 and I am using the SupportActionBar . 我正在为midSdkVersion=8targetSdkVersion=18我正在使用SupportActionBar

Question
Is there a way to prevent the Service to leak? 有没有办法阻止服务泄漏? I didn't find anything that helps, yet. 我找不到任何有用的东西了。 Am I missing something? 我错过了什么吗?

Code
Relevant parts of MainActivity that extends ActionBarActivity from support library: 从支持库扩展ActionBarActivity的MainActivity的相关部分:

AbstractPlayerService mService;
private boolean mBound;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawer_layout);

    // Abstract Class that extends Service
    AbstractPlayerService service = (AbstractPlayerService) getLastCustomNonConfigurationInstance();

    if(service != null) { 
        this.mService = service;
        mBound = true;
    }else{
        // init..
    }


@Override
protected void onStart(){
    super.onStart();

    if(!mBound){
        // following line is line 170
        bindService(new Intent(getApplicationContext(), PlayerService.class), mConnection, Context.BIND_AUTO_CREATE);
    }
}


public ServiceConnection mConnection = new ServiceConnection() {

    public void onServiceConnected(ComponentName className, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
        mService = null;
    }
};


@Override
public Object onRetainCustomNonConfigurationInstance () {
    return mService;
}

LogCat logcat的

11-27 15:42:31.992: E/ActivityThread(25111): Activity de.malaka.player.MainActivity has leaked ServiceConnection de.malaka.player.MainActivity$1@4053fc20 that was originally bound here
11-27 15:42:31.992: E/ActivityThread(25111): android.app.ServiceConnectionLeaked: Activity de.malaka.player.MainActivity has leaked ServiceConnection de.malaka.player.MainActivity$1@4053fc20 that was originally bound here
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:938)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:833)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ContextImpl.bindService(ContextImpl.java:932)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
11-27 15:42:31.992: E/ActivityThread(25111):    at de.malaka.player.MainActivity.onStart(MainActivity.java:170)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.Activity.performStart(Activity.java:3817)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1624)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.os.Looper.loop(Looper.java:130)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.main(ActivityThread.java:3691)
11-27 15:42:31.992: E/ActivityThread(25111):    at java.lang.reflect.Method.invokeNative(Native Method)
11-27 15:42:31.992: E/ActivityThread(25111):    at java.lang.reflect.Method.invoke(Method.java:507)
11-27 15:42:31.992: E/ActivityThread(25111):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
11-27 15:42:31.992: E/ActivityThread(25111):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
11-27 15:42:31.992: E/ActivityThread(25111):    at dalvik.system.NativeStart.main(Native Method)

If you take a look at onRetainCustomNonConfigurationInstance in FragmentActivity source code you'll see that is calls Activity#onRetainNonConfigurationInstance and that method is deprecated since level 13. In your case you can very well remove that method since you're anyway binding in onStart ... and you MUST unbind in onStop : 如果您查看FragmentActivity源代码中的onRetainCustomNonConfigurationInstance ,您将看到调用Activity#onRetainNonConfigurationInstance并且该方法从13级开始不推荐使用。在您的情况下,您可以很好地删除该方法,因为您无论如何都在onStart绑定。你必须onStop取消绑定:

@Override
protected void onStop() {
    super.onStop();
    unbindService(mConnection);
}

According to Service foreground documentation , there is no direct connection between running a service in the foreground and having it as bounded or not. 根据服务前台文档 ,在前台运行服务与将其作为有界或无限制之间没有直接连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM