Android车机开发——内存优化操作

一、MemoryManagerImpl(整个应用的内存"中枢神经系统")

它负责全面监控、协调和管理应用的内存使用情况,其核心目标是确保在内存资源有限的移动设备上,相机这一高资源消耗型应用能够稳定、流畅地运行,避免因内存不足(Out of Memory)而导致的崩溃、性能下降或功能中断,从而保障最终用户的拍摄体验。

1.响应系统级内存事件

该类通过实现 ComponentCallbacks2接口,具备了直接响应系统级内存事件的能力。当 Android 系统整体内存紧张时,会向应用发送 onTrimMemory(int level)回调。该类内部定义了一个关键状态数组 sCriticalStates,用于过滤出需要立即采取行动的严重内存压力信号(如 TRIM_MEMORY_RUNNING_CRITICAL)。一旦接收到这些信号,它便会主动通知所有监听者,触发应用内部的内存释放流程。同时,它还实现了 onLowMemory()方法,作为最后一道防线来应对极端的内存不足情况。

特性 onTrimMemory(int level) onLowMemory()
​精确度​ ​精细分级​ ​。系统会传入一个 level参数(如 TRIM_MEMORY_RUNNING_MODERATE),指明内存紧张的严重程度和应用的状态(前台、后台等)。 ​粗放紧急​​。没有分级,只有一个终极警告。
​严重程度​ 从"提醒"到"严重"不等。应用可以根据级别采取不同力度的释放策略。 ​最高级别​​。是系统在"万不得已"时发出的最后通牒。
​处理逻辑​ MemoryManagerImpl中,它只过滤处理最严重的几个状态(如 TRIM_MEMORY_RUNNING_CRITICAL),然后才触发 notifyLowMemory() 只要被调用,就​​无条件​ ​地触发 notifyLowMemory()
java 复制代码
    @Override
    public void onTrimMemory(int level) {
        for (int i = 0; i < sCriticalStates.length; ++i) {
            if (level == sCriticalStates[i]) {
                notifyLowMemory();
                return;
            }
        }
    }
java 复制代码
    @Override
    public void onLowMemory() {
        notifyLowMemory();
    }  
  private void notifyLowMemory() {
        synchronized (mListeners) {
            for (MemoryListener listener : mListeners) {
                listener.onLowMemory();
            }
        }
    }

2.监控应用内部的核心内存消耗源

除了响应系统事件,该类还通过实现 MediaSaver.QueueListener接口,监控应用内部的核心内存消耗源------媒体文件(照片、视频)的保存队列。当媒体保存队列已满(onQueueStatus(true)),意味着待处理的数据积压过多,内存消耗可能即将达到临界点,此时管理器会提前发出警告,通知相关组件暂停或减缓可能进一步消耗内存的操作(如连续拍摄),这是一种主动的、应用层的内部分级预警机制。

为了有效地分发这些内存状态信息,该类采用了观察者设计模式。它维护了一个监听器列表 (mListeners),允许应用中的其他组件(如相机控制器、图像处理模块等)注册为监听者。当内存状态发生变化时,无论是系统通知还是队列告警,它都会同步地遍历所有监听器并调用相应的回调方法(如 onLowMemory()onMemoryStateChanged),确保所有相关部分都能协同响应,实现统一的内存管理策略。

在内存分配策略上,该类的一个重要职责是计算并限制本地(Native)代码可以使用的最大内存量。它通过一个辅助方法 getMaxAllowedNativeMemory来实现此功能。该方法首先检查系统配置(Gservices)中是否存在预设的覆盖值,为调试和适配不同设备提供了灵活性。如果没有配置,则采用默认计算策略:获取应用可用的最大 Dalvik 堆内存(取常规 MemoryClass和大型 LargeMemoryClass中的最大值),并取其 70% (MAX_MEM_ALLOWED) 作为 Native 内存的上限。这 30% 的缓冲空间是为处理高分辨率照片、连拍或视频录制等特别耗内存的操作预留的,防止 Native 层耗尽所有内存而导致 Java 层崩溃。

最后,该类通过一个静态的 create(...)工厂方法对外提供实例化服务。这个方法确保了对象被正确且完整地"装配":它不仅创建了 MemoryManagerImpl 实例本身,还自动将其注册为系统的组件回调接收者,并将其设置为 MediaSaver 的队列监听器。这种设计将复杂的依赖设置和注册逻辑封装在内部,简化了外部的调用过程,保证了管理器在创建后立即处于完全工作状态。

二、MemoryQuery和MemoryManager

这两个Java类共同构成了Android相机应用中内存管理系统的两个关键层面,体现了清晰的职责分离和协作关系。

MemoryQuery类作为一个具体的数据查询工具,其核心作用是深入系统底层,通过ActivityManager和Debug.MemoryInfo等Android API来采集详细的内存使用数据。它能够获取包括可用内存、总内存、进程内存使用情况(PSS)、各组件内存分配以及系统内存阈值等一系列关键指标,并将这些数据转换为统一的键值对格式,为上层决策提供准确的数据支持。

另一方面,MemoryManager接口则扮演了管理协调者的角色,它并不直接处理数据采集,而是定义了一套内存管理的框架和规范。它通过监听器模式(MemoryListener)允许应用中的其他模块(如相机模块、图像处理模块)注册成为内存状态变化的观察者。当内存状态发生变化时,MemoryManager负责通知这些模块,使它们能够根据当前内存状况(如正常状态或低内存状态)调整自身行为,从而避免内存不足导致的应用崩溃。

java 复制代码
public interface MemoryManager {
    /**
     * Classes implementing this interface will be able to get updates about
     * memory status changes.
     */
    public static interface MemoryListener {
        /**
         * Called when the app is experiencing a change in memory state. Modules
         * should listen to these to not exceed the available memory.
         *
         * @param state the new state, one of {@link MemoryManager#STATE_OK},
         *            {@link MemoryManager#STATE_LOW_MEMORY},
         */
        public void onMemoryStateChanged(int state);

        /**
         * Called when the system is about to kill our app due to high memory
         * load.
         */
        public void onLowMemory();
    }

    /** The memory status is OK. The app can function as normal. */
    public static final int STATE_OK = 0;

    /** The memory is running low. E.g. no new media should be captured. */
    public static final int STATE_LOW_MEMORY = 1;

    /**
     * Add a new listener that is informed about upcoming memory events.
     */
    public void addListener(MemoryListener listener);

    /**
     * Removes an already registered listener.
     */
    public void removeListener(MemoryListener listener);

    /**
     * Returns the maximum amount of memory allowed to be allocated in native
     * code by our app (in megabytes).
     */
    public int getMaxAllowedNativeMemoryAllocation();

    /**
     * Queries the memory consumed, total memory, and memory thresholds for this app.
     *
     * @return HashMap containing memory metrics keyed by string labels
     *     defined in {@link MemoryQuery}.
     */
    public HashMap queryMemory();
}

两者之间的直接联系体现在MemoryManager接口中定义的queryMemory()方法,这个方法明确要求返回一个使用MemoryQuery中定义的标准键值格式的HashMap。这意味着任何实现了MemoryManager接口的具体类都需要依赖MemoryQuery或类似工具来获取标准化内存数据。这种设计使得系统能够保持高度模块化------MemoryQuery专注于数据准确性,而MemoryManager专注于状态管理和模块协调。

java 复制代码
public HashMap queryMemory() {
        // Get ActivityManager.MemoryInfo.
        int memoryClass = mActivityManager.getMemoryClass();
        int largeMemoryClass = mActivityManager.getLargeMemoryClass();
        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
        mActivityManager.getMemoryInfo(memoryInfo);
        long availMem = memoryInfo.availMem / BYTES_IN_MEGABYTE;
        long totalMem = memoryInfo.totalMem / BYTES_IN_MEGABYTE;
        long threshold = memoryInfo.threshold / BYTES_IN_MEGABYTE;
        boolean lowMemory = memoryInfo.lowMemory;

        // Get ActivityManager.RunningAppProcessInfo.
        ActivityManager.RunningAppProcessInfo info = new ActivityManager.RunningAppProcessInfo();
        ActivityManager.getMyMemoryState(info);

        // Retrieve a list of all running processes. Get the app PID.
        int appPID = Process.myPid();

        // Get ActivityManager.getProcessMemoryInfo for the app PID.
        long timestamp = SystemClock.elapsedRealtime();
        long totalPrivateDirty = 0L;
        long totalSharedDirty = 0L;
        long totalPSS = 0L;
        long nativePSS = 0L;
        long dalvikPSS = 0L;
        long otherPSS = 0L;

        if (appPID != 0) {
            int pids[] = new int[1];
            pids[0] = appPID;
            Debug.MemoryInfo[] memoryInfoArray = mActivityManager.getProcessMemoryInfo(pids);
            totalPrivateDirty = memoryInfoArray[0].getTotalPrivateDirty() / BYTES_IN_KILOBYTE;
            totalSharedDirty = memoryInfoArray[0].getTotalSharedDirty() / BYTES_IN_KILOBYTE;
            totalPSS = memoryInfoArray[0].getTotalPss() / BYTES_IN_KILOBYTE;
            nativePSS = memoryInfoArray[0].nativePss / BYTES_IN_KILOBYTE;
            dalvikPSS = memoryInfoArray[0].dalvikPss / BYTES_IN_KILOBYTE;
            otherPSS = memoryInfoArray[0].otherPss / BYTES_IN_KILOBYTE;
        }

        HashMap outputData = new HashMap();
        outputData.put(KEY_TIMESTAMP, new Long(timestamp));
        outputData.put(KEY_MEMORY_AVAILABLE, new Long(availMem));
        outputData.put(KEY_TOTAL_MEMORY, new Long(totalMem));
        outputData.put(KEY_TOTAL_PSS, new Long(totalPSS));
        outputData.put(KEY_LAST_TRIM_LEVEL, new Integer(info.lastTrimLevel));
        outputData.put(KEY_TOTAL_PRIVATE_DIRTY, new Long(totalPrivateDirty));
        outputData.put(KEY_TOTAL_SHARED_DIRTY, new Long(totalSharedDirty));
        outputData.put(KEY_MEMORY_CLASS, new Long(memoryClass));
        outputData.put(KEY_LARGE_MEMORY_CLASS, new Long(largeMemoryClass));
        outputData.put(KEY_NATIVE_PSS, new Long(nativePSS));
        outputData.put(KEY_DALVIK_PSS, new Long(dalvikPSS));
        outputData.put(KEY_OTHER_PSS, new Long(otherPSS));
        outputData.put(KEY_THRESHOLD, new Long(threshold));
        outputData.put(KEY_LOW_MEMORY, new Boolean(lowMemory));

        Log.d(TAG, String.format("timestamp=%d, availMem=%d, totalMem=%d, totalPSS=%d, " +
                "lastTrimLevel=%d, largeMemoryClass=%d, nativePSS=%d, dalvikPSS=%d, otherPSS=%d," +
                "threshold=%d, lowMemory=%s", timestamp, availMem, totalMem, totalPSS,
                info.lastTrimLevel, largeMemoryClass, nativePSS, dalvikPSS, otherPSS,
                threshold, lowMemory));

        return outputData;
    }

在实际运行中,这两个类协同工作形成了一个完整的内存管理闭环:系统内存状态变化首先被MemoryManager监控到,然后通过调用MemoryQuery的详细数据采集方法获取当前内存快照,最后MemoryManager根据这些数据判断是否需要触发状态变化通知,从而引导各个功能模块采取相应的内存优化措施。这种设计不仅确保了内存敏感型应用(如相机)的稳定运行,也为性能优化和问题排查提供了坚实的数据基础,充分体现了良好的软件架构设计原则。

相关推荐
2501_916766542 小时前
【Git学习】Git本地仓库基础命令
git·学习
与代码不die不休2 小时前
Numpy学习——创建ndarray的方法
学习·numpy
墨^O^2 小时前
软件测试开发知识笔记
笔记·学习·测试工具·单元测试·测试用例·压力测试·ab测试
LGL6030A2 小时前
Java学习历程21——集成框架与常用库函数
学习
赵得C3 小时前
软件设计师进阶知识点解析:分布式与数据应用考点精讲
java·开发语言·分布式·设计模式
冬夜戏雪3 小时前
【java学习】【12.10】【10/60】
学习
Digitally3 小时前
设置完成后,将数据从安卓设备传输到 iPhone
android·ios·iphone
独行soc3 小时前
2025年渗透测试面试题总结-276(题目+回答)
android·网络·python·安全·web安全·网络安全·渗透测试
代码游侠3 小时前
应用——文件I/O操作代码
linux·运维·c语言·笔记·学习·算法