Weather app #16 : Список прогноза по дням

MainFragment

import android.Manifest
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.activityViewModels
import com.android.volley.Request
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.android.material.tabs.TabLayoutMediator
import com.meter_alc_rgb.weatherappcursey.MainViewModel
import com.meter_alc_rgb.weatherappcursey.R
import com.meter_alc_rgb.weatherappcursey.adapters.VpAdapter
import com.meter_alc_rgb.weatherappcursey.adapters.WeatherModel
import com.meter_alc_rgb.weatherappcursey.databinding.FragmentMainBinding
import com.squareup.picasso.Picasso
import org.json.JSONObject

const val API_KEY = "Ваш API ключь"

class MainFragment : Fragment() {
private val fList = listOf(
HoursFragment.newInstance(),
DaysFragment.newInstance()
)
private val tList = listOf(
"Hours",
"Days"
)
private lateinit var pLauncher: ActivityResultLauncher<String>
private lateinit var binding: FragmentMainBinding
private val model: MainViewModel by activityViewModels()

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
checkPermission()
init()
updateCurrentCard()
requestWeatherData("Berlin")
}

private fun init() = with(binding){
val adapter = VpAdapter(activity as FragmentActivity, fList)
vp.adapter = adapter
TabLayoutMediator(tabLayout, vp){
tab, pos -> tab.text = tList[pos]
}.attach()

}

private fun updateCurrentCard() = with(binding){
model.liveDataCurrent.observe(viewLifecycleOwner){
val maxMinTemp = "${it.maxTemp}Cº/${it.minTemp}Cº"
tvData.text = it.time
tvCity.text = it.city
tvCurrentTemp.text = it.currentTemp
tvCondition.text = it.condition
tvMaxMin.text = maxMinTemp
Picasso.get().load("https:" + it.imageUrl).into(imWeather)
}
}

private fun permissionListener(){
pLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()){
Toast.makeText(activity, "Permission is $it", Toast.LENGTH_LONG).show()
}
}

private fun checkPermission(){
if(!isPermissionGranted(Manifest.permission.ACCESS_FINE_LOCATION)){
permissionListener()
pLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}

private fun requestWeatherData(city: String){
val url = "https://api.weatherapi.com/v1/forecast.json?key=" +
API_KEY +
"&q=" +
city +
"&days=" +
"3" +
"&aqi=no&alerts=no"
val queue = Volley.newRequestQueue(context)
val request = StringRequest(
Request.Method.GET,
url,
{
result -> parseWeatherData(result)
},
{
error -> Log.d("MyLog", "Error: $error")
}
)
queue.add(request)
}

private fun parseWeatherData(result: String) {
val mainObject = JSONObject(result)
val list = parseDays(mainObject)
parseCurrentData(mainObject, list[0])
}

private fun parseDays(mainObject: JSONObject): List<WeatherModel>{
val list = ArrayList<WeatherModel>()
val daysArray = mainObject.getJSONObject("forecast")
.getJSONArray("forecastday")
val name = mainObject.getJSONObject("location").getString("name")
for (i in 0 until daysArray.length()){
val day = daysArray[i] as JSONObject
val item = WeatherModel(
name,
day.getString("date"),
day.getJSONObject("day").getJSONObject("condition")
.getString("text"),
"",
day.getJSONObject("day").getString("maxtemp_c"),
day.getJSONObject("day").getString("mintemp_c"),
day.getJSONObject("day").getJSONObject("condition")
.getString("icon"),
day.getJSONArray("hour").toString()
)
list.add(item)
}
model.liveDataList.value = list
return list
}

private fun parseCurrentData(mainObject: JSONObject, weatherItem: WeatherModel){
val item = WeatherModel(
mainObject.getJSONObject("location").getString("name"),
mainObject.getJSONObject("current").getString("last_updated"),
mainObject.getJSONObject("current")
.getJSONObject("condition").getString("text"),
mainObject.getJSONObject("current").getString("temp_c"),
weatherItem.maxTemp,
weatherItem.minTemp,
mainObject.getJSONObject("current")
.getJSONObject("condition").getString("icon"),
weatherItem.hours
)
model.liveDataCurrent.value = item
}

companion object {
@JvmStatic
fun newInstance() = MainFragment()
}
}

DaysFragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.meter_alc_rgb.weatherappcursey.MainViewModel
import com.meter_alc_rgb.weatherappcursey.adapters.WeatherAdapter
import com.meter_alc_rgb.weatherappcursey.databinding.FragmentDaysBinding

class DaysFragment : Fragment() {
private lateinit var adapter: WeatherAdapter
private lateinit var binding: FragmentDaysBinding
private val model: MainViewModel by activityViewModels()

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentDaysBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
model.liveDataList.observe(viewLifecycleOwner){
adapter.submitList(it.subList(1, it.size))
}
}

private fun init() = with(binding){
adapter = WeatherAdapter()
rcView.layoutManager = LinearLayoutManager(activity)
rcView.adapter = adapter
}

companion object {
@JvmStatic
fun newInstance() = DaysFragment()
}
}

WeatherAdapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.meter_alc_rgb.weatherappcursey.R
import com.meter_alc_rgb.weatherappcursey.databinding.ListItemBinding
import com.squareup.picasso.Picasso

class WeatherAdapter : ListAdapter<WeatherModel, WeatherAdapter.Holder>(Comparator()) {

class Holder(view: View) : RecyclerView.ViewHolder(view){
val binding = ListItemBinding.bind(view)

fun bind(item: WeatherModel) = with(binding){
tvDate.text = item.time
tvCondition.text = item.condition
tvTemp.text = item.currentTemp.ifEmpty { "${item.maxTemp}ºC / ${item.minTemp}ºC" }
Picasso.get().load("https:" + item.imageUrl).into(im)
}
}

class Comparator : DiffUtil.ItemCallback<WeatherModel>(){
override fun areItemsTheSame(oldItem: WeatherModel, newItem: WeatherModel): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: WeatherModel, newItem: WeatherModel): Boolean {
return oldItem == newItem
}

}

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

override fun onBindViewHolder(holder: Holder, position: Int) {
holder.bind(getItem(position))
}
}

fragment_days

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rcView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.DaysFragment">

</androidx.recyclerview.widget.RecyclerView>

2 комментария для “Weather app #16 : Список прогноза по дням”

  1. Добрый день! Подскажите, в чем может быть проблема, подчеркивает красным list в методе parseDays (model.liveDataList.value = list) в MainFragment, а в DaysFragment в методе onViewCreated также подчеркивает красным init(it) (в строке adapter.submitList(init(it)))

Добавить комментарий

Ваш адрес email не будет опубликован.