添加依赖
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:converter-gson:2.9.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" implementation 'androidx.recyclerview:recyclerview:1.2.1'
data class Article(val id: Int, val text: String)
创建实体类Article
interface ArticleApi {
@GET("article")
suspend fun searchArticles(
@Query("key")Key:String
):List
}
object RetrofitClient {
//lazy 懒加载 在使用时构造Retrofit对象
private val instance: Retrofit by lazy {
Retrofit.Builder()
.client(OkHttpClient.Builder().build())
.baseUrl("http://192.168.1.34:8080/kotlinstudyserver/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val articleApi: ArticleApi by lazy {
instance.create(ArticleApi::class.java)
}
}
封装 Retrofit
class BindingViewHolder (val binding:ViewBinding):RecyclerView.ViewHolder(binding.root){
}
class ArticleAdapter(private val context: Context) : RecyclerView.Adapter() { private val data=ArrayList() fun setData(data:List){ this.data.clear(); this.data.addAll(data) notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder { val inflate = ItemUserBinding.inflate(LayoutInflater.from(context), parent, false) return BindingViewHolder(inflate) } override fun onBindViewHolder(holder: BindingViewHolder, position: Int) { val item=data[position] val itemUserBinding = holder.binding as ItemUserBinding itemUserBinding.text.text=item.text } override fun getItemCount(): Int { return data?.size } }
RecyclerView适配器
class ArticleViewModel(application: Application) : AndroidViewModel(application) {
val articles=MutableLiveData ()
fun searchArticles(key:String){
//因为双flow会造成嵌套 ,所以在这里收获后改用了liveData
viewModelScope.launch {
flow {
val list=RetrofitClient.articleApi.searchArticles(key)
emit(list) //发射数据
}.flowOn(Dispatchers.IO) //更改Flow上下文
.catch {
e->
e.printStackTrace() //上游有异常,在保证不打破flow涉及原则的情况下推荐使用catch函数
}.collect {
articles.value=it; //接收数据并给LiveData赋值
}
}
}
//双flow会造成嵌套写法
fun searchArticles1(key:String)= flow{
val list=RetrofitClient.articleApi.searchArticles(key)
emit(list) //发射数据
}.flowOn(Dispatchers.IO) //更改Flow上下文
.catch {
e->
e.printStackTrace() //上游有异常,在保证不打破flow涉及原则的情况下推荐使用catch函数
}
}
ViewModel类
class ArticleFragment :Fragment() {
private val viewModel by viewModels()
private val mBinding: FragmentArticleBinding by lazy {
FragmentArticleBinding.inflate(layoutInflater)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return mBinding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
lifecycleScope.launchWhenCreated {
//这里调了下面的监听 这里用来双flow设计
mBinding.etSearch.textWatcherFlow().collect {
viewModel.searchArticles(it)
//双Flow写法接收
}
}
context?.let {
val articleAdapter = ArticleAdapter(it)
mBinding.recyclerView.adapter= articleAdapter
mBinding.recyclerView.layoutManager=LinearLayoutManager(it,LinearLayoutManager.VERTICAL,false)
viewModel.articles.observe(viewLifecycleOwner,{article->
articleAdapter.setData(article)
})
}
}
private fun TextView.textWatcherFlow(): Flow = callbackFlow{
val textWatcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
offer(s.toString())
}
}
addTextChangedListener(textWatcher)
//移除监听器
awaitClose{removeTextChangedListener(textWatcher)}
}
}
效果演示:



