https://antonioleiva.com/retrofit-android-kotlin/
我是Kotlin的新手,我想创建一个Android移动应用程序。我使用Android Studio 3.3(Android API级别28)。我使用了一个摇摇欲坠的工具来获取我所有的RESTful Web服务,因此, android-client-generated生成了包含所有Web服务的文件。首先,我选择使用Web服务进行“登录”身份验证,因此创建了一个android界面,该界面包含两个editText和一个Login按钮,edittext一个用于“ Email”,另一个用于“ Password”。以下代码是swagger产生的Web服务:
fun apiMobileAPILoginPost(model: LoginViewModel) : Unit { val localVariableBody: kotlin.Any? = model val localVariableQuery: MultiValueMap = mapOf()
val contentHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val acceptsHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: kotlin.collections.MutableMap<kotlin.String,kotlin.String> = mutableMapOf()
localVariableHeaders.putAll(contentHeaders)
localVariableHeaders.putAll(acceptsHeaders)
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/api/MobileAPI/Login",
query = localVariableQuery,
headers = localVariableHeaders
)
val response = request<Unit>(
localVariableConfig,
localVariableBody
)
return when (response.responseType) {
ResponseType.Success -> Unit
ResponseType.Informational -> TODO()
ResponseType.Redirection -> TODO()
ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error")
ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error")
else -> throw kotlin.IllegalStateException("Undefined ResponseType.")
}
}
我的目标是,当我输入电子邮件和密码时,以及在按下登录按钮时,main_activity.xml会显示在屏幕上。以下代码是我使用服务Web登录名的方式:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login_user)
bt_login.setOnClickListener {
if (email.text.toString() != "" && password.text.toString() != "")
{ // if email and password edit text not empty
if (email.text.toString() .isValidEmail()) { // if the email form is correct
try {
MobileAPIApi().apiMobileAPILoginPost(
LoginViewModel(
email.text.toString(),
password.text.toString()
)
)
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
} catch (e: Exception) {
println("Client error")
e.printStackTrace()
}
} else {
val alertDialogBuilder = AlertDialog.Builder(this)
alertDialogBuilder.setMessage(R.string.invalid_email)
.setCancelable(false)
.setNegativeButton(R.string.cancel, DialogInterface.OnClickListener { dialog, id ->
dialog.cancel()
})
val alert = alertDialogBuilder.create()
alert.show()
}
} else {
val alertDialogBuilder = AlertDialog.Builder(this)
alertDialogBuilder.setMessage(R.string.fill_entries)
.setCancelable(false)
.setNegativeButton(R.string.cancel, DialogInterface.OnClickListener { dialog, id ->
dialog.cancel()
})
val alert = alertDialogBuilder.create()
alert.show()
}
}
}
我还在AndroidManifest.xml中添加了互联网许可的使用:
以下代码是ApiClient的一部分:
@JvmStatic
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
inline protected fun <reified T: Any?> request(requestConfig: RequestConfig, body : Any? = null): ApiInfrastructureResponse<T?> {
val httpUrl = HttpUrl.parse(baseUrl) ?: throw IllegalStateException("baseUrl is invalid.")
var urlBuilder = httpUrl.newBuilder()
.addPathSegments(requestConfig.path.trimStart('/'))
requestConfig.query.forEach { query ->
query.value.forEach { queryValue ->
urlBuilder = urlBuilder.addQueryParameter(query.key, queryValue)
}
}
val url = urlBuilder.build()
val headers = defaultHeaders + requestConfig.headers
if(headers[ContentType] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Content-Type header. This is required.")
}
if(headers[Accept] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Accept header. This is required.")
}
// TODO: support multiple contentType,accept options here.
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val accept = (headers[Accept] as String).substringBefore(";").toLowerCase()
var request : Request.Builder = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
RequestMethod.GET -> Request.Builder().url(url)
RequestMethod.HEAD -> Request.Builder().url(url).head()
RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(body, contentType))
RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(body, contentType))
RequestMethod.POST -> Request.Builder().url(url).post(requestBody(body, contentType))
RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null)
}
headers.forEach { header -> request = request.addHeader(header.key, header.value) }
val realRequest = request.build()
val response = client.newCall(realRequest).execute()
// TODO: handle specific mapping types. e.g. Map<int, Class<?>>
when {
response.isRedirect -> return Redirection(
response.code(),
response.headers().toMultimap()
)
response.isInformational -> return Informational(
response.message(),
response.code(),
response.headers().toMultimap()
)
response.isSuccessful -> return Success(
responseBody(response, accept),
response.code(),
response.headers().toMultimap()
)
response.isClientError -> return ClientError(
response.body()?.string(),
response.code(),
response.headers().toMultimap()
)
else -> return ServerError(
null,
response.body()?.string(),
response.code(),
response.headers().toMultimap()
)
}
}
运行我的应用程序时,出现以下异常:
I / System.out:客户端错误W / System.err: android.os.NetworkOnMainThreadException W / System.err:在 android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1285) 在java.net.InetAddress.lookupHostByName(InetAddress.java:434) 在java.net.InetAddress.getAllByNameImpl(InetAddress.java:255) 在java.net.InetAddress.getAllByName(InetAddress.java:218) 在okhttp3.Dns $ Companion $ SYSTEM $ 1.lookup(Dns.kt:48) 在okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.kt:157) 在okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.kt:122) 在okhttp3.internal.connection.RouteSelector.next(RouteSelector.kt:70) 在okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:203) 在okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:108) 在okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:76) 在okhttp3.internal.connection.Transmitter.newExchange $ okhttp(Transmitter.kt:162) 在okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:36) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:117) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:90) 在okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:84) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:117) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:90) 在okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:117) 在okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:117) 在okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:90) 在okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184) 在okhttp3.RealCall.execute(RealCall.kt:67) 在io.swagger.client.apis.MobileAPIApi.apiMobileAPILoginPost(MobileAPIApi.kt:2839) 在com.hotpay.LoginUserActivity $ onCreate $ 1.onClick(LoginUserActivity.kt:39) 在android.view.View.performClick(View.java:5273) 在android.view.View $ PerformClick.run(View.java:21315) 在android.os.Handler.handleCallback(Handler.java:743) 在android.os.Handler.dispatchMessage(Handler.java:95) 在android.os.Looper.loop(Looper.java:150) 在android.app.ActivityThread.main(ActivityThread.java:5639) 在java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:799) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:689)
我想知道如何纠正我的代码以使其正常工作,否则如何使用swagger生成的Web服务。