lateinit属性recview未初始化:Hilt环境下10天天气Fragment问题
问题描述
开发了一个用于获取定位城市并展示该城市10天天气的Fragment,目前遇到RecyclerView与ViewModel的初始化问题,报错信息为lateinit property recview has not been initialized。项目采用Hilt实现依赖注入,已获取定位权限,需求是实现定位城市的10天天气展示。
相关代码
ForecastViewmodel 接口
import androidx.lifecycle.LiveData import dagger.hilt.android.lifecycle.HiltViewModel import db.entities.WeatherData @HiltViewModel interface ForecastViewmodel { val dataforecast: LiveData<List<WeatherData>> val city : LiveData<String> val isRefreshing: LiveData<Boolean> fun onRefresh() }
ForecastViewmodelImpl 实现类
@HiltViewModel class ForecastViewmodelImpl(private val repository: ForecastRepository, private val day: Day ) : ForecastViewmodel, ViewModel(){ override val dataforecast = MutableLiveData<List<WeatherData>>() override val city = MutableLiveData(day.city) override val isRefreshing = MutableLiveData(true) init { loadForecast() } private fun loadForecast() { isRefreshing.value = true viewModelScope.launch { try { val data = repository.getForecast(day.days) Timber.d("size is ${data}") }catch (e:Exception){ Timber.e(e) } isRefreshing.value = false } } override fun onRefresh() = loadForecast() private fun Forecastday.toWeatherData() = WeatherData( date = date, temp = "${temp.roundToInt()}℃" ) }
WeatherRecView 适配器
import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.example.testtaskweatherappkevychsol.R import db.entities.WeatherData class WeatherRecView:RecyclerView.Adapter<WeatherRecView.WeatherHolder>() { var listweather = emptyList<WeatherData>() class WeatherHolder(view:View):RecyclerView.ViewHolder(view) override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): WeatherHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.daily_weather_layout, parent,false) return WeatherHolder(view) } override fun onBindViewHolder( holder: WeatherHolder, position: Int ) { holder.itemView.findViewById<TextView>(R.id.Dateitem).text = listweather[position].date holder.itemView.findViewById<TextView>(R.id.tempitem).text = listweather[position] .temp.toString() } override fun getItemCount(): Int { return listweather.size } fun addlistintoUI(list: List<WeatherData>){ listweather = list } }
WeatherData 数据类
data class WeatherData( val temp:String, val date:String )
WeatherAtTheLifeMomentFragment 碎片类
import RecyclerView.WeatherRecView import Viewmodel.ForecastViewmodel import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.example.testtaskweatherappkevychsol.R import com.example.testtaskweatherappkevychsol.databinding.FragmentWeatherBinding import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class WeatherAtTheLifeMomentFragment : Fragment(R.layout.fragment_weather){ lateinit var recview:WeatherRecView private var binding : FragmentWeatherBinding? = null lateinit var viewmodel:ForecastViewmodel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding = FragmentWeatherBinding.inflate(inflater,container,false) this.binding = binding return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) with(binding){ this!!.refreshbt.setOnClickListener { viewmodel.isRefreshing } containerlistweather.adapter = recview containerlistweather.addItemDecoration(DividerItemDecoration(containerlistweather.context, (containerlistweather .layoutManager as LinearLayoutManager).orientation)) with(viewmodel){ dataforecast.observe(viewLifecycleOwner) { recview.listweather = it } City.text = city.toString() } } } override fun onDestroyView() { super.onDestroyView() binding = null } }
解决方案
1. 初始化RecyclerView适配器
报错核心原因是声明了lateinit var recview:WeatherRecView但未实例化,在onViewCreated开头添加适配器初始化代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化适配器 recview = WeatherRecView() with(binding){ // ... 原有代码 } }
2. 正确注入ViewModel
Fragment中的viewmodel同样是lateinit未初始化,改用Hilt的viewModels委托获取实例:
// 替换原有viewmodel声明 private val viewmodel: ForecastViewmodel by viewModels<ForecastViewmodelImpl>()
注:需确保ForecastRepository、Day已通过Hilt提供依赖。
3. 修复适配器数据更新逻辑
适配器的addlistintoUI方法未通知RecyclerView刷新数据,补充刷新调用:
fun addlistintoUI(list: List<WeatherData>){ listweather = list notifyDataSetChanged() }
同时在Fragment的观察者中调用该方法,而非直接赋值:
dataforecast.observe(viewLifecycleOwner) { recview.addlistintoUI(it) }
4. 修复刷新按钮逻辑
当前点击事件仅获取isRefreshing值,未触发刷新操作,改为调用ViewModel的刷新方法:
this!!.refreshbt.setOnClickListener { viewmodel.onRefresh() }
5. 修复城市名称展示
city是LiveData,不能直接toString()取值,需观察其变化更新UI:
viewmodel.city.observe(viewLifecycleOwner) { cityName -> binding?.City?.text = cityName }
6. 补全ViewModel数据转换逻辑
loadForecast方法中获取数据后未转换为WeatherData并更新LiveData,补充转换代码:
private fun loadForecast() { isRefreshing.value = true viewModelScope.launch { try { val data = repository.getForecast(day.days) Timber.d("size is ${data.size}") // 转换数据并更新LiveData val weatherDataList = data.map { it.toWeatherData() } dataforecast.value = weatherDataList }catch (e:Exception){ Timber.e(e) } isRefreshing.value = false } }
内容的提问来源于stack exchange,提问作者user20498005
相关产品推荐
相关产品推荐

