Activity中bindService和registerReceiver的清理工作

原文地址为: Activity中bindService和registerReceiver的清理工作

在Android开发中,我们经常需要注册BroadcastReceiver和bind service。

接口函数如下:

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter);

public void unregisterReceiver(BroadcastReceiver receiver);

public boolean bindService(Intent service, ServiceConnection conn, int flags);

public void unbindService(ServiceConnection conn);


有的时候,用户只调用了注册函数,或者是bind service,而忘记了unregisterReceiver和unbindService。这时,在Activity退出的时候,会自动这些问题,自动调用unregisterReceiver和unbindService。具体的流程如下:

    private void handleDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
        ActivityClientRecord r = performDestroyActivity(token, finishing,
                configChanges, getNonConfigInstance);        回调Activity的onDestroy
        if (r != null) {
            // Mocked out contexts won't be participating in the normal
            // process lifecycle, but if we're running with a proper
            // ApplicationContext we need to have it tear down things
            // cleanly.
            Context c = r.activity.getBaseContext();
            if (c instanceof ContextImpl) {
                ((ContextImpl) c).scheduleFinalCleanup(
                        r.activity.getClass().getName(), "Activity");     清理 注册的receiver和bind的service
            }
        }
        if (finishing) {
            try {
                ActivityManagerNative.getDefault().activityDestroyed(token);     通知AMS,activity已经destroy
            } catch (RemoteException ex) {
                // If the system process has died, it's game over for everyone.
            }
        }
        mSomeActivitiesChanged = true;
    }


In ContextImpl.java

    final void scheduleFinalCleanup(String who, String what) {
        mMainThread.scheduleContextCleanup(this, who, what);
    }


In ActivityThread.java

    final void scheduleContextCleanup(ContextImpl context, String who,
            String what) {
        ContextCleanupInfo cci = new ContextCleanupInfo();
        cci.context = context;
        cci.who = who;
        cci.what = what;
        sendMessage(H.CLEAN_UP_CONTEXT, cci);
    }

                case CLEAN_UP_CONTEXT:
                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
                    cci.context.performFinalCleanup(cci.who, cci.what);
                    break;


In ContextImpl.java

    final void performFinalCleanup(String who, String what) {
        //Log.i(TAG, "Cleanup up context: " + this);
        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
    }


In LoadedApk.java

    public void removeContextRegistrations(Context context,
            String who, String what) {
        final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =  mReceivers.remove(context);
        if (rmap != null) {
            for (int i=0; i<rmap.size(); i++){      清理所有已经注册的receiver
                LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
                IntentReceiverLeaked leak = new IntentReceiverLeaked(
                        what + " " + who + " has leaked IntentReceiver "
                        + rd.getIntentReceiver() + " that was " +
                        "originally registered here. Are you missing a " +
                        "call to unregisterReceiver()?");
                leak.setStackTrace(rd.getLocation().getStackTrace());
                Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
                if (reportRegistrationLeaks) {
                    StrictMode.onIntentReceiverLeaked(leak);
                }
                try {
                    ActivityManagerNative.getDefault().unregisterReceiver(
                            rd.getIIntentReceiver());
                } catch (RemoteException e) {
                    // system crashed, nothing we can do
                }
            }
        }
        mUnregisteredReceivers.remove(context);
        //Slog.i(TAG, "Receiver registrations: " + mReceivers);

        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
            mServices.remove(context);
        if (smap != null) {
            for (int i=0; i<smap.size(); i++) {        解绑定已经bind的service
                LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
                ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
                        what + " " + who + " has leaked ServiceConnection "
                        + sd.getServiceConnection() + " that was originally bound here");
                leak.setStackTrace(sd.getLocation().getStackTrace());
                Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
                if (reportRegistrationLeaks) {
                    StrictMode.onServiceConnectionLeaked(leak);
                }
                try {
                    ActivityManagerNative.getDefault().unbindService(
                            sd.getIServiceConnection());
                } catch (RemoteException e) {
                    // system crashed, nothing we can do
                }
                sd.doForget();
            }
        }
        mUnboundServices.remove(context);
        //Slog.i(TAG, "Service registrations: " + mServices);

    }


转载请注明本文地址: Activity中bindService和registerReceiver的清理工作

猜你喜欢

转载自blog.csdn.net/hong2511/article/details/80958897