Android Kotlin OkHttp api调用承诺

Android Kotlin OkHttp api调用承诺,android,kotlin,Android,Kotlin,我正在使用Kotlin为我的android应用程序开发数据源,但有一些问题我不确定到底发生了什么,或者我想得太多了。所以android不希望您在主线程上执行联网,所以您必须使用okHttp中的排队方法。我想做的是实现一个promise-like方法,它执行一个api调用,然后它有一个回调,在某种意义上说,只有在api调用执行完成后才会运行回调 我想调用这个方法,在从服务器发回令牌之前不做任何事情,这样我就可以保存它,并显示登录用户的主要活动。我很迷茫,不知道该怎么做我想做的事?我对如何登录用户有

我正在使用Kotlin为我的android应用程序开发数据源,但有一些问题我不确定到底发生了什么,或者我想得太多了。所以android不希望您在主线程上执行联网,所以您必须使用okHttp中的排队方法。我想做的是实现一个promise-like方法,它执行一个api调用,然后它有一个回调,在某种意义上说,只有在api调用执行完成后才会运行回调

我想调用这个方法,在从服务器发回令牌之前不做任何事情,这样我就可以保存它,并显示登录用户的主要活动。我很迷茫,不知道该怎么做我想做的事?我对如何登录用户有正确的想法吗

 fun login(username: String, password: String): Result<LoggedInUser> {
        val httpClient = OkHttpClient.Builder()
        val retrofit = Retrofit.Builder()
            .baseUrl("https://test.com")
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient.build())
            .build()


        try {
            val service: AuthenticationService = retrofit.create(AuthenticationService::class.java)
            val userResponse: retrofit2.Call<LoggedInUser> = service.login(LoginRequest(username,password))
            val response = userResponse.enqueue(object : Callback<LoggedInUser> {
                override fun onFailure(call: Call<LoggedInUser>, t: Throwable) {
                    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
                }

                override fun onResponse(
                    call: Call<LoggedInUser>,
                    response: Response<LoggedInUser>
                ) {
                    val user = response.body()
                    if (user != null){
                        return Result.Success(user)
                    }
                }

            })
//            val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "Jane Doe","")
//            return Result.Success(fakeUser)
        } catch (e: Throwable) {
            return Result.Error(IOException("Error logging in", e))
        }
    }
fun登录(用户名:String,密码:String):结果{
val httpClient=OkHttpClient.Builder()
val reformation=reformation.Builder()
.baseUrl(“https://test.com")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build()
试一试{
val服务:AuthenticationService=Reformation.create(AuthenticationService::class.java)
val userResponse:involution2.Call=service.login(LoginRequest(用户名、密码))
val response=userResponse.enqueue(对象:回调{
覆盖失效时的乐趣(调用:调用,t:可丢弃){
TODO(“未实现”)//要更改已创建函数的主体,请使用文件|设置|文件模板。
}
覆盖响应(
呼叫:呼叫,,
答复:答复
) {
val user=response.body()
如果(用户!=null){
返回结果。成功(用户)
}
}
})
//val fakeUser=LoggedInUser(java.util.UUID.randomUUID().toString(),“Jane Doe”,“”)
//返回结果。成功(伪造用户)
}捕获(e:可丢弃){
返回Result.Error(IOException(“错误登录”,e))
}
}

以上是我在通话结束后试图返回登录用户的操作,但我得到的是一个requires unit but found结果。

对于我来说,在这种情况下使用改装似乎更容易。但是如果您想自己编写,可以使用
suspendCoroutine
,这在您尝试将回调转换为协同路由时非常有用

import com.google.gson.GsonBuilder
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import okhttp3.*
import java.io.IOException
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

class API {
    suspend fun authenticate(username: String, password: String): Deferred<LoggedInUser> = withContext(Dispatchers.IO) {
        async {
            suspendCoroutine<LoggedInUser> { continuation ->
                val url = "http:www.test.com"

                val formBody = FormBody.Builder()
                    .add("email", username)
                    .add("password", password)
                    .build()

                val request = Request.Builder()
                    .url(url)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Accept", "application/json")
                    .post(formBody)
                    .build();

                val client = OkHttpClient()

                client.newCall(request).enqueue(object : Callback {
                    override fun onResponse(call: Call, response: Response) {
                        val body = response.body()?.string()

                        val gson = GsonBuilder().create()
                        val res = gson.fromJson(body, LoginResponse::class.java)
                        APIToken.getInstance().put(APIToken.Key.API_TOKEN, res.token)
                        continuation.resume(LoggedInUser(UUID.randomUUID().toString(), "Jane DD","dfasdfasdf")) // return LoggedInUser
                    }

                    override fun onFailure(call: Call, e: IOException) {
                        println("error")
                        println(call)
                        continuation.resumeWithException(e) // fails with exception
                    }
                })
            }
        }
    }
}

import com.google.gson.GsonBuilder
导入kotlinx.coroutines.Deferred
导入kotlinx.coroutines.Dispatchers
导入kotlinx.coroutines.async
导入kotlinx.coroutines.withContext
进口okhttp3*
导入java.io.IOException
导入java.util*
导入kotlin.coroutines.resume
导入kotlin.coroutines.resumeWithException
导入kotlin.coroutines.suspendCoroutine
类API{
暂停验证(用户名:String,密码:String):Deferred=withContext(Dispatchers.IO){
异步的{
suspendCoroutine{continuation->
val url=“http:www.test.com”
val formBody=formBody.Builder()
.add(“电子邮件”,用户名)
.add(“密码”,password)
.build()
val request=request.Builder()
.url(url)
.addHeader(“内容类型”、“应用程序/json”)
.addHeader(“接受”、“应用程序/json”)
.职位(表格)
.build();
val client=OkHttpClient()
client.newCall(请求).enqueue(对象:回调{
覆盖fun onResponse(调用:调用,响应:响应){
val body=response.body()?.string()
val gson=GsonBuilder().create()
val res=gson.fromJson(body,LoginResponse::class.java)
APIToken.getInstance().put(APIToken.Key.API_-TOKEN,res.TOKEN)
continuation.resume(LoggedInUser(UUID.randomuid().toString(),“Jane DD”,“dfasdfasdf”)//返回LoggedInUser
}
覆盖失效(调用:调用,e:IOException){
println(“错误”)
println(调用)
continuation.resumeWithException(e)//异常失败
}
})
}
}
}
}

我想您应该尝试使用
LoginResponse
res
来生成
LoggedInUser
或其他任何东西。在这种情况下,您可以使用Kotlin回调(在这里
然后:((LoginResponse)->Unit
)-

fun authenticate(username: String, password: String, then: ((LoginResponse) -> Unit) {
    val url = "http:www.test.com"

    val formBody = FormBody.Builder()
        .add("email", username)
        .add("password", password)
        .build()

    val request = Request.Builder()
        .url(url)
        .addHeader("Content-Type", "application/json")
        .addHeader("Accept", "application/json")
        .post(formBody)
        .build();

    val client = OkHttpClient()

    client.newCall(request).enqueue(object : Callback {
        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string();

            val gson = GsonBuilder().create()
            val res = gson.fromJson(body, LoginResponse::class.java)
            APIToken.getInstance().put(APIToken.Key.API_TOKEN, res.token)
            then(res)
        }

        override fun onFailure(call: Call, e: IOException) {
            println("error")
            println(call)
        }
    })
}
然后你可以像这样调用这个函数-

authenticate(userName, password){ LoginResponse res ->
    // use the response to do what you need to do
}

希望这能有所帮助。

您这里的设备应该可以正常工作,但可以省去一些麻烦,改型是否“承诺”了像我尝试做的那样基于调用?查看教程我对android dev是新手,但以前在swift中做过我想做的事情。这种方式允许我在http调用完成之前不继续进行?@user12039164在http调用期间,它将等待,但不会阻塞。我仍在尝试了解来自swift世界的协同路由。Netwr=work call w在swiftyep中没有什么特别难的,改型后会更容易:)OkHttp这是一个相当低的级别,通常Android应用程序本身不使用它我不需要为它们导入任何东西吗?我在上下文和其他方面遇到错误,比如异步,您使用的是哪个版本的协同程序?