Gson使用泛型
如果你的后端统一了返回结果的话, 那么可以用Gson解析带泛型成员的Bean, 但在这个过程中遇到了一个坑, 现记录如下:
// 返回结果格式如下
public class Result<T> {
private int code;
private String message;
private T data;
// 省略getter和setter
...
}
原来的实现是这样的:
public static <T> Result<T> fromJson(String json, Class<T> clazz) {
Gson gson = new Gson();
Type type = new TypeToken<Result<T>>(){}.getType();
return gson.fromJson(json, type);
}
但是上面的代码有问题, 在调试时发现data不会正常转化, 似乎是T失去了作用.
经查阅资料, 最后发现了原因和解决方案: https://www.jianshu.com/p/d62c2be60617
这是因为Java是泛型擦除的, 不像C++, 运行时是无法获得T的具体类型的, 所以自然就把data当成Object了. 因此, 我们只要手动把T的类型告诉Gson即可, 这里用了ParameterizedType 这个接口, 详情请看上面的文章.
private static class ParameterizedTypeImpl implements ParameterizedType {
private final Class<?> raw;
private final Type[] args;
public ParameterizedTypeImpl(Class<?> raw, Type... args) {
this.raw = raw;
this.args = args != null ? args : new Type[0];
}
@NonNull
@Override
public Type[] getActualTypeArguments() {
return args;
}
@NonNull
@Override
public Type getRawType() {
return raw;
}
@Override
public Type getOwnerType() {
return null;
}
}
public static <T> Result<T> fromJson(String json, Class<T> clazz) {
Gson gson = new Gson();
Type type = new ParameterizedTypeImpl(Result.class, clazz);
return gson.fromJson(json, type);
}
这样就没有问题啦~( •̀ ω •́ )✧
org.json如何判断null
在org.json中null被视为一个独特的类型(org.json.JSONObject#NULL), 它重载了toString方法并且返回”null”, 所以直接用getString只会得到”null”. 应该调用org.json.JSONObject#isNull(String)判断是否为空
Cannot add the same observer with different lifecycles
如果Lambda表达式中不使用外部变量或方法, 那么编译器会进行单例优化, 所以重复观察时使用了同一个observer对象, 导致此异常的发生.
解决方法也很简单:
- 不使用Lambda表达式, 把Lambda表达式里的代码抽到内部类中
- Lambda表达式内使用外部的非静态变量或方法
我选择第二种
参考自: https://juejin.cn/post/6934606974239637511
Android 9.0后在应用中使用http
从Android 9开始, 谷歌为安全起见, 应用默认是无法发起http请求的, 如果需要发送http请求, 需要在清单文件里进行配置:
第一种方式:
在清单文件的application标签中添加属性android:usesCleartextTraffic="true"
第二种方式:
在res目录下创建xml目录, 然后在里面新建network_security_config.xml, 写入以下内容:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
然后再在清单文件的application标签中添加属性android:networkSecurityConfig="@xml/network_security_config"
推荐第二种方式, 但是更推荐使用https
在Room库中删除符合指定条件的行
Room的@Delete注解只能删除指定的Entity, 若想根据条件删除可以用@Query然后在里面写自定义查询语句(神奇吧
@Query("DELETE FROM user WHERE id = :id")
void deleteById(int id);
ListView#setOnItemSelectedListener(AdapterView.OnItemSelectedListener)无效
在网上搜了一圈, 这个Listener好像只在焦点改变的时候才调用, 如果想监听选项点击应该用setOnItemClickListener
这里有详细的分析: https://www.jianshu.com/p/d11f86051c20
当然了, 能用RecyclerView就更好了
TextView中的超链接无法点击
需要调用TextView#setMovementMethod(LinkMovementMethod.getInstance())