我已经使用改造库获取了响应,我在添加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之前成功检查了获取的响应。
黑屏是没有崩溃的输出。
答案 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()
}