android开发小贴士

1.使用Glide库提取视频帧

图片加载框架Glide就可以做到获取本地视频的缩略图(不能获取网络视频文件):

1
2
3
4
5
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
Glide
.with( context )
.load( Uri.fromFile( new File( filePath ) ) )
.into( imageViewGifAsBitmap );
泛型相关
通过反射获取一个Field对象的泛型类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 /**
* 获取某一个字段上面的泛型参数数组,典型的就是获取List对象里面是啥参数
*
* @param f
* @return
*/
public static Class<?>[] getParameterizedType(Field f) {
// 获取f字段的通用类型
Type fc = f.getGenericType(); // 关键的地方得到其Generic的类型
// 如果不为空并且是泛型参数的类型
if (fc != null && fc instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) fc;
Type[] types = pt.getActualTypeArguments();
if (types != null && types.length > 0) {
Class<?>[] classes = new Class<?>[types.length];
for (int i = 0; i < classes.length; i++) {
classes[i] = (Class<?>) types[i];
}
return classes;
}
}
return null;
}
TypeToken

解析泛型Json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//构造泛型Json
List<Map<Integer, String>> list = new ArrayList();
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "111111111");
list.add(map);
for (int i = 0; i < 10; i++){
HashMap<Integer, String> map1 = new HashMap<>();
map1.put(i, String.valueOf(i*1000));
list.add(map1);
}
Gson gson = new Gson();
String str = gson.toJson(list);
Log.i(TAG, "str:" + str);

//解析泛型Json
Type type = new TypeToken<List<Map>>() {
}.getType();
List<Map> myList = gson.fromJson(str, type);
if (list != null) {
for (Map<Integer, String> bean : list) {
for (Map.Entry<Integer, String> entry : bean.entrySet()) {
Log.i(TAG, "key = " + entry.getKey() + ";value = " + entry.getValue());
}
}
}
ParameterizedType

假设不只一个json数组字符串需要你解析,很显然重复的代码应该抽象成一个方法。 关于Student的数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
{
"name": "zhaoxa",
"score": 100
},
{
"name": "zhaoxa2",
"score": 76
},
{
"name": "zhaoxa3",
"score": 99
},
{
"name": "zhaoxa4",
"score": 48
}
]

关于Book的数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
{
"author": "zhaoxa",
"name": "如何入门android",
"price": 100
},
{
"author": "zhaoxa2",
"name": "如何入门android2",
"price": 76
},
{
"author": "zhaoxa3",
"name": "如何入门android3",
"price": 99
},
{
"author": "zhaoxa4",
"name": "如何入门android4",
"price": 48
}
]

抽象一个泛型的方法出来,把json数组字符串转化成类。

第一次尝试

1
2
3
4
5
public <T> List<T> parseString2List(String json){
T[] array = new Gson().fromJson(json, T[].class);
List<T> list = Arrays.asList(array);
return list;
}

报错了,fromJson不支持使用泛型解析。

第二次尝试

1
2
3
4
5
public <T> List<T> parseString2List(String json) {
Type type = new TypeToken<List<T>>(){}.getType();
List<T> list = new Gson().fromJson(jsonString,type);
return list;
}

嗯,没有报错,我们运行时断点看看list里的数据类型。

我们通过这句话调用方法:

1
List<Student> list = parseString2List(jsonString);

可以看到,list中的数据类型不是Student,而是LinkedTreeMap,LinkedTreeMap是Gson库内部数据模型,换句话说我们的解析失败了,尝试着将parseString2List方法中的泛型T去掉,运行结果一样,说明Gson解析时不支持泛型。

第三次尝试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public <T> List<T> parseString2List(String json,Class clazz) {
Type type = new ParameterizedTypeImpl(clazz);
List<T> list = new Gson().fromJson(json, type);
return list;
}

private class ParameterizedTypeImpl implements ParameterizedType {
Class clazz;

public ParameterizedTypeImpl(Class clz) {
clazz = clz;
}

@Override
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}

@Override
public Type getRawType() {
return List.class;
}

@Override
public Type getOwnerType() {
return null;
}
}

在调用的地方使用:

1
2
List<Student> list = parseString2List(jsonString, Student.class);
List<Book> list2 = parseString2List(jsonString, Book.class);

现在在回过头来看看,ParameterizedType的几个方法的含义吧,以HashMap<String,Integer>为例。

  • getActualTypeArguments 返回实际类型组成的数据,即new Type[]{String.class,Integer.class}
  • getRawType 返回原生类型,即 HashMap
  • getOwnerType 返回 Type 对象,表示此类型是其成员之一的类型。例如,如果此类型为 O.I,则返回 O 的表示形式。 如果此类型为顶层类型,则返回 null。这里就直接返回null就行了。
坚持原创技术分享,您的支持将鼓励我继续创作!