美文网首页
ComponentCallbacks调用

ComponentCallbacks调用

作者: leenpong | 来源:发表于2018-11-22 20:06 被阅读0次

前言:

今天在看Glide的源码的时候发现其在初始化的时候,注册了一个cb(ComponentCallbacks),想到Activity 等四大组件都实现了该cb接口,所以就看了源码其调用的逻辑和时间,下面简单分析

Glide源码

    glide = builder.createGlide(applicationContext);
    for (GlideModule module : manifestModules) {
      module.registerComponents(applicationContext, glide.registry);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide.registry);
    }

其中讲glide对象注册到了applicationcontext里面

    public void registerComponentCallbacks(ComponentCallbacks callback) {
        getApplicationContext().registerComponentCallbacks(callback);
    }

其中getApplicationContext()返回的是application对象

    public void registerComponentCallbacks(ComponentCallbacks callback) {
        synchronized (mComponentCallbacks) {
            mComponentCallbacks.add(callback);
        }
    }

从上面的代码可以知道将glide(实现了cb接口)添加到了当前的application对象里面。

那cb里面的接口是什么时候被触发的呢?

由于fragmenwork的代码比较复杂,本人只找到在ams里面发起的调用:
ActivityManagerService:

case GC_BACKGROUND_PROCESSES_MSG: {
                synchronized (ActivityManagerService.this) {
                    performAppGcsIfAppropriateLocked();
             

当系统发生gc后台进程的时候,会发这样一个消息,接下来就系代码调用堆栈了:

     */
    final void performAppGcsLocked() {
        final int N = mProcessesToGc.size();
        if (N <= 0) {
            return;
        }
        if (canGcNowLocked()) {
            while (mProcessesToGc.size() > 0) {
                ProcessRecord proc = mProcessesToGc.remove(0);
                if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
                    if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
                            <= SystemClock.uptimeMillis()) {
                        // To avoid spamming the system, we will GC processes one
                        // at a time, waiting a few seconds between each.
                        performAppGcLocked(proc);
                        scheduleAppGcsLocked();
                        return;
                    } else {
                        // It hasn't been long enough since we last GCed this
                        // process...  put it in the list to wait for its time.
                        addProcessToGcListLocked(proc);
                        break;
                    }
                }
            }

            scheduleAppGcsLocked();
        }
    }


final void performAppGcLocked(ProcessRecord app) {
        try {
            app.lastRequestedGc = SystemClock.uptimeMillis();
            if (app.thread != null) {
                if (app.reportLowMemory) {
                    app.reportLowMemory = false;
                    app.thread.scheduleLowMemory();
                } else {
                    app.thread.processInBackground();
                }
            }
        } catch (Exception e) {
            // whatever.
        }
    }


其中app.thread.scheduleLowMemory(),thread就是ActivityThread


        @Override
        public void scheduleLowMemory() {
            sendMessage(H.LOW_MEMORY, null);
        }


    case LOW_MEMORY:
          Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
                    handleLowMemory();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;



    final void handleLowMemory() {
        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);

        final int N = callbacks.size();
        for (int i=0; i<N; i++) {
            callbacks.get(i).onLowMemory();
        }

        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
        if (Process.myUid() != Process.SYSTEM_UID) {
            int sqliteReleased = SQLiteDatabase.releaseMemory();
            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
        }

        // Ask graphics to free up as much as possible (font/image caches)
        Canvas.freeCaches();

        // Ask text layout engine to free also as much as possible
        Canvas.freeTextLayoutCaches();

        BinderInternal.forceGc("mem");
    }'


###这个方法就是收集当前实现cb的接口,然后给上面的方法调用

   ArrayList<ComponentCallbacks2> collectComponentCallbacks(
            boolean allActivities, Configuration newConfig) {
        ArrayList<ComponentCallbacks2> callbacks
                = new ArrayList<ComponentCallbacks2>();

        synchronized (mResourcesManager) {
            final int NAPP = mAllApplications.size();
            for (int i=0; i<NAPP; i++) {
                callbacks.add(mAllApplications.get(i));
            }
            final int NACT = mActivities.size();
            for (int i=0; i<NACT; i++) {
                ActivityClientRecord ar = mActivities.valueAt(i);
                Activity a = ar.activity;
                if (a != null) {
                    Configuration thisConfig = applyConfigCompatMainThread(
                            mCurDefaultDisplayDpi, newConfig,
                            ar.packageInfo.getCompatibilityInfo());
                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
                        // If the activity is currently resumed, its configuration
                        // needs to change right now.
                        callbacks.add(a);
                    } else if (thisConfig != null) {
                        // Otherwise, we will tell it about the change
                        // the next time it is resumed or shown.  Note that
                        // the activity manager may, before then, decide the
                        // activity needs to be destroyed to handle its new
                        // configuration.
                        if (DEBUG_CONFIGURATION) {
                            Slog.v(TAG, "Setting activity "
                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
                        }
                        ar.newConfig = thisConfig;
                    }
                }
            }
            final int NSVC = mServices.size();
            for (int i=0; i<NSVC; i++) {
                callbacks.add(mServices.valueAt(i));
            }
        }
        synchronized (mProviderMap) {
            final int NPRV = mLocalProviders.size();
            for (int i=0; i<NPRV; i++) {
                callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
            }
        }

        return callbacks;
    }

由于四大组件分别是在这里被collect,所以不需要特定注册,从上面可以知道接下来就是调用四大组件的onlowMemory

Application:


    @CallSuper
    public void onLowMemory() {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ComponentCallbacks)callbacks[i]).onLowMemory();
            }
        }
    }

相关文章

  • ComponentCallbacks调用

    前言: 今天在看Glide的源码的时候发现其在初始化的时候,注册了一个cb(ComponentCallbacks)...

  • ComponentCallbacks2接口简介

    ComponentCallbacks2接口扩展自ComponentCallbacks回调接口,用以实现更细粒度的内...

  • Context registerComponentCallbac

    水一篇文章: 今天看Glide源码时看到glide实现了 ComponentCallbacks 接口,注册到了 A...

  • Glide总结

    Glide中实现了ComponentCallbacks2,并注册,所以glide可以在系统内存紧张时,回调appl...

  • 通过ComponentCallbacks2来接收onTrimMe

    我们在做app内存不足时,需要做一些内存释放的操作,以避免app卡顿,或者尽可能的延迟app存活时间,减少被系统回...

  • 对Lua ,C,C#互相调用的理解

    几种情况讨论 C调用Lua C调用C# C#调用C C#调用Lua Lua调用C Lua调用C# Lua调用C 本...

  • JS函数调用

    js 里函数调用有4种模式:方法调用、正常函数调用、构造器函数调用、apply/call 调用。无论哪种函数调用除...

  • iOS开发:调用打电话,发短信,打开网址

    调用 自带mail 调用 电话phone 调用 SMS 调用自带 浏览器 safari 调用phone可以传递号码...

  • Pintos源码学习进度(8)

    1.系统调用的基本过程 ①调用系统调用相关函数,在系统调用函数中调用syscall,在syscall中会调用i...

  • 织梦标签总汇

    关键描述调用标签: 模板路径调用标签: 网站标题调用标签: 栏目导航调用标签: 指定调用栏目标签: 频道栏目调用标...

网友评论

      本文标题:ComponentCallbacks调用

      本文链接:https://www.haomeiwen.com/subject/vrlrqqtx.html