我在这个项目上使用了Retrofit和Gson。我试图登录,我应该得到一个用户ID的响应,faunadb_token,以及填充了用户数据的数据列表。
"body": "{\n \"content\": {\n \"id\": \"328803596056396364\",\n \"faunadb_token\": \"fauna fnEEnk81KUACTwSP8HIOwApJqbjNg-u4fqC9q6Da2FvPTP2esYs\",\n \"data\": {\n \"name\": \"test2\",\n \"email\": \"bowner@gmail.com\",\n \"role\": \"admin\",\n \"organization_id\": \"328992226856141394\",\n \"address\": \"address local\",\n \"birthdate\": \"2000-04-13\",\n \"phonenumber\": \"0811033222\",\n \"s3_image\": \"https://assignmentsystem.s3.ap-southeast-1.amazonaws.com/userimages/0abf8e6b-c2b2-4e49-9a88-10ffb3fffaba-272327.jpg\"\n }\n },\n \"message\": \"Successful Login\",\n \"errors\": []\n}"
然而,当我登录时,我得到的statusCode为200,而我的response.body全部为空。
但是,在终端中,我可以看到实际的响应主体在那里,我只是不知道如何获得它(倒数第三行)。
I/okhttp.OkHttpClient: <-- 200 https://api.absensia.online/backend/user/login (1111ms)
I/okhttp.OkHttpClient: content-type: application/json; charset=utf-8
I/okhttp.OkHttpClient: x-powered-by: Express
I/okhttp.OkHttpClient: access-control-allow-origin: *
I/okhttp.OkHttpClient: etag: W/"1b0-6FklyrUjQI2dIrZLhEXcT1rvf1A"
I/okhttp.OkHttpClient: vary: Accept-Encoding
I/okhttp.OkHttpClient: date: Mon, 27 Jun 2022 07:45:02 GMT
I/okhttp.OkHttpClient: x-kong-upstream-latency: 264
I/okhttp.OkHttpClient: x-kong-proxy-latency: 1
I/okhttp.OkHttpClient: via: kong/2.8.1
I/okhttp.OkHttpClient: {"content":{"id":"328803596056396364","faunadb_token":"fauna fnEEqE4wt-ACUQSP8HIOwApJ7n1pLvPWUfBNciPtrEL0t1ifoT8","data":{"name":"test2","email":"bowner@gmail.com","role":"admin","organization_id":"328992226856141394","address":"address local","birthdate":"2000-04-13","phonenumber":"0811033222","s3_image":"https://assignmentsystem.s3.ap-southeast-1.amazonaws.com/userimages/default.png"}},"message":"Successful Login","errors":[]}
I/okhttp.OkHttpClient: <-- END HTTP (432-byte body)
D/EGL_emulation: app_time_stats: avg=16.10ms min=1.92ms max=565.09ms count=42
下面是我的一些代码:
Api配置
object ApiConfig {
private const val BASE_URL = "https://api.absensia.online/backend/"
private val client: Retrofit
get() {
val gson = GsonBuilder().setLenient().create()
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(40, TimeUnit.SECONDS)
.readTimeout(40, TimeUnit.SECONDS)
.writeTimeout(40, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build()
}
val instanceRetrofit: ApiService
get() = client.create(ApiService::class.java)
}
Api服务
interface ApiService {
@FormUrlEncoded
@POST("user/login")
suspend fun login(
@Field("email") email:String,
@Field("password") password:String,
): Response<LoginResponse>
@GET("user/logout")
suspend fun logout(
@Header("Auth") auth: String
): Response<ResponseAuth>
}
登录响应类
data class LoginResponse(
@SerializedName("id")
var id: String?,
@SerializedName("faunadb_token")
var faunadb_token: String?,
@SerializedName("data")
var data: User?
)
资料档案库
class Repository {
suspend fun login(email: String, password: String): Response<LoginResponse>{
return ApiConfig.instanceRetrofit.login(email, password)
}
suspend fun logout(auth: String): Response<ResponseAuth>{
return ApiConfig.instanceRetrofit.logout(auth)
}
}
身份验证视图模型
class AuthenticationViewModel(private val repository: Repository): ViewModel() {
var loginResponse: MutableLiveData<Response<LoginResponse>> = MutableLiveData()
var logout: MutableLiveData<Response<ResponseAuth>> = MutableLiveData()
fun login(email: String, password: String){
viewModelScope.launch {
val response = repository.login(email, password)
loginResponse.value = response
}
}
fun logout(auth: String){
viewModelScope.launch {
val response = repository.logout(auth)
logout.value = response
}
}
}
身份验证视图模型工厂
class AuthenticationViewModelFactory(private val repository: Repository): ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return AuthenticationViewModel(repository) as T
}
}
登录活动
class LoginActivity : AppCompatActivity() {
private lateinit var loginpref: SharedPref
private lateinit var viewModel: AuthenticationViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_masuk)
loginpref = SharedPref(this)
val masuk = findViewById<Button>(R.id.masuk_btn)
masuk.setOnClickListener {
masukButton()
}
buttonsMasukTest()
}
private fun masukButton(){
val masukEmail = findViewById<TextInputEditText>(R.id.masukHpEmail)
val masukPass = findViewById<TextInputEditText>(R.id.masukPass)
val masukEmailLayout = findViewById<TextInputLayout>(R.id.masukHpEmail_layout)
val masukPassLayout = findViewById<TextInputLayout>(R.id.masukPass_layout)
val loadMasuk = findViewById<ProgressBar>(R.id.load_masuk)
masukEmailLayout.isErrorEnabled = false
masukPassLayout.isErrorEnabled = false
if (masukEmail.text.toString().isEmpty()) {
masukEmailLayout.isErrorEnabled = true
masukEmailLayout.error = "Mohon mengisi kolom ini"
masukEmailLayout.requestFocus()
return
}
if (masukPass.text.toString().isEmpty()) {
masukPassLayout.isErrorEnabled = true
masukPassLayout.error = "Mohon mengisi kolom ini"
masukPassLayout.requestFocus()
return
}
if (!android.util.Patterns.EMAIL_ADDRESS.matcher(masukEmail.text.toString()).matches()){
masukEmailLayout.isErrorEnabled = true
masukEmailLayout.error = "Mohon mengisi email dengan benar"
masukEmailLayout.requestFocus()
return
}
loadMasuk.visibility = View.VISIBLE
val repository = Repository()
val viewModelFactory = AuthenticationViewModelFactory(repository)
viewModel = ViewModelProvider(this, viewModelFactory).get(AuthenticationViewModel::class.java)
viewModel.login(
masukEmail.text.toString(),
masukPass.text.toString())
viewModel.loginResponse.observe(this, Observer { response ->
if (response.isSuccessful){
loadMasuk.visibility = View.GONE
val respon = response.body()
loginpref.setStatusLogin(true)
respon?.data?.let { loginpref.setUser(it) }
respon?.faunadb_token?.let { loginpref.saveToken(it) }
/**
* Momentary textview so I can know my respon
*/
findViewById<TextView>(R.id.testing).setText(respon.toString())
/**
* I comment the section where it start the next activity for testing purposes
*/
// val intent = Intent(this@LoginActivity, MainActivity::class.java)
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
// startActivity(intent)
// finish()
// Toast.makeText(this@LoginActivity, "Welcome " + masukEmail.text.toString(), Toast.LENGTH_SHORT).show()
}else if(!response.isSuccessful){
loadMasuk.visibility = View.GONE
Toast.makeText(this@LoginActivity, "Login failed: Your Email or Password is Incorrect : "+response, Toast.LENGTH_SHORT).show()
}
})
}
private fun buttonsMasukTest(){
val testMasuk = findViewById<Button>(R.id.masuk_btnTest)
testMasuk.setOnClickListener {
val intent = Intent (this@LoginActivity, MainActivity::class.java)
loginpref.setStatusLogin(true)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
}
}
}
我是新的Kotlin,我试图阅读和观看从几个来源有关Okhttp,翻新,gson,和viewmodel,但没有在解决这个问题的效用.任何帮助和建议将不胜感激,关于我如何可以得到响应体.谢谢.
1条答案
按热度按时间628mspwn1#
也许这可以帮助您。您正在内容节点中获取数据,因此