Monday, February 8, 2021

Android Interpreter Pattern

1.定义

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

2.介绍

  • 解释器模式属于行为型模式。
  • 解释器模式提供了一种解释语言的语法或表达式的方式。
  • 解释器模式实际开发中很少用到。

5. 应用场景

  • 简单的语法需要解释时,如解释一个sql语句。
  • 一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-cd,有时是ab+c-d等,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。

6. 优点

  • 灵活的扩展性,想扩展语法规则时只需新增新的解释器就可以了。如上面的例子中,想增加乘除法,只想增加相应的解释类,并增加相应的表达式解释操作即可。

7. 缺点

  • 每一个文法都至少对应一个解释器,会产生大量的类,难于维护。
  • 解释器模式由于大量使用循环和递归,需要考虑效率的问题,而且调试也不方便。
  • 对于复杂的文法,构建其抽象语法树会显得异常繁琐。
  • 所以不推荐在重要的模块中使用解释器模式,维护困难。

8. Android中的源码分析

对于AndroidManifest.xml这个文件,我们是相当熟悉。实际上AndroidManifest.xml是由PackageManagerService使用了PackageParser这个类来解释的,这里面就用到了解释器模式。对于AndroidManifest.xml中的每一个标签,都有对应的类去保存相应的信息。

8.1 PackageParser的parseBaseApkCommon方法

基于Android 27的源码,不同版本的源码方法名可能不一样。

=======================================================================
    private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
                                       XmlResourceParser parser, int flags, String[] outError) 
            throws XmlPullParserException, IOException {
        //其他代码略
        if (tagName.equals(TAG_APPLICATION)) {
            //其他代码略
            if (!parseBaseApplication(pkg, res, parser, flags, outError)) {//解释application标签
                return null;
            }
        } else if (tagName.equals(TAG_OVERLAY)) {
            //其他代码略
        } else if (tagName.equals(TAG_KEY_SETS)) {
            if (!parseKeySets(pkg, res, parser, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
            if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_PERMISSION)) {
            if (!parsePermission(pkg, res, parser, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_PERMISSION_TREE)) {
            if (!parsePermissionTree(pkg, res, parser, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_USES_PERMISSION)) {
            if (!parseUsesPermission(pkg, res, parser)) {
                return null;
            }
        } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
                || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
            if (!parseUsesPermission(pkg, res, parser)) {
                return null;
            }
        } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
            //其他代码略
        } else if (tagName.equals(TAG_USES_FEATURE)) {
            //其他代码略
        } else if (tagName.equals(TAG_FEATURE_GROUP)) {
            //其他代码略
        } else if (tagName.equals(TAG_USES_SDK)) {
            //其他代码略
        } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
            //其他代码略
        } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
            //其他代码略
        } else if (tagName.equals(TAG_INSTRUMENTATION)) {
            //其他代码略
        } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
            //其他代码略
        } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
            //其他代码略
        } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
            //其他代码略
        } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
            //其他代码略
        } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
            //其他代码略
        } else if (tagName.equals(TAG_EAT_COMMENT)) {
            //其他代码略
        } else if (tagName.equals(TAG_PACKAGE)) {
            //其他代码略
        } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
            //其他代码略
        } else if (RIGID_PARSER) {
            //其他代码略
        } else {
            //其他代码略
        }
    }
=======================================================================

从上面代码可以看到,就是对各个标签的内容进行解释。我们再来看看parseBaseApplication这个方法,这个是对Application进行解释。

8.2 parseBaseApplication方法

=======================================================================
    private boolean parseBaseApplication(Package owner, Resources res,
                                         XmlResourceParser parser, int flags, String[] outError)
            throws XmlPullParserException, IOException {

        //其他代码略
        String tagName = parser.getName();
        if (tagName.equals("activity")) {//解释activity
            Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
                    owner.baseHardwareAccelerated);
            //其他代码略

        } else if (tagName.equals("receiver")) {//解释receiver
            Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
                    true, false);
            //其他代码略

        } else if (tagName.equals("service")) {//解释service
            Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
            //其他代码略

        } else if (tagName.equals("provider")) {//解释provider
            Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
            //其他代码略

        } else if (tagName.equals("activity-alias")) {
            Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
            //其他代码略

        } else if (parser.getName().equals("meta-data")) {
            //其他代码略
        } else if (tagName.equals("static-library")) {
            //其他代码略
        } else if (tagName.equals("library")) {
            //其他代码略

        } else if (tagName.equals("uses-static-library")) {
            if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
                return false;
            }

        } else if (tagName.equals("uses-library")) {
            //其他代码略

        } else if (tagName.equals("uses-package")) {
            //其他代码略
        } else {
            //其他代码略
        }
        //其他代码略

        return true;
    }
=======================================================================
可以看到,上面有对activityreceiverservice等标签的解释,activity的具体解释在parseActivity这个方法里面,有兴趣的可以自行去看下,这里就不细说了,同时可以看到receiver也是在parseActivity这个方法中解释。

Reference:
https://www.jianshu.com/p/234a156b0210

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能