使用recyclerview和改造无法显示获取的数据

时间:2019-11-29 13:53:56

标签: android android-fragments kotlin android-recyclerview retrofit2

我已经使用改造库获取了响应,我在添加recyclerView之前对其进行了仔细检查,该库工作正常,但是在添加recyclerView和适配器后,数据无法显示。

ApiService.kt

package com.kunalrai.githubtrends

import com.squareup.moshi.Moshi
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import retrofit2.http.GET

private const val BASE_URL = "https://github-trending-api.now.sh"

val moshi: Moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(BASE_URL)
    .build()

interface ApiService {
    @GET("repositories")
    fun getRepos(): Call<List<Repo>>
}

object Api {
    val RETROFIT_SERVICE : ApiService by lazy { retrofit.create(ApiService::class.java) }
}

ListAdapter.kt

package com.kunalrai.githubtrends

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions

class ListAdapter(private val context: Context?, private val repoList: List<Repo>) : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

        val view = LayoutInflater.from(parent.context).inflate(R.layout.repo_item,parent,false)
        return MyViewHolder(view)
    }

    override fun getItemCount(): Int {
        Log.i("reposize: ",""+repoList.size)
        return repoList.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

        holder.author.text = repoList[position].author

        holder.repo.text = repoList[position].name

        Glide.with(context!!).load(repoList[position].avatar)
            .apply(RequestOptions().centerCrop())
            .into(holder.image)
    }

    class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {

        val author: TextView = itemView!!.findViewById(R.id.owner_name)
        val image: ImageView = itemView!!.findViewById(R.id.owner_image)
        val repo: TextView = itemView!!.findViewById(R.id.repo_name)


    }
}

ListViewModel.kt

package com.kunalrai.githubtrends

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class ListViewModel : ViewModel() {
    var repoList: MutableLiveData<List<Repo>> = MutableLiveData(listOf())

    fun getRepos(): MutableLiveData<List<Repo>>{

            repoList = MutableLiveData()
            loadRepos()

        return repoList
    }

    private fun loadRepos() {
        Api.RETROFIT_SERVICE.getRepos().enqueue( object: Callback<List<Repo>> {
            override fun onFailure(call: Call<List<Repo>>, t: Throwable) {
                Log.i("Failure: ", t.message)
            }

            override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) {
                if(response.body() != null){
                    repoList.value = response.body()
                    Log.i("response.body :",""+response.body())
                }

            }
        })
    }

}


ListFragment.kt

package com.kunalrai.githubtrends

import androidx.lifecycle.ViewModelProviders
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 androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kunalrai.githubtrends.databinding.ListFragmentBinding


class ListFragment : Fragment() {

    companion object {
        fun newInstance() = ListFragment()
    }

    private val viewModel: ListViewModel by lazy {
        ViewModelProviders.of(this).get(ListViewModel::class.java)
    }

    private lateinit var binding: ListFragmentBinding
    var recyclerView: RecyclerView? = null
    lateinit var listAdapter: ListAdapter
    var repoList: List<Repo> = listOf()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

//        viewModel.getRepos().observe(this,
//            Observer<List<Repo>> {
//                it?.let { repoList ->
//                    this.repoList = repoList
//                    Log.i("inside observe",""+repoList)
//                }
//            })
    }

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

        viewModel.getRepos().observe(this,
            Observer<List<Repo>> {
                it?.let { repoList ->
                    this.repoList = repoList
                    Log.i("inside observe",""+repoList)
                    listAdapter = ListAdapter(context, repoList)
                    recyclerView?.adapter = listAdapter
                }
            })

        recyclerView = view.findViewById(R.id.rv_repo_list)
        recyclerView?.layoutManager = LinearLayoutManager(context)
        recyclerView?.setHasFixedSize(true)


    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = ListFragmentBinding.inflate(inflater, container, false)
        binding.lifecycleOwner

        binding.viewmodel = viewModel
        setHasOptionsMenu(true)

//        recyclerView = view?.findViewById(R.id.rv_repo_list)
//        recyclerView?.layoutManager = LinearLayoutManager(context)
//        recyclerView?.setHasFixedSize(true)
//        listAdapter = ListAdapter(context, repoList)
//        recyclerView?.adapter = listAdapter


        return binding.root
    }

}

Repo.kt

package com.kunalrai.githubtrends

import com.squareup.moshi.Json

data class Repo(
    @Json(name = "author")
    var author: String,
    @Json(name = "name")
    var name: String,
    @Json(name = "description")
    var desc: String,
    @Json(name = "avatar")
    var avatar: String,
    @Json(name = "language")
    var language: String,
    @Json(name = "url")
    var url: String,
    @Json(name = "stars")
    var stars: String,
    @Json(name = "forks")
    var forks: String
)

list_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewmodel"
            type="com.kunalrai.githubtrends.ListViewModel" />
    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ListFragment">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_repo_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>
</layout>

repo_item.xml

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <de.hdodenhof.circleimageview.CircleImageView
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/owner_image"
                android:layout_width="96dp"
                android:layout_height="96dp"
                app:civ_border_width="2dp"
                app:civ_border_color="#FF000000"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/owner_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

                <TextView
                    android:id="@+id/repo_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

Logcat:

2019-11-29 19:15:15.170 20890-20890/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2019-11-29 19:15:15.187 20890-20890/? E/Zygote: accessInfo : 1
2019-11-29 19:15:18.090 20890-20890/com.kunalrai.githubtrends E/RecyclerView: No adapter attached; skipping layout

清单文件中已授予Internet许可。在添加recyclerView之前成功检查了获取的响应。

黑屏是没有崩溃的输出。

2 个答案:

答案 0 :(得分:1)

我建议进行一些更改。

在ListAdapter中

class ListAdapter(private val context: Context?) : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {

  private val repoList = ArrayList<Repo>() //create an empty list first.

  fun resetList(newList: List<Repo>){ //update only when a list is available.

      repoList.clear()
      repoList.addAll(newList)
      notifyDataSetChanged() //you need this part to tell the adapter to redraw the views.
  }

 ... the rest of your List Adapter

然后在您的片段中

private lateinit var listAdapter: ListAdapter

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = ListFragmentBinding.inflate(inflater, container, false)
    binding.lifecycleOwner

    binding.viewmodel = viewModel
    setHasOptionsMenu(true)


    listAdapter = ListAdapter(context) //create adapter with emptyList
    recyclerView = view?.findViewById(R.id.rv_repo_list)
    recyclerView?.let{
        it.layoutManager = LinearLayoutManager(context)
        it.setHasFixedSize(true)
        it.adapter = listAdapter //we add the adapter here
    } 

    return binding.root
}

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

  viewModel.getRepos().observe(this,
    Observer<List<Repo>> {
        it?.let { repoList ->
            //you just need to repopulate/recycle the views in your adapter.
            //no need to recreate the adapter again.
            listAdapter.resetList(repoList) 
        }
    })
   }

答案 1 :(得分:0)

BASE_URL应该以{{1​​}}结尾,因此在基本URL的末尾添加/

/

未调用API,因为您初始化了repoList并调用了api(如果为null)。因此api永远不会调用,因此请删除不需要的if

BASE_URL = "https://github-trending-api.now.sh/"

在onviewCreated()中调用您的api

    var repoList: MutableLiveData<List<Repo>> = MutableLiveData(listOf())
    if(repoList == null) {
        repoList = MutableLiveData()
        loadRepos()
    }