Android 字体内存泄露

字体需求

在App开发中,一般都会使用自定义的字体,这些字体美化App的同时,可能还会带来额外的问题,最容易带来的问题就是内存泄露,这里举个实际中遇到的问题作为例子

上面的UI,我们需要在Title、Price上做自定义字体。假如我们这么处理这个需求

  • Title
Typeface tf=Typeface.createFromAsset(getAssets(), Consts.LANTING_FONT_PATH);
title.setTypeface(tf);
  • Price
Typeface tf=Typeface.createFromAsset(getAssets(), Consts.LANTING_FONT_PATH);
price.setTypeface(tf);

像上面这么处理,进入这个页面以后,在滚动View的时候会明显卡顿 1S左右, 用户体验相当不好。

接下来看看问题在哪里

跑monkey测试:

发现问题

adb shell dumpsys meminfo 【packgename】

此命令会打出当前应用内存占用情况,如下:

注意很明显的/assets/fonts/fzlthjw.ttf 出现的N多次,而且每次都是2,M多,这个内存占用相当的恐怖了,很明显出现了内存泄露

那么该如何解决?

解决问题

解决的办法比较简单,因为 Typeface.createFromAsset(…)是个高消耗方法,缓存使用即可。

比如像这样:

protected static final Typeface TYPEFACE = Typeface.createFromAsset(
            application.getAssets(), "fonts/fzlthjw.ttf");  

titile.setTypeface(TYPEFACE );
price.setTypeface(TYPEFACE );

然后我们再次用monkey测试一下:

问题得以解决

推荐方法

不过建议上面的Typeface用Manager管理起来,防止不恰当使用引起内存泄露,下面给个简单的Manager类以供参考:

import java.util.HashMap;
import java.util.Map;
import android.app.Application;
import android.content.res.AssetManager;
import android.graphics.Typeface;
public class FontManager {
    private static FontManager FONT_MANAGER;
    private AssetManager mAssetManager;
    private static final Map<String, Typeface> CACHE_FONT_MAP = new HashMap<String, Typeface>();
    private FontManager(Application application) {
        mAssetManager = application.getAssets();
    }
    public static void createInstance(Application application) {
        if (FONT_MANAGER == null) {
            synchronized (FontManager.class) {
                if (FONT_MANAGER == null) {
                    FONT_MANAGER = new FontManager(application);
                }
            }
        }
    }
    public static FontManager getInstance() {
        if (FONT_MANAGER == null) {
            throw new NullPointerException("NullPoint Exception, Please call createInstance first!");
        }
        return FONT_MANAGER;
    }
    public Typeface getFont(FontType type) {
        if (type == null) {
            return null;
        }
        final String key = type.getValue();
        Typeface typeface = null;
        switch (type) {
        case TANG_SH:
            if (CACHE_FONT_MAP.containsKey(key)) {
                return CACHE_FONT_MAP.get(key);
            } else {
                typeface = Typeface.createFromAsset(mAssetManager, "fonts/fzlthjw.ttf");
                CACHE_FONT_MAP.put(key, typeface);
            }
            break;
        default:
            break;
        }
        return typeface;
    }
    public static enum FontType {
        TANG_SH("tang_sh");
        String value;
        FontType(String value) {
            this.value = value;
        }
        public String getValue() {
            return value;
        }
    }
    // -----------------------------------------------------------------------
    // Convenient
    // -----------------------------------------------------------------------
    public static class FLFont {
        public static Typeface getFont(FontType type) {
            try {
                FontManager manager = FontManager.getInstance();
                return manager.getFont(type);
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

调用的时候在Application中初始化一次

FontManager.createInstance(this); 

然后在使用的时候:

title.setTypeface(FLFont.getFont(FontType.TANG_SH)) 

这样就可以全局避免内存泄露。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 12:37:48

Android 字体内存泄露的相关文章

Android App 内存泄露之Thread

Thread 内存泄露 线程也是造成内存泄露的一个重要的源头.线程产生内存泄露的主要原因在于线程生命周期的不可控. 1.看一下下面是否存在问题 <span style="white-space:pre"> </span>/** * * @version 1.0.0 * @author Abay Zhuang <br/> * Create at 2014-7-17 */ public class ThreadActivity extends Activ

Android App 内存泄露之调试工具(1)

Android App 内存泄露之工具(1) 使用内存监测工具 DDMS –> Heap 操作步骤 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的,没打开的直接Window>ShowView>自己选 将手机通过USB链接至电脑,链接时需要确认手机是处于"USB调试"模式 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息: 点击选中想要监测的进程,如果在进程列表中未出现你

Android App 内存泄露之Handler

Android App 内存泄露之Handler Handler也是造成内存泄露的一个重要的源头,主要Handler属于TLS(Thread Local Storage)变量,生命周期和Activity是不一致的 ,Handler引用Activity会存在内存泄露. 看一下如下代码 /** * * 实现的主要功能. * @version 1.0.0 * @author Abay Zhuang <br/> * Create at 2014-7-28 */ public class Handler

Android 常见内存泄露 &amp; 解决方案

前言 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃 (OOM) 等严重后果. 那什么情况下不能被回收呢? 目前 java 垃圾回收主流算法是虚拟机采用 GC Roots Tracing 算法.算法的基本思路是:通过一系列的名为 GC Roots (GC 根节点)的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径,当一个对象到GC Roots没有任何引用链相连(图论说:从GC Roots

如何用MAT分析Android应用内存泄露

使用工具:Android Studio 2.0 Preview, Android Device Monitor, MAT(Memory Analyzer). 点击Android Studio工具栏上的“Android Device Monitor”,如下图 打开后选中应用进程,然后点击“Update heap”,接着反复点击应用的每个activity,最后“Dump HPROF file”,如下图1-2-3所示 保存hprof文件. 下面需要对hprof文件进行转换. 打开CMD终端,进入到\s

Android Handler内存泄露

前言 在Android开发中,使用Handler的地方很多,大致通常写法如下: private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 1) { mAdapter.notifyDataSetChanged(); } }};这段代码看似没什么问题,但是里面却有一个警告,警告信息如下: This Handler class should

【转载】 Android App 内存泄露之Thread

转载地址http://blog.csdn.net/zhuanglonghai/article/details/37909553 Thread 内存泄露 线程也是造成内存泄露的一个重要的源头.线程产生内存泄露的主要原因在于线程生命周期的不可控. 1.看一下下面是否存在问题 <span style="white-space:pre"> </span>/** * * @version 1.0.0 * @author Abay Zhuang <br/> *

Android常见内存泄露,学会这六招优化APP性能

很多开发者都知道,在面试的时候会经常被问到内存泄露和内存溢出的问题. 1.内存溢出(Out Of Memory,简称 OOM),通俗理解就是内存不够,即内存占用超出内存的空间大小. 2.内存泄漏(Memory Leak),简单理解就是内存使用完毕之后本该垃圾回收却未被回收. 2 在正式了解内存泄露之前,首先来简单回顾一下 Java 内存分配策略. Java 程序运行时的内存分配策略有三种,分别是静态分配.栈式分配.堆式分配,对应的主要内存空间分别是静态存储区(也称方法区).栈区.堆区. 1.静态

Android中内存泄露与如何有效避免OOM总结

一.关于OOM与内存泄露的概念 我们在Android开发过程中经常会遇到OOM的错误,这是因为我们在APP中没有考虑dalvik虚拟机内存消耗的问题. 1.什么是OOM OOM:即OutOfMemoery,顾名思义就是指内存溢出了.内存溢出是指APP向系统申请超过最大阀值的内存请求,系统不会再分配多余的空间,就会造成OOM error.在我们Android平台下,多数情况是出现在图片不当处理加载的时候. Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会