欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Android动态获取资源ID之getIdentifier()

程序员文章站 2022-03-23 12:25:19
前言  再说getIdentifier()前,科普下什么是SDK:SDK(Software Development Kit)是软件开发工具包的意思,一般我们将一部分功能单独封装成一个库文件进行开发和维护,然后将库文件提供给第三方使用。1.应用场景描述  SDK都是基于AS进行功能开发的 ,因为要提供给别人使用,而AS作为库文件的最终产物就是.aar文件。SDK开发精髓就是麻烦自己方便别人。既然提供了AS库支持自然也要提供EC库的支持 ,但是EC它不支持aar文件,怎么办嘞,aar文件也是压缩包,将a...

前言

  再说getIdentifier()前,科普下什么是SDK:SDK(Software Development Kit)是软件开发工具包的意思,一般我们将一部分功能单独封装成一个库文件进行开发和维护,然后将库文件提供给第三方使用。

1.应用场景描述

  SDK都是基于AS进行功能开发的 ,因为要提供给别人使用,而AS作为库文件的最终产物就是.aar文件。SDK开发精髓就是麻烦自己方便别人。既然提供了AS库支持自然也要提供EC库的支持 ,但是EC它不支持aar文件,怎么办嘞,aar文件也是压缩包,将aar解压出来,把里面的classes.jar拷贝出来重命名,然后在Eclipse中依赖这个jar包,同时,SDK的资源文件、Assets相关也需要拷贝到Eclipse项目中。

1.1异常原因分析

将AS库放到EC工程里发生崩溃Caused by: android.content.res.Resources$NotFoundException:

经过分析找到了问题原因所在:举个例子,sdk用到 setContentView(R.layout.activity_main)这种方式展示布局, 当我们把资源文件拷贝到Eclipse,再编译apk的时候,资源文件会对应一个新的资源id,而aar中classes.jar里引用R中id的是不变的 也就是说在.aar文件中setContentView(2130903040),

到了EC中重新编译后aapt会重新赋予activity_main一个新的值,自然报找不到资源ID 的异常了 。要解决这个问题需要SDK动态的获取资源ID ,不能直接写死,查找过一些资料发现,谷歌提供了相关的API,可以通过资源名称获取资源id

  /**
     * Return a resource identifier for the given resource name.  A fully
     * qualified resource name is of the form "package:type/entry".  The first
     * two components (package and type) are optional if defType and
     * defPackage, respectively, are specified here.
     * 
     * <p>Note: use of this function is discouraged.  It is much more
     * efficient to retrieve resources by identifier than by name.
     * 
     * @param name The name of the desired resource.
     * @param defType Optional default resource type to find, if "type/" is
     *                not included in the name.  Can be null to require an
     *                explicit type.
     * @param defPackage Optional default package to find, if "package:" is
     *                   not included in the name.  Can be null to require an
     *                   explicit package.
     * 
     * @return int The associated resource identifier.  Returns 0 if no such
     *         resource was found.  (0 is not a valid resource ID.)
     */
    public int getIdentifier(String name, String defType, String defPackage) {
        return mResourcesImpl.getIdentifier(name, defType, defPackage);
    }

   API格式getIdentifier(“资源ID名称”,“资源类型”,“应用包名”)
   getIdentifier(“activity_main”,“layout”,“com.demo.xxxx”)

2.Demo示例

通过上面提供的官方API ,尝试写一个DEMO 验证下

在Activity中 调用封装好的getIdentifier(),看下动态获取的ID是否和R.layout.activity_main值一样

Android动态获取资源ID之getIdentifier()

布局文件R.layout.activity_main ,从AS工程R.class可以看到int类型的索引值2130903040

Android动态获取资源ID之getIdentifier()
动态获取的R.layout.activity_main 同样为2130903040

Android动态获取资源ID之getIdentifier()

2.1结论

ResourceUtils.getLayoutId(context,“activity_main”))等效于R.layout.activity_main

SDK是给第三方使用的,避免使用R.layout.main方式引用资源。而且在游戏SDK圈中,涉及到编译和反编译等技术多资源合并去重。

在三方使用的时候资源id经常会发生改变,如果还用R.layout.main方式会造成第三方接入难度 等很多不确定因素。

3. 工具类封装

import android.content.Context;
import java.lang.reflect.Field;

/**
 * @author sjr
 * Date 2020/7/16
 */
public class ResourceUtils {

	public static int getAnimId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "anim", context.getPackageName());
	}
	public static int getAnimatorId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "animator", context.getPackageName());
	}
	public static int getAttrId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "attr", context.getPackageName());
	}

	public static int getBoolId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "bool", context.getPackageName());
	}

	public static int getColorId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "color", context.getPackageName());
	}

	public static int getDimenId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "dimen", context.getPackageName());
	}

	public static int getDrawableId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "drawable", context.getPackageName());
	}

	public static int getId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "id", context.getPackageName());
	}

	public static int getIntegerId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "integer", context.getPackageName());
	}

	public static int getInterpolatorId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "interpolator", context.getPackageName());
	}

	public static int getLayoutId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "layout", context.getPackageName());
	}

	public static int getPluralsId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "plurals", context.getPackageName());
	}

	public static int getStringId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "string", context.getPackageName());
	}

	public static int getStyleId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "style", context.getPackageName());
	}

	public static int getStyleableId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "styleable", context.getPackageName());
	}

	public static int getXmlId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "xml", context.getPackageName());
	}

	public static int getMipmapId(Context context, String defType) {
		return context.getResources().getIdentifier(defType, "mipmap", context.getPackageName());
	}

	/**
     * 通过反射来读取int[]类型资源Id
     * @param context
     * @param name
     * @return
     */
    public static final int[] getResourceDeclareStyleableIntArray(Context context, String name) {
    	try {
    		Field[] fields2 = Class.forName(context.getPackageName() + ".R$styleable" ).getFields();
            for (Field f : fields2 ){
                if (f.getName().equals(name)){
                    int[] ret = (int[])f.get(null);
                    return ret;
                }
            }
        }
        catch (Throwable t){
        }
        return null;
    }

}

结语

 记录下自己的学习和工作经验,分享给有需要的人。如果有那里写的不对或者不理解,欢迎大家的指正。

本文地址:https://blog.csdn.net/baidu_31156101/article/details/107402888