kotlin集成retrofit获取网络数据,将数据通过Flow发射
效果:
1.定义实体类和网络相关
实体类:
package com.aruba.flowapplyapplication.modeldata class Article(val id: Int, val text: String)
Api:
package com.aruba.flowapplyapplication.netimport com.aruba.flowapplyapplication.model.Article
import retrofit2.http.GET
import retrofit2.http.Query/*** Created by aruba on 2021/9/21.*/
interface Api {@GET("article")suspend fun searchArticles(@Query("key") key: String): List<Article>}
Retrofit的工具类:
package com.aruba.flowapplyapplication.netimport okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory/*** Created by aruba on 2021/9/21.*/
object RetrofitClient {private val instance: Retrofit by lazy {Retrofit.Builder().baseUrl("http://192.168.0.118:8080/kotlinstudyserver/").client(OkHttpClient.Builder().build()).addConverterFactory(GsonConverterFactory.create()).build()}fun getApi(): Api {return instance.create(Api::class.java)}
}
2.ViewModel实现
利用LiveData进行后续的双向绑定
package com.aruba.flowapplyapplication.viewmodelimport androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.aruba.flowapplyapplication.model.Article
import com.aruba.flowapplyapplication.net.RetrofitClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch/*** Created by aruba on 2021/9/21.*/
class ArticleViewModel : ViewModel() {var searchText: MutableLiveData<String> = MutableLiveData()var articleList = MutableLiveData<List<Article>>()fun getArticle() {if (searchText.value == null) returnviewModelScope.launch {flow {emit(RetrofitClient.getApi().searchArticles(searchText.value!!))}.flowOn(Dispatchers.IO).catch { e ->e.printStackTrace()}.collect {articleList.value = it}}}
}
fragment的布局也比较简单,一个EditText和RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<layout 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"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".ArticleFragment"><androidx.appcompat.widget.AppCompatEditTextandroid:id="@+id/appCompatEditText"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:text="@={articleViewModel.searchText}"android:textSize="24sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.0"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerview"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginTop="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/appCompatEditText"></androidx.recyclerview.widget.RecyclerView></androidx.constraintlayout.widget.ConstraintLayout><data><variablename="articleViewModel"type="com.aruba.flowapplyapplication.viewmodel.ArticleViewModel" /></data>
</layout>
3.在Fragment中进行绑定、配置等
package com.aruba.flowapplyapplicationimport android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.aruba.flowapplyapplication.adapter.ArticleAdapter
import com.aruba.flowapplyapplication.databinding.FragmentArticleBinding
import com.aruba.flowapplyapplication.viewmodel.ArticleViewModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launchclass ArticleFragment : Fragment() {private val articleViewModel by lazy { ArticleViewModel() }private val articleAdapter by lazy { ArticleAdapter() }override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {val fragmentArticleBinding = DataBindingUtil.inflate<FragmentArticleBinding>(inflater,R.layout.fragment_article,container,false)//绑定viewmodelfragmentArticleBinding.articleViewModel = articleViewModel//配置recyclerviewfragmentArticleBinding.recyclerview.adapter = articleAdapterfragmentArticleBinding.recyclerview.layoutManager = LinearLayoutManager(requireContext())//设置LiveDatafragmentArticleBinding.lifecycleOwner = viewLifecycleOwner//对edittext文本进行监听articleViewModel.searchText.observe(viewLifecycleOwner) {articleViewModel.getArticle()}//对服务器返回list的变化进行监听articleViewModel.articleList.observe(viewLifecycleOwner) {articleAdapter.setData(it)}return fragmentArticleBinding.root}}