在Android中少不了去获取资源文件,在Android里封装了几种获取固定Resource文件的方式,今天不讲这个。
如果你要获取资源文件夹raw目录下的视频文件,那你会怎么做? 这时候Uri就排上用场了
我在这先设个疑问,通过Uri去拿raw文件夹下的mbg_unlock资源,以下哪种是正确的Uri呢?
- Uri uri = ("://" + getPackageName() + "/raw/mbg_unlock" );
- Uri uri = ("://" + getPackageName() + "/raw/" +.mbg_unlock);
- Uri uri = ("://" + getPackageName() + "/" +.mbg_unlock);
- Uri uri = ("://" + getPackageName() + "/xxxx/mbg_unlock" );
当你尝试以后你会发现,这四种都可以!是不是很神奇、很惊讶、是不是得说一句妈卖批,哈哈
读者可能会问了,前三种我还稍微可以理解,第四种也太无语了吧!别着急,我来给你解释为什么这四张都可以。
在Android中涉及Uri的操作一定少不了 这个类,而这个类就是我们所要找的那个关键类,如果不懂这个类是做什么的读者可以自己查一下。
通过debug在 中找到 getResourceId() 方法的这段代码,就是问题的关键。我来带大家解读一下
/**
* Resolves an URI to a {@link Resources} and a resource id.
*
* @hide
*/
public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
String authority = ();
Resources r;
if ((authority)) {
throw new FileNotFoundException("No authority: " + uri);
} else {
try {
r = ().getResourcesForApplication(authority);
} catch (NameNotFoundException ex) {
throw new FileNotFoundException("No package found for authority: " + uri);
}
}
List<String> path = (); //对Uri包名后面根据 '/' 进行切割
if (path == null) {
throw new FileNotFoundException("No path: " + uri);
}
int len = ();
int id;
if (len == 1) { //如果包名后面的 '/'只有一个,就直接看看是不是int型的 id ,后面代码就直接根绝这个id调用native方法进行了资源查找。这也就解释了例3可以通过。
try {
id = ((0));
} catch (NumberFormatException e) {
throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
}
} else if (len == 2) { //如果有两个,则调用了这个方法。下面有这个代码源码
id = ((1), (0), authority);
} else { //如果是其他数量,则直接抛异常
throw new FileNotFoundException("More than two path segments: " + uri);
}
if (id == 0) {
throw new FileNotFoundException("No resource found for: " + uri);
}
OpenResourceIdResult res = new OpenResourceIdResult();
= r;
= id;
return res;
}
下面的是getIdentifier((1), (0), authority)的源码:
int getIdentifier(String name, String defType, String defPackage) {
if (name == null) {
throw new NullPointerException("name is null");
}
try {
return (name); //直接对包名后面的的第二个'/'后面的部分进行判断是不是int型,如果是的话直接返回,然后进行native方法取资源。这也解释了为什么例2和例4都可以通过。
} catch (Exception e) {
// Ignore
}
return (name, defType, defPackage); //这段代码是个native方法,系统根绝资源文件名进行查找到资源所对应的id,然后返回。这也说明了例1为什么能通过了。
}
在上面代码里面注释部分,对上满的问题进行了一一解答。应该可以解决读者的疑惑了吧,如果还是不是很懂可以自己动手debug试试~