我传递了一个Uri.Builder对象,作为子类在Android中执行Uri之前向其填充任何必要参数的机制。
问题是,基类使用builder.appendQueryParameter("q",searchPhrase);
添加的一个参数需要在子类中替换,但我只能找到appendQueryParameter()
,没有替换或设置方法。具有相同参数名称的appendQueryParameter()
添加了该参数的另一个实例,而不是替换它
我应该放弃并尝试另一种方式吗?或者有没有办法替换我还没有找到的查询参数?
由于没有内置方法,我找到的最好方法是构建一个新的Uri。迭代旧Uri的所有查询参数,然后用新值替换所需的键。
private static Uri replaceUriParameter(Uri uri, String key, String newValue) {
final Set<String> params = uri.getQueryParameterNames();
final Uri.Builder newUri = uri.buildUpon().clearQuery();
for (String param : params) {
newUri.appendQueryParameter(param,
param.equals(key) ? newValue : uri.getQueryParameter(param));
}
return newUri.build();
}
这将添加一个参数,或替换Kotlin中现有参数的值。
Uri的扩展:
fun Uri.addUriParameter(key: String, newValue: String): Uri {
val params = queryParameterNames
val newUri = buildUpon().clearQuery()
var isSameParamPresent = false
for (param in params) {
// if same param is present override it, otherwise add the old param back
newUri.appendQueryParameter(param,
if (param == key) newValue else getQueryParameter(param))
if (param == key) {
// make sure we do not add new param again if already overridden
isSameParamPresent = true
}
}
if (!isSameParamPresent) {
// never overrode same param so add new passed value now
newUri.appendQueryParameter(key,
newValue)
}
return newUri.build()
}
实施:
val appendedURL = originalUri.addUriParameter("UID","123456")
@bmjohns建议的更简洁的方法。
fun Uri.addUriParameter(key: String, newValue: String): Uri =
with(buildUpon()) {
clearQuery()
queryParameterNames.forEach {
if (it != key) appendQueryParameter(it, getQueryParameter(it))
}
appendQueryParameter(key, newValue)
build()
}
/*
* Append or replace query parameters
*/
fun Uri.Builder.addQueryParameters(uri: Uri, params: Map<String, String>) = apply {
if (uri.query == null) {
appendQueryParameters(params)
} else {
clearQuery()
appendQueryParameters(params)
val names = params.keys
uri.queryParameterNames.forEach {
if (it !in names) appendQueryParameter(it, uri.getQueryParameter(it))
}
}
}
fun Uri.Builder.appendQueryParameters(params: Map<String, String>) = apply {
params.forEach { name, value ->
appendQueryParameter(name, value)
}
}
我以前也遇到过同样的问题,决定换一种方式。
制作一个包装类,并将查询(比如setQueryParameter(key, value)
)存储在Map
(或者ArrayMap
,类似的东西)中。
然后包装器实例的build()
方法处理原始Builder
的appendQueryParameter()
和build()
带UrlQuerySanitizer
-
val sanitizer = UrlQuerySanitizer(serviceUrl)
val paramVal = sanitizer.getValue("byCustomValue")
val replacedUrl = serviceUrl.replace(paramVal, "REPLACE_HERE")
这里有一个简单的方法来编码一个特定的参数-
fun encodeParameter(url: String, key: String): String {
val sanitizer = UrlQuerySanitizer(url)
return if (sanitizer.hasParameter(key)) {
val paramValue = sanitizer.getValue(key)
val encodedValue = try {
URLEncoder.encode(paramValue, "utf-8")
} catch (e: UnsupportedEncodingException) {
paramValue
}
url.replace(paramValue, encodedValue)
} else url
}