没有适配器附加; 跳过布局。Recycler View 出现错误。

huangapple go评论69阅读模式
英文:

No adapter attached; skipping layout. Error with Recycler View

问题

以下是您要翻译的部分:

In my app I integrate rest api to show weather at life time, and I have problems to bind viewmodel and Recyclerview adapter in fragment to get final result and show weather. I have successful response, so I don't have problems with it.

Also I integrate locations permissions, maybe errors could be of this.

Here is the code of my xml layout and logic.

data class WeatherCurrentResponse(
    @SerializedName("latitude")
    var lat :Double,
    @SerializedName("longitude")
    var lon:Double,
    @SerializedName("current_weather")
    var weathercurrent:CurrentWeather,
)
data class CurrentWeather(
    val time: LocalDateTime,
    @SerializedName("temperature")
    val temp : Int
)

@HiltViewModel
class WeatherViewModel @Inject constructor(private val repository: CurrentRepository,
                                           private val location: TrackLocation ):ViewModel() {
private val _weatherstate = MutableLiveData<Response<WeatherCurrentResponse>>()
    val weatherstate:LiveData<Response<WeatherCurrentResponse>> = _weatherstate

fun displayweatherbylocation() {
    viewModelScope.launch {
try {
    location.getCurrentlocation()?.let {
        loc->
      val result = repository.getCurrentWeather(loc.latitude,loc.longitude)
          _weatherstate.value = result
    }
}catch (e:ViewmodelException){
Log.d("VM EXCEPTION","Check viewmodel probably nullpointexcept")
}

    }
}
}

class CurrentWeatherRecView
    :RecyclerView.Adapter<CurrentWeatherRecView.WeatherListHolder>() {
    var weatherlist = ArrayList<WeatherCurrentResponse>()
    inner class WeatherListHolder(itemView:View) :RecyclerView.ViewHolder(itemView){
        fun bind(data:WeatherCurrentResponse){
            itemView.findViewById<TextView>(R.id.tempcurrent).text =
                data.weathercurrent.temp.toString()
            itemView.findViewById<TextView>(R.id.time).text = data.weathercurrent.time.format(
                DateTimeFormatter.ofPattern("yyyy/MM/dd")
            )
            itemView.findViewById<TextView>(R.id.city).text =
                data.lat.compareTo(data.lon).toString()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherListHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.forecast_items,parent,
            false)
        return WeatherListHolder(view)
    }

    override fun getItemCount(): Int {
   return  weatherlist.size
    }

    override fun onBindViewHolder(holder: WeatherListHolder, position: Int) {
     weatherlist[position].let {
         holder.bind(data = it)
     }
    }

    fun updateInfo(list:ArrayList<WeatherCurrentResponse>){
        weatherlist.clear()
        weatherlist.addAll(list)
        notifyDataSetChanged()
    }
}

@AndroidEntryPoint
class ListWeatherFragment : Fragment() {
    lateinit var recView:RecyclerView
private lateinit var binding:FragmentListWeatherBinding
private val viewModel:WeatherViewModel by viewModels()
private lateinit var permissionlauncher:ActivityResultLauncher<Array<String>>
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentListWeatherBinding.inflate(inflater)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        permissionlauncher = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ){
            recView = binding.recviewInFragment
            recView.apply {
                layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,
                    false)
                val weatheradapter = CurrentWeatherRecView()
                adapter = weatheradapter
                viewModel.displayweatherbylocation()
                viewModel.weatherstate.observe(viewLifecycleOwner) {
                 data->
                    data.body()?.let {
                        weatheradapter.updateInfo(
                            list = ArrayList()
                        )
                    }
                }
            }
        }
        permissionlauncher.launch(arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        ))
    }
}
英文:

In my app I integrate rest api to show weather at life time , and I have problems to bind viewmodel and Recyclerview adapter in fragment to get final result and show weather. I have successful response , so I don't have problems with it.

Also I integrate locations permissions , maybe errors could be of this.

Here is the code of my xml layout and logic.

data class WeatherCurrentResponse(
@SerializedName(&quot;latitude&quot;)
var lat :Double,
@SerializedName(&quot;longitude&quot;)
var lon:Double,
@SerializedName(&quot;current_weather&quot;)
var weathercurrent:CurrentWeather,
)
data class CurrentWeather(
val time: LocalDateTime,
@SerializedName(&quot;temperature&quot;)
val temp : Int
)

@HiltViewModel
class WeatherViewModel @Inject constructor(private val repository: CurrentRepository,
private val location: TrackLocation ):ViewModel() {
private val _weatherstate = MutableLiveData&lt;Response&lt;WeatherCurrentResponse&gt;&gt;()
val weatherstate:LiveData&lt;Response&lt;WeatherCurrentResponse&gt;&gt; = _weatherstate
fun displayweatherbylocation() {
viewModelScope.launch {
try {
location.getCurrentlocation()?.let {
loc-&gt;
val result = repository.getCurrentWeather(loc.latitude,loc.longitude)
_weatherstate.value = result
}
}catch (e:ViewmodelException){
Log.d(&quot;VM EXCEPTION&quot;,&quot;Check viewmodel probably nullpointexcept&quot;)
}
}
}
}

class CurrentWeatherRecView
:RecyclerView.Adapter&lt;CurrentWeatherRecView.WeatherListHolder&gt;() {
var weatherlist = ArrayList&lt;WeatherCurrentResponse&gt;()
inner class WeatherListHolder(itemView:View) :RecyclerView.ViewHolder(itemView){
fun bind(data:WeatherCurrentResponse){
itemView.findViewById&lt;TextView&gt;(R.id.tempcurrent).text =
data.weathercurrent.temp.toString()
itemView.findViewById&lt;TextView&gt;(R.id.time).text = data.weathercurrent.time.format(
DateTimeFormatter.ofPattern(&quot;yyyy/MM/dd&quot;)
)
itemView.findViewById&lt;TextView&gt;(R.id.city).text =
data.lat.compareTo(data.lon).toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherListHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.forecast_items,parent,
false)
return WeatherListHolder(view)
}
override fun getItemCount(): Int {
return  weatherlist.size
}
override fun onBindViewHolder(holder: WeatherListHolder, position: Int) {
weatherlist[position].let {
holder.bind(data = it)
}
}
fun updateInfo(list:ArrayList&lt;WeatherCurrentResponse&gt;){
weatherlist.clear()
weatherlist.addAll(list)
notifyDataSetChanged()
}
}

@AndroidEntryPoint
class ListWeatherFragment : Fragment() {
lateinit var recView:RecyclerView
private lateinit var binding:FragmentListWeatherBinding
private val viewModel:WeatherViewModel by viewModels()
private lateinit var permissionlauncher:ActivityResultLauncher&lt;Array&lt;String&gt;&gt;
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentListWeatherBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
permissionlauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
){
recView = binding.recviewInFragment
recView.apply {
layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,
false)
val weatheradapter = CurrentWeatherRecView()
adapter = weatheradapter
viewModel.displayweatherbylocation()
viewModel.weatherstate.observe(viewLifecycleOwner) {
data-&gt;
data.body()?.let {
weatheradapter.updateInfo(
list = ArrayList()
)
}
}
}
}
permissionlauncher.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
))
}
}

答案1

得分: 0

Instead of giving the result to your RecyclerViewAdapter, you always give a new empty list list = ArrayList(). You must use the received body inside your let-block to update the RecyclerViewAdapter.

viewModel.weatherstate.observe(viewLifecycleOwner) { data ->
    data.body()?.let { body ->
        weatheradapter.updateInfo(list = body)
    }
}

You can simplify your Adapter by using ListAdapter. It will manage updating the list and animate any changes (see also DiffCallback for better update handling).

英文:

Here is the problem:

viewModel.weatherstate.observe(viewLifecycleOwner) {
data-&gt;
data.body()?.let {
weatheradapter.updateInfo(
list = ArrayList()
)
}
}

Instead of giving the result to your RecyclerViewAdapter, you always give a new empty list list = ArrayList(). You must use the received body inside your let-block to update the RecyclerViewAdapter.

viewModel.weatherstate.observe(viewLifecycleOwner) {
data-&gt;
data.body()?.let { body -&gt;
weatheradapter.updateInfo(
list = body
)
}
}

You can simplify your Adapter by using ListAdapter. It will manage updating the list and animate any changed (see also DiffCallback for better update handling).

huangapple
  • 本文由 发表于 2023年3月8日 19:26:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75672413.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定