优化Android工程的资源管理

Part 1

首先,我们来看一张项目结构图,

图中标红的部分就是我们整个项目的核心部分,其中,

*java*目录存放的是我们所有的源代码,

*res*目录存放我们项目中需要用到的所有资源,包括布局(layout),图片 (drawable),字符串(strings),动画(anim)等等……

通常我们的项目都包括了多个模块,我们就拿微信来举例吧,首页(entrance)模块通常包含了登录(login)、注册(register)、找回密码(forgot-password)功能,进入到主页(dashboard)之后,又有四个大的功能模块,分别是微信(wechat)、通讯录(contact)、发现(discovery)、我(me)。然后在每个功能模块下又有更细化的功能模块,于是我们在定义我们的源代码结构时,我们可以建立类似这样的一个包结构:

当我们需要修改某个界面时,我们可以通过清晰的包结构快速定位到我们的源代码文件。那么对于我们的资源文件呢?

Part 2

对于我们资源文件,留给我们的选择看似不多。一般而言,资源文件的结构基本如下图所示,

我们将对应的资源放入到对应的目录下即可。通常为了将资源信息与实际的功能模块挂钩,狐狸君的做法是在命名上下功夫,例如对于字符串资源,狐狸君的命名习惯是页面_关键字,例如,

同样的规则也适用于布局文件及其他资源,例如,

一个合适的前缀可以将布局文件的功能描述清楚,假如当我们需要修改登录界面的UI时,我们打开layout目录看到fragment_login就知道这就是我们要找的内容了。狐狸君的一般命名习惯是,对于Activity/Fragment文件,加上activity_/fragment_前缀,对于抽取出来的复用布局,加上view_前缀,对于ListView/RecyclerView的Item布局,就加上item_前缀。这样在寻找对应文件时,可以通过前缀快速缩小寻找的范围,找到最终的布局文件。但是,这样就是最完美的解决方案了吗?

显然上述还不是最优方案。我们还是看上图,所有activity文件在上方,fragment文件按文件名排序依次在后面。通过这样的一个结构,我们还不能立即将fragment与它所属的activity建立一个层级关系,每一个Fragment分别是属于哪一个Activity呢?如果我们有一个朋友圈界面(fragment_moments.xml),它属于哪一个模块,是在发现里面,还是的里面?当我们的项目越来越庞大,功能越来越多,layout目录下的布局文件也会越来越多,全挤在这一个小小目录下,当我们需要寻找时,只能从上往下一个个浏览下来。这样的寻找效率是很低的,那怎么解决呢?我们只有一个layout目录,将布局文件放在别的地方又无法通过编译,出路在哪?

Part 3

可喜的是Gradle为我们的提供了应对这种情况的解决方案。对于代码我们可以创建包结构,对于资源文件,我们也可以!!

首先,我们需要确定我们需要创建的资源结构,根据我们的包结构,我们先创建几个对应的资源目录吧。在javares的父目录,也就是main目录下,我们创建几个全新的目录,

可以很明显看到上图中,res目录图标右下角有一个小标志,这个标志就意味着res目录现在是作为项目的资源目录而存在的。

然后我们需要在build.gradle文件(app目录下的gradle文件,不要找项目根目录下的gradle文件)里添加几行内容,

红框内的就是我们需要添加的主要内容,如果找不到soruceSets的相关内容,请将所有内容都添加上去。还要注意的一点是,千万不要忘了红框内的最后一行内容。因为系统之前是默认将res作为资源目录的,现在我们添加了新的资源目录之后,res目录将不再被默认,如果还是有资源内容在此目录下,请一定要将此行内容添加上去。这时候我们再重新build一下项目,

可以看到我们添加的所有目录图标下都有了和res目录一样的标志。现在,所有的新添加目录都将作为资源目录而存在了。

我们可以将原先res目录下的所有目录都复制到其他目录下,再将对应资源文件放入到相应文件夹下,这样我们的项目不仅针对代码有了一个清晰包结构,针对所有的资源文件,我们也将更加容易管理与查找了,再复杂的功能模块,通过此设置方式,都是小事一桩了!!

Tips:如果我们只想要为布局文件创建结构而忽略其他的资源的话,在res目录下,我们也可以只创建几个不同的layout目录,例如layout-entrance、layout-dash,然后将布局文件放入到每个目录下的layout文件下,problem solved!

0%