Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 326|回复: 0

[默认分类] Activity中bindService和registerReceiver的清理工作

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-8 14:05:14 | 显示全部楼层 |阅读模式

    在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);
        }

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-28 20:26 , Processed in 0.378420 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表