Libgdx仿安卓R文件通过Id访问资源

    xiaoxiao2026-04-24  7



    博客已迁移:更多精彩内容尽在AyoCrazy.com



    在Libgdx开发过程中,对资源的引用是直接通过一个资源路径的字符串来获取的,这给我们开发过程中造成了很大的不便。例如我们修改了某个资源文件的路径后,编译器并不会报错,但是运行的时候却提示找不到这个文件,因为编译器无法判断这个资源路径是否为有效路径,这个时候我们需要手动去修改这个路径字符串,如果是一个两个倒还好,但如果是批量修改呢,又怎么保证路径不会输错。要解决这个问题,我们可以通过将资源路径与变量对应起来,因为编译器可以判断一个变量是否存在。于是,我们很容易想到Android中的R文件,每个资源对应一个整型id,通过id去访问资源。那么在Libgdx中我们同样可以采取类似的方式,手动生成一个R文件,通过访问R文件中的变量去访问资源。这也是很多libgdx开发者通用的做法。

    原理

    通过遍历资源目录(android工程下的assets文件夹),获取每个资源的路径,然后将这些资源路径储存为Java的一个String类型常量,那么用的时候就可以直接使用R文件中的这个常量就行了,如果资源发生变动,只需要重新生成一下R文件就行了,十分方便。

    好处

    有效防止路径拼写错误资源变动后,编译器会给予错误提示遍历文件夹为耗时操作,若遍历R文件则方便快速得多

    步骤

    1.在core工程下创建一个R文件的包和一个生成R文件的类

    如下图的包和AutoR类

    2.在AutoR类中写入生成R文件的代码

    package com.mytian.mypet.R; import java.io.File; import java.io.FileOutputStream; import java.util.Locale; import com.badlogic.gdx.utils.Array; /** * 自动生成R文件,在电脑上运行本程序,将会对assetPath路径下的所有文件进行遍历,生成R文件 * * @author AyoCrazy * */ public class AutoR { //这个路径是你android工程的assets文件夹路径 private String assetPath = "E:\\workspace\\MyPet\\mypet\\android\\assets"; public static void main(String[] args) { new AutoR().start(); } public void start() { Group root = new Group("R"); getFiles(root, new File(assetPath)); writeFiles(root); } // 写代码到R文件 private void writeFiles(Group group) { // 包名 String packName = getClass().getPackage().getName(); // R文件的路径 String RFilePath = assetPath.replace("\\android\\assets", "\\core\\src\\" + packName.replace(".", "\\") + "\\R.java"); // 生成包名代码 String head = "package " + packName + ";\n"; // 生成注释 String info = "\n/** 此文件为自动生成,请勿随意手动修改 */"; // 生成代码主体 String body = head + info + group.toString(); try { FileOutputStream os = new FileOutputStream(new File(RFilePath)); os.write(body.getBytes(), 0, body.getBytes().length); os.close(); } catch (Exception e) { e.printStackTrace(); } } // 递归遍历文件 private void getFiles(Group group, File parent) { File[] fs = parent.listFiles(); for (File f : fs) { String fileName = f.getName(); if (f.isDirectory()) { // 如果是目录,则创建一个Group并将其加入到父Group中 Group g = new Group(fileName); group.addGroup(g); // 此处递归 getFiles(g, f); } else { // 如果是文件,直接将文件名加入到父Group中 group.addFile(fileName); } } } private int index; /** 一个Group对应一个文件目录*/ private class Group { private String name;// 名字,一般为目录名,顶层为"R",此名字将用作R文件中的类名或内部类名 private Array<Group> groups = new Array<AutoR.Group>();// 子Group,对应子目录 private Array<String> fileNames = new Array<String>();// 文件名,只有名字,不包含后缀 private Group parent;// 父Group,对应其父目录 private String space = "";// 空格,用于格式化生成的java代码 public Group(String dirName) { name = dirName; } @Override public String toString() { String fileString = ""; for (String fileName : fileNames) { // 获取文件的输出路径 String outPath = (outPath() + "/" + fileName).substring(1);// 去除最前面的斜杠 // 生成单个变量的java代码 fileString += space + " public static final String " + fileName.toUpperCase(Locale.ENGLISH).replace(".", "_").replace("-", "_") + " = \"" + outPath + "\";\n"; System.out.println(">> " + (++index) + " <<------- " + outPath); } String groupString = ""; // 生成子Group的代码 for (Group g : groups) { groupString += g.toString(); } // 返回Group对应的类和变量的java代码 return "\n" + space + "public class " + name + " {\n" + fileString + groupString + space + "}\n"; } // 添加一个子Group private void addGroup(Group g) { groups.add(g); g.parent = this; g.space = space + " "; } // 添加一个文件 private void addFile(String fileName) { fileNames.add(fileName); } // 生成输出路径 private String outPath() { if (parent == null) { return ""; } else { return parent.outPath() + "/" + name; } } } }

    记得将变量assetPath的值该为你的android工程下的assets文件夹路径(绝对路径)。

    3.运行AutoR文件,并刷新第一步中创建的包

    点右键运行AutoR文件并刷新后,将会看到包下多了一个R文件。这个文件中就是自动生成的资源ID文件。 生成的文件如下格式:

    package com.mytian.mypet.R; /** 此文件为自动生成,请勿随意手动修改 */ public class R { public static final String BG_PNG = "bg.png"; public static final String GOBLINS_ATLAS = "goblins.atlas"; public static final String GOBLINS_JSON = "goblins.json"; public static final String GOBLINS_PNG = "goblins.png"; public static final String SKIN1_SKIN = "skin1.skin"; public static final String SKIN2_SKIN = "skin2.skin"; public class fonts { public static final String MINI_TTF = "fonts/mini.ttf"; } }

    R文件会自动为每个目录创建一个内部类,保持层级关系同资源目录中的一致。

    4.引用R文件中的资源ID来访问资源

    例如:

    // R文件中的访问方式 FileHandle fh1 = Gdx.files.internal(R.fonts.MINI_TTF); // 原始访问方式 FileHandle fh2 = Gdx.files.internal("fonts/mini.ttf");

    5.最后记得每次改动资源之后,都要重新运行运行AutoR文件,并刷新R文件

    结语

    相关资源:python入门教程(PDF版)
    最新回复(0)