已获取API数据,但无法在Recycler View中显示

问题描述 投票:0回答:1

我目前面临API问题,问题是我得到的数据是200 OK,但即使没有错误适配器也无法显示数据,并且我收到了数据

这是主页片段

package com.example.papb_tubes

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.papb_tubes.databinding.FragmentHomeBinding
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class HomeFragment : Fragment() {

    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!

    private lateinit var apiService: ApiService
    private lateinit var weatherAdapter: WeatherAdapter

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        apiService = ApiConfig.getApiService("London") // Set initial city

        weatherAdapter = WeatherAdapter(object : WeatherAdapter.OnClickListener {
            override fun onClickItem(data: WeatherResponse) {
                // Handle item click if needed
            }
        })

        binding.rvHomepage.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = weatherAdapter
        }

        binding.ivPerson.setOnClickListener {
            // Navigate to profile fragment if needed
        }

        // Fetch initial weather data for London
        fetchWeatherData("London")
    }

    private fun fetchWeatherData(city: String) {
        apiService = ApiConfig.getApiService(city)

        apiService.getAllProvinsi(city).enqueue(object : Callback<WeatherResponse> {
            override fun onResponse(
                call: Call<WeatherResponse>,
                response: Response<WeatherResponse>
            ) {
                if (response.isSuccessful) {
                    val weatherResponse = response.body()
                    if (weatherResponse != null) {
                        Log.d("WeatherResponse", weatherResponse.toString())
                        weatherAdapter.submitData(weatherResponse)
                    } else {
                        Log.e("WeatherResponse", "Response body is null")
                    }
                } else {
                    Log.e("WeatherResponse", "Error: ${response.code()}")
                }
            }

            override fun onFailure(call: Call<WeatherResponse>, t: Throwable) {

            }
        })
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

这是适配器

package com.example.papb_tubes

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.papb_tubes.databinding.ItemRowBinding

class WeatherAdapter(
    private val onClickItem: OnClickListener // Use the correct interface name here
) : RecyclerView.Adapter<WeatherAdapter.ViewHolder>() {

    private val differCallback = object : DiffUtil.ItemCallback<WeatherResponse>() {
        override fun areItemsTheSame(oldItem: WeatherResponse, newItem: WeatherResponse): Boolean {
            return oldItem.id == newItem.id
        }
        override fun areContentsTheSame(oldItem: WeatherResponse, newItem: WeatherResponse): Boolean = oldItem.hashCode() == newItem.hashCode()

    }

    val differ = AsyncListDiffer(this, differCallback)
    fun submitData(value: WeatherResponse) = differ.submitList(listOf(value))
    inner class ViewHolder(private val binding: ItemRowBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(data: WeatherResponse) {
            val temp = (data.main.temp) - 273
            binding.apply {
                tvNamakota.text = data.name.toString()
                tvTemperatur.text = temp.toString()
                tvTipe.text = data.weather[0].description.toString()

                root.setOnClickListener {
                    onClickItem.onClickItem(data)
                }
            }
        }
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val data = differ.currentList[position]
        Log.d("WeatherAdapter", "Data size: ${differ.currentList.size}")
        data.let { holder.bind(data) }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return ViewHolder(ItemRowBinding.inflate(inflater,parent,false))
    }

    override fun getItemCount(): Int = differ.currentList.size

    interface OnClickListener {
        fun onClickItem(data: WeatherResponse)
    }
}

这是 apiconfig

package com.example.papb_tubes

import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class ApiConfig {
    companion object {
        private const val BASE_URL = "https://api.openweathermap.org/data/2.5/"
        private const val API_KEY = ""

        fun getApiService(city: String): ApiService {
            val loggingInterceptor =
                HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)

            val authInterceptor = Interceptor { chain ->
                val originalRequest = chain.request()
                val newUrl = originalRequest.url.newBuilder()

                    .addQueryParameter("appid", API_KEY)
                    .build()

                val newRequest = originalRequest.newBuilder()
                    .url(newUrl)
                    .build()

                chain.proceed(newRequest)
            }

            val client = OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .addInterceptor(authInterceptor)
                .build()

            val retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build()

            return retrofit.create(ApiService::class.java)
        }
    }
}

这就是服务

package com.example.papb_tubes

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface ApiService {
    @GET("weather")
        fun getAllProvinsi(
            @Query("q") city:String,
    ): Call<WeatherResponse>
}

这是 homefragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeFragment"
    android:background="@color/primary">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_ellipse"
        android:id="@+id/iv_elipse_1"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_ellipse"
        android:id="@+id/iv_elipse_2"
        android:layout_marginTop="300dp"
        android:layout_marginLeft="160dp"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_ellipse"
        android:id="@+id/iv_elipse_3"
        android:layout_marginTop="500dp"
        android:layout_marginLeft="0dp"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_rectangle"
        android:layout_gravity="right"
        android:id="@+id/iv_rectangle1"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_rectangle"
        android:layout_gravity="right|bottom"
        android:id="@+id/iv_rectangle2"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_rectangle"
        android:layout_gravity="left|center"
        android:scaleX="-1"
        android:id="@+id/iv_rectangle3"/>
    <LinearLayout
        android:id="@+id/ll_homepage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_marginTop="20sp"
        android:layout_marginBottom="20sp">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingLeft="20dp"
        android:paddingTop="30dp"
        android:paddingRight="20dp"
        >

        <TextView
            android:id="@+id/tv_username_homepage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:fontFamily="@font/poppins_r"
            android:text="Welcome, Username"
            android:textSize="15sp"
            android:textStyle="normal"
            android:textColor="@color/white"/>

        <ImageView
            android:id="@+id/iv_person"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_weight="1"
            android:paddingLeft="90dp"
            android:src="@drawable/baseline_person_24" />
    </LinearLayout>
        <EditText
            android:id="@+id/etSearch"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:hint="Search City"
            android:imeOptions="actionSearch"
            android:inputType="text"
            android:layout_margin="16dp"/>
    <TextView
        android:layout_marginTop="30dp"
        android:id="@+id/tv_home"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:fontFamily="@font/poppins_r"
        android:text="Home"
        android:textSize="20sp"
        android:textStyle="bold"
        android:textColor="@color/white"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_homepage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp" />
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv_weather"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"/>
    </LinearLayout>

</FrameLayout>

我希望我能收到可以在回收器视图中显示的数据

我刚刚尝试过的就像

  1. 添加日志确保数据200 OK
  2. 我使用像submitList等函数来实际创建回收器视图但失败了

编辑:

  1. 我使用按钮手动在搜索栏上插入值,但最终导致崩溃
android json kotlin android-fragments android-recyclerview
1个回答
0
投票

Welp我只是弄清楚,使用logcat会非常有用,我发现在分配数据类类型时我完全错误,有float类型,但我使用Extension is Int分配它

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.