替换Android中Uri.Builder中的查询参数



我传递了一个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()方法处理原始BuilderappendQueryParameter()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
    }

最新更新