RestActivity
package com.example.internet_ex
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.lifecycle.*
import kotlinx.coroutines.launch
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
import java.lang.StringBuilder
data class Owner(val login: String)
data class Repo(val name: String, val owner: Owner, val url: String)
data class Contributor(val login: String, val contributions: Int)
interface RestApi {
@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String): List<Repo>
@GET("/repos/{owner}/{repo}/contributors")
suspend fun contributors(
@Path("owner") owner: String,
@Path("repo") repo: String
): List<Contributor>
}
class MyViewModel : ViewModel() {
private val baseURL = "https://api.github.com/"
private lateinit var api: RestApi
val userName = MutableLiveData<String>()
val response = MutableLiveData<String>()
init {
retrofitInit()
refreshData()
}
fun refreshData() {
viewModelScope.launch {
try {
val repos = api.listRepos(userName.toString())
response.value = StringBuilder().apply {
repos.forEach {
append(it.name)
append(" - ")
append(it.owner.login)
append("\n")
}
}.toString()
} catch (e: Exception) {
response.value = "Failed to connect to the server"
}
}
}
private fun retrofitInit() {
val retrofit = Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(MoshiConverterFactory.create())
.build()
api = retrofit.create(RestApi::class.java)
}
}
class RestActivity : AppCompatActivity() {
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rest)
myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)
// problem
myViewModel.userName.observe(this) {
findViewById<Button>(R.id.queryBtn).setOnClickListener {
myViewModel.userName.value = findViewById<Button>(R.id.nameText).toString()
myViewModel.refreshData()
}
}
myViewModel.response.observe(this) {
findViewById<TextView>(R.id.textResponse).text = it
findViewById<Button>(R.id.queryBtn).setOnClickListener {
}
}
}
}
activity_rest
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RestActivity">
<TextView
android:id="@ id/textResponse"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@ id/queryBtn" />
<Button
android:id="@ id/queryBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Query"
app:layout_constraintStart_toEndOf="@ id/nameText"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@ id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
**activity_rest.xml**
I made a place where I commented that it was a problem because I wanted to change the userName
in the ViewModel
when I pressed queryBtn
, but it didn't work. I want to change the LiveData (userName)
in the ViewModel using the setOnClickLisenter
command, but I can't figure it out. And I would appreciate it if you could let me know what to study additionally.
CodePudding user response:
Your OnClickListener
needs to be set outside of the observer
.
At least from what I can tell you don't need to observe
userName
as the queryBtn
is used to activate a response
, and NOT the fact that userName
was changed.
But you do want to observe
the response
as it is changed in the ViewModel
, and needs to be displayed in textResponse
.
The code below is NOT checked for correctness I just copied what you had and removed the unnecessary bits.
findViewById<Button>(R.id.queryBtn).setOnClickListener {
myViewModel.userName.value = findViewById<EditText>(R.id.nameText).getText().toString()
myViewModel.refreshData()
}
myViewModel.response.observe(this) {
findViewById<TextView>(R.id.textResponse).text = it
}
CodePudding user response:
Move this outside observer block
findViewById<Button>(R.id.queryBtn).setOnClickListener {
myViewModel.userName.value = findViewById<EditText>(R.id.nameText).getText().toString()
}
Inside observer block, when user String is updated, call refresh data
myViewModel.userName.observe(this) {
myViewModel.refreshData()
}
Remove onClickListener
from response
observer block.