You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:20:33