文章目录
效果图

全文链接
使用的依赖版本
dataBinding {
enabled true
}
implementation 'androidx.core:core-ktx:1.1.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "com.squareup.okhttp3:okhttp:4.2.0"
implementation "com.squareup.retrofit2:retrofit:2.6.1"
implementation "com.squareup.okhttp3:logging-interceptor:4.2.0"
implementation "com.squareup.retrofit2:converter-gson:2.6.1"
netViewModel = ViewModelProvider(this).get(NetViewMoudle::class.java)
- 废弃过时方式 ViewModelProviders is desprecated
// netViewModel = ViewModelProviders.of(this).get(NetViewMoudle::class.java)
retrofit封装类
package com.wjx.android.wanandroidmvvm.base.https
import android.util.Log
import com.example.myapp.common.Constant
import com.example.myapp.common.SPreference
import com.google.gson.Gson
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.StringBuilder
import java.util.concurrent.TimeUnit
class RetrofitFactory private constructor() {
private val retrofit: Retrofit
init {
val gson = Gson().newBuilder()
.setLenient()
.serializeNulls()
.create()
retrofit = Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
.client(initOkhttpClient())
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
companion object {
val instance: RetrofitFactory by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
RetrofitFactory()
}
}
private fun initOkhttpClient(): OkHttpClient {
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.addInterceptor(initLogInterceptor())
.build()
return okHttpClient
}
private fun initLogInterceptor(): HttpLoggingInterceptor {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.i("Retrofit", message)
}
})
interceptor.level = HttpLoggingInterceptor.Level.BODY
return interceptor
}
fun <T> getService(service: Class<T>): T {
return retrofit.create(service)
}
}
网络相关数据结构
package com.example.myapp.bean
data class BaseResp<T> (
var errorCode: Int = 0,
var errorMsg: String = "",
var data: T
)
package com.example.myapp.bean
data class WBean(
val apkLink: String,
val audit: Int,
val author: String,
val canEdit: Boolean,
val chapterId: Int,
val chapterName: String,
val collect: Boolean,
val courseId: Int,
val desc: String,
val descMd: String,
val envelopePic: String,
val fresh: Boolean,
val id: Int,
val link: String,
val niceDate: String,
val niceShareDate: String,
val origin: String,
val prefix: String,
val projectLink: String,
val publishTime: Long,
val selfVisible: Int,
val shareDate: Long,
val shareUser: String,
val superChapterId: Int,
val superChapterName: String,
val tags: List<Any>,
val title: String,
val type: Int,
val userId: Int,
val visible: Int,
val zan: Int
)
package com.example.myapp.ext
import com.example.myapp.bean.BaseResp
fun <T> BaseResp<T>.dataConvert(): T {
if (errorCode == 0) {
return data
} else {
throw Exception(errorMsg)
}
}
fun Context.toast(msg: String) {
Toast.makeText(this, msg, LENGTH_SHORT).show()
}
fun Activity.openActivity(cls: Class<*>) {
startActivity(Intent(this, cls))
}
定义协程api
package com.wjx.android.wanandroidmvvm.base.https
import com.example.myapp.bean.BaseResp
import com.example.myapp.bean.WBean
import retrofit2.http.GET
interface ApiService {
@GET("article/top/json/")
suspend fun getTopArticle(): BaseResp<List<WBean>>
@GET("article/list/{page}/json")
suspend fun getArticleList(@Path("page") page: Int = 0): Result<PageEntity<Article>>
}
ViewModel层
package com.example.myapp.moudle
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.myapp.bean.WBean
import com.example.myapp.ext.dataConvert
import com.wjx.android.wanandroidmvvm.base.https.ApiService
import com.wjx.android.wanandroidmvvm.base.https.RetrofitFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.lang.Exception
import kotlin.math.log
class NetViewMoudle :ViewModel() {
var list= MutableLiveData<List<WBean>>()
fun getTopArticle(){
viewModelScope.launch {
try {
val data = withContext(Dispatchers.IO){
RetrofitFactory.instance.getService(ApiService::class.java).getTopArticle().dataConvert()
}
list.value = data
}catch (e:Exception){
e.printStackTrace()
Log.e("net error","网络请求错误${e.toString()}")
}
}
}
}
class ArticleViewModel :ViewModel() {
private val _articleListData = MutableLiveData<List<Article>>()
val articleListData: LiveData<List<Article>> = _articleListData
private val _errorMsg = MutableLiveData<String?>()
val errorMsg: LiveData<String?> = _errorMsg
fun fetch(page:Int){
viewModelScope.launch {
var result = RetrofitFactory.instance.getService(ApiService::class.java).getArticleList(page)
_articleListData.value = result.data.datas
}
}
}
UI层调用
package com.example.myapp.ui
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import com.example.myapp.R
import com.example.myapp.bean.Animal
import com.example.myapp.databinding.ActivityMainBinding
import com.example.myapp.moudle.NetViewMoudle
import com.example.myapp.vm.AnimalViewModel
import com.google.gson.Gson
import com.wjx.android.wanandroidmvvm.base.https.ApiService
import com.wjx.android.wanandroidmvvm.base.https.RetrofitFactory
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.jvm.java as java
class MainActivity : AppCompatActivity() {
lateinit var mBinding:ActivityMainBinding
lateinit var mViewMode:AnimalViewModel
lateinit var netViewModel:NetViewMoudle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
var animal = Animal("dog",0)
mViewMode = AnimalViewModel(animal)
mBinding.model = mViewMode
netViewModel = ViewModelProvider(this).get(NetViewMoudle::class.java)
mBinding.listener = View.OnClickListener {
when(it.id){
R.id.btn -> netViewModel.getTopArticle()
}
}
netViewModel.list.observe(this, Observer {
tv.text = Gson().toJson(it)
})
}
}
viewModel.articleListData.observe(this, Observer { list ->
loadProgress.visibility = View.GONE
adapter.submitList(list)
})
viewModel.errorMsg.observe(this, Observer {
if (it!=null){
toast(it)
}
})