起因
有这样一个需求 我们想把 原始uri中的scheme转换一下 你会怎么做
hehe://a/hehe?params=%7B%22url
转换成
haha://a/hehe?params=%7B%22url
直接replace显然是不合适的
经过
我们这样做
Uri originaluri = Uri.parse("hehe://a/hehe?params=%7B%22url");
Uri newuri = new Uri.Builder().scheme("haha")
.authority(originaluri.getAuthority())
.path(originaluri.getPath())
.query(originaluri.getQuery()).build();
Log.d("uri", newuri.toString());
看似很美好但是日志确实
haha://a/hehe?params%3D%7B%22url
可以看出query参数中的 = 被编码了 变成了%3D!
这显然不是我们想要的
分析
originaluri.getQuery()的返回结果是{"url
那我们需要分析
query(originaluri.getQuery()).build();
都做了啥?
最终会生成Part类作为uri的一个属性
new Part(encoded, decoded)
该类存放我们query参数中的编码数据和解码数据,其中encoded = NOT_CACHED ,decoded = {"url.
build()方法会返回HierarchicalUri类 我们看看该类的toString做了啥
String encodedAuthority = authority.getEncoded();
if (encodedAuthority != null) {
// Even if the authority is "", we still want to append "//".
builder.append("//").append(encodedAuthority);
}
String encodedPath = path.getEncoded();
if (encodedPath != null) {
builder.append(encodedPath);
}
if (!query.isEmpty()) {
builder.append('?').append(query.getEncoded()); //编码 把query的所有数据的编码了
}
String getEncoded() {
@SuppressWarnings("StringEquality")
boolean hasEncoded = encoded != NOT_CACHED;
return hasEncoded ? encoded : (encoded = encode(decoded));
}
builder.append('?').append(query.getEncoded());编码 由于没有缓存所以把query的解码数据编码了 所有 = 变成了 %3D
结果
如何解决呢?编码数据由缓存就可以了!
Uri originaluri = Uri.parse("hehe://a/hehe?params=%7B%22url");
Uri newuri = new Uri.Builder().scheme("haha")
.authority(originaluri.getAuthority())
.path(originaluri.getPath())
.encodedQuery(originaluri.getEncodedQuery()).build();
Log.d("uri", newuri.toString());
将 query改成encodedQuery就可以了
网友评论