apache设置了一个简单的字段, {"name":"this is new name"}
viewModel观察retrofit获取的数据,更新给textView
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
val textView: TextView = findViewById(R.id.textView)
viewModel.counter.observe(this) { current ->
textView.text = current
}
val btn: Button = findViewById(R.id.btn)
btn.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
MainViewModel.kt
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.switchMap
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainViewModel : ViewModel() {
val counter: LiveData<String>
get() = _counter
private val _counter = MutableLiveData<String>()
init {
val appService = ServiceCreator.create<AppService>()
appService.getAppData().enqueue(object : Callback<App> {
override fun onResponse(call: Call<App>, response: Response<App>) {
val ponSe = response.body()
if (ponSe != null) {
_counter.value = ponSe.name
}
}
override fun onFailure(call: Call<App>, t: Throwable) {
t.printStackTrace()
}
})
}
}
问题①,使用协程简化回调,按书本方法不对,该如何正确使用.
class MainViewModel : ViewModel() {
val counter: LiveData<String>
get() = _counter
private val _counter = MutableLiveData<String>()
private suspend fun <T> Call<T>.await(): T {
return suspendCoroutine { continuation ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
val body = response.body()
if (body != null) continuation.resume(body)
else continuation.resumeWithException(
RuntimeException("response body is null")
)
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
}
方法灰色
直接引用也不行
问题②,按书本的MVVM架构继续搭建,到了后两步按书大致意思修改但没写对,
需要详细更改代码参考学习,
定义数据模型 App.kt
class App (val name: String)
访问接口 AppService.kt
import retrofit2.Call
import retrofit2.http.GET
interface AppService {
@GET("get_data.json")
fun getAppData(): Call<App>
}
retrofit构建器 ServiceCreator.kt
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object ServiceCreator {
private const val BASE_URL = "http://10.0.2.2"
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
inline fun <reified T> create(): T = create(T::class.java)
}
定义统一的数据源访问入口,AppNetwork.kt
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.await
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
object AppNetwork {
private val appService = ServiceCreator.create<AppService>()
suspend fun searchApp() = appService.getAppData().await()
private suspend fun <T> Call<T>.await(): T {
return suspendCoroutine { continuation ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
val body = response.body()
if (body != null) continuation.resume(body)
else continuation.resumeWithException(
RuntimeException("response body is null")
)
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
}
定义仓库层的统一封装,我的数据只有一个参数,书本的比较多,这里不知道改的对不对,
Repository.kt
import androidx.lifecycle.liveData
import kotlinx.coroutines.Dispatchers
object Repository {
fun searchApp(query: @JvmSuppressWildcards String) = liveData(Dispatchers.IO) {
val result = try {
val searchResponse = AppNetwork.searchApp()
Result.success(searchResponse)
} catch (e: Exception) {
Result.failure<App>(e)
}
emit(result)
}
}
书本viewModel的逻辑