1

在我的开始活动中,我调用FontFactory.init(getApplicationContext());将 Context 设置为 FontFactory 类。

我也有扩展的类,TextView并且在这个 TextView 的构造函数中有setTypeface(FontFactory.Fonts.ROBOTO_LIGHT.getFont());. 因此,文件中的字体在首次需要时加载,而不是在启动期间加载。

问题是只有有时,而不是每次都会出现启动错误和应用程序崩溃:

InflateException: Binary XML file line .. - 错误膨胀类 LayoutWithExtendedTextView

由字体 nativeCreateFromAsset、createFRomAsset 和 FontFactory.loadFont(FontFactory.java:46) 中的 NullPointerException 引起

第 46 行是return Typeface.createFromAsset(assetManager, fontEnum.getPath());

我的字体工厂类:

public final class FontFactory {

    public enum Fonts {
        ROBOTO_CONDENSED("fonts/Roboto-Condensed.ttf"), ROBOTO_LIGHT(
                "fonts/Roboto-Light.ttf"), ROBOTO_MEDIUM(
                "fonts/Roboto-Medium.ttf"), ROBOTO_REGULAR(
                "fonts/Roboto-Regular.ttf");

        private String path;
        private Typeface loadedFont = null;

        private Fonts(String path) {
            this.path = path;
        }

        public String getPath() {
            return path;
        }

        public void setLoadedFont(Typeface font) {
            this.loadedFont = font;
        }

        public Typeface getFont() {
            if (loadedFont == null) {
                this.loadedFont = FontFactory.loadFont(this);
            }
            return loadedFont;
        }
    }

    private static final String TAG = "FontFactory";
    private static AssetManager assetManager;

    public static void init(Context context) {
        assetManager = context.getAssets();
    }

    private static Typeface loadFont(FontFactory.Fonts fontEnum) {
        return Typeface.createFromAsset(assetManager, fontEnum.getPath());
    }
}

加载资产时是否有一些延迟?

谢谢你。

4

1 回答 1

1

方法 createFromAsset调用nativeCreateFromAsset 它是本机 C++ 代码。

static JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
{ "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
{ "nativeUnref",              "(I)V",  (void*)Typeface_unref },
{ "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
{ "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
                                       (void*)Typeface_createFromAsset },
{ "nativeCreateFromFile",     "(Ljava/lang/String;)I",
                                       (void*)Typeface_createFromFile }
};

通过代码挖掘,我发现了以下Typeface_createFromAsset的实现。

static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
                                        jobject jassetMgr,
                                        jstring jpath) {

NPE_CHECK_RETURN_ZERO(env, jassetMgr);
NPE_CHECK_RETURN_ZERO(env, jpath);

AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
if (NULL == mgr) {
    return NULL;
}

AutoJavaStringToUTF8    str(env, jpath);
Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
if (NULL == asset) {
    return NULL;
}

return SkTypeface::CreateFromStream(new AssetStream(asset, true));
}

该方法在以下两种情况下返回 null:

  • 一、提供的资产管理器为空
  • 其次,它无法从文件系统创建负载资产。

此外,仅针对某些人阅读问题“无法制作原生字体”,该问题可能提供有关该问题的最完整信息(不值得在此处复制/粘贴)

于 2014-09-05T10:32:45.043 回答