集成Flow后Retrofit无法返回数据的问题排查与解决
Android Flow + Retrofit 异步数据加载失效问题排查与解决
近期学习Android开发时,遇到一个问题:编写的REST接口数据获取+RecyclerView展示代码,硬编码数据时功能正常,用Retrofit的enqueue方法能在日志中看到返回数据,但改用Flow处理异步数据后,功能失效且日志为空。相关代码如下:
ApiInterface 代码
interface ApiInterface { @GET("/api/v1/employees") fun getEmployees() : Call<ResponseModel> }
ServiceBuilder 代码
object ServiceBuilder { private val client = OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT) .setLevel(HttpLoggingInterceptor.Level.BODY)) .build() private val retrofit: Retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build() fun<T> buildService(service: Class<T>): T{ return retrofit.create(service) } }
EmployeeRepository 代码
class EmployeeRepository() { fun getEmployees(): Flow<ResponseModel?> = flow { val response = ServiceBuilder.buildService(ApiInterface::class.java) Log.d("restAPI",response.getEmployees().execute().body()!!.toString() ) emit( response.getEmployees().execute().body() ) } }
MainViewModel 代码
class MainViewModel(private val savedStateHandle: SavedStateHandle): ViewModel() { init { viewModelScope.launch { EmployeeRepository().getEmployees().collect { Log.d("restAPI", it.toString()) } } } }
MainActivity 代码
class MainActivity : AppCompatActivity() { private val mainModel: MainViewModel by viewModels() private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.recyclerView.layoutManager = LinearLayoutManager(this) val employee = EmployeeModel(id = 1, employee_age = 11, employee_salary = 12, employee_name = "ABCD", profile_image = "") var employeeList = mutableListOf(employee) val adapter = EmployeeListAdapter(employeeList) binding.recyclerView.adapter = adapter } }
问题解决方法
感谢ho3einshah的帮助,关键修改如下:
- 修改ApiInterface定义:将返回类型从
Call改为Response,并添加suspend关键字
interface ApiInterface { @GET("/api/v1/employees") suspend fun getEmployees() : Response<ResponseModel> }
- 调整ViewModel逻辑:将init块中的收集逻辑改为暴露
getData方法,返回Repository的Flow
fun getData() = repository.getEmployees()
- Activity中正确收集Flow:使用
lifecycleScope配合repeatOnLifecycle在合适的生命周期状态下收集数据,并更新RecyclerView适配器
lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { mainModel.getData().collect { employeeList -> Log.d("restAPI", employeeList.toString() ) val adapter = EmployeeListAdapter(employeeList) binding.recyclerView.adapter = adapter } } }
修改后已能正常在界面上展示获取到的数据。
内容的提问来源于stack exchange,提问作者Mnemonic
相关产品推荐
相关产品推荐

