【发布时间】:2020-12-01 04:42:08
【问题描述】:
我正在尝试使用 Retrofit2 显示来自虚拟服务器 (json-server) 的 JSON 数据,并将其显示在放置在片段内的 RecyclerView 中。到目前为止,正在发生以下事件(使用日志信息发现):
- 主片段
CharactersListFragment.kt创建已启动。 - 只有
getItemCount()被调用。它返回 0。 -
OnCreateViewHolder()和onBindViewHolder()未被调用。 - 从服务器成功获取数据并传递给适配器(来自
CharactersListFragment.kt)
没有编译时错误,我的应用也没有崩溃,只是 RecyclerView 是空的。
这是我的代码文件:
- 带有 RecyclerView 的片段布局:
fragment_characters_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".CharactersListFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
- RecyclerView 行的布局:
fragment_character_recyclerview_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/character_card_view"
android:layout_width="match_parent"
android:layout_height="300dp"
android:elevation="15dp"
app:cardBackgroundColor="@color/violet_forcard"
app:cardCornerRadius="3dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/char_thumnail_img"
android:layout_width="143dp"
android:layout_height="150dp"
android:layout_marginStart="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.106"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/char_id_txt"
android:layout_width="190dp"
android:layout_height="53dp"
android:layout_marginTop="16dp"
android:fontFamily="@font/roboto"
android:text="Character ID: "
android:textAlignment="viewStart"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/char_thumnail_img"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/char_name_txt"
android:layout_width="190dp"
android:layout_height="53dp"
android:layout_marginTop="24dp"
android:fontFamily="@font/roboto"
android:text="Name: "
android:textAlignment="viewStart"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/char_thumnail_img"
app:layout_constraintTop_toBottomOf="@+id/char_id_txt" />
<TextView
android:id="@+id/char_descp_txt"
android:layout_width="359dp"
android:layout_height="wrap_content"
android:fontFamily="@font/roboto"
android:textAlignment="viewStart"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.461"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.918" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
- 片段的 Kotlin 类:
CharactersListFragment.kt
package com.example.marvelapp
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.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class CharactersListFragment : Fragment() {
private lateinit var charsAdapter: CharacterListAdapter
private lateinit var apiService: APIService
private var characters: MutableList<Character> = ArrayList()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
Log.i("INSIDE_FRAGMENT_ONCREATEVIEW", "Fragment creation initiated")
val v = inflater.inflate(R.layout.fragment_characters_list, container, false)
apiService = RestClient.client.create(APIService::class.java)
getCharacterList()
val recycler_view = v.findViewById(R.id.recycler_view) as RecyclerView
recycler_view.layoutManager = LinearLayoutManager(activity)
charsAdapter = CharacterListAdapter()
recycler_view.adapter = charsAdapter
return v
}
private fun getCharacterList(){
val call = apiService!!.get_characters()
call.enqueue(object: Callback<List<Character>> {
override fun onResponse(
call: Call<List<Character>>,
response: Response<List<Character>>
) {
val chars = response.body()
Log.i("get_character_succeeded_FOR_CALL", chars.toString())
if (chars != null){
characters.addAll(chars!!)
Log.i("character_ADD_CHECK_INSIDE_FRAGMENT", characters[0].toString())
charsAdapter.submitDataforcharList(characters)
}
}
override fun onFailure(call: Call<List<Character>>, t: Throwable) {
Log.e("get_character_failed", t.localizedMessage)
}
})
}
}
- 适配器的 Kotlin 类:
CharacterListAdapter.kt
package com.example.marvelapp
import android.text.Layout
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_character_recyclerview_list.view.*
class CharacterListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var charItems: List<Character> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
Log.i("INSIDE_ONCREATE_VIEWHOLDER", "reached")
return CharacterListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.fragment_character_recyclerview_list,
parent,
false))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder){
is CharacterListViewHolder ->{
Log.i("VIEWHOLDER_FOUND", "proceeding to bind")
holder.bind(charItems.get(position))
}
}
}
override fun getItemCount(): Int {
Log.i("INSIDE_ADAPTER_GET_ITEM_COUNT", charItems.size.toString())
return charItems.size
}
fun submitDataforcharList (characterlist: List<Character>){
Log.i("INSIDE_ADAPTER_SUBMIT_DATA", characterlist[0].toString())
charItems = characterlist
}
class CharacterListViewHolder
constructor(view: View): RecyclerView.ViewHolder(view){
val char_id = view.findViewById<TextView>(R.id.char_id_txt)
val char_name = view.findViewById<TextView>(R.id.char_name_txt)
val char_descp = view.findViewById<TextView>(R.id.char_descp_txt)
fun bind(character: Character){
Log.i("INSIDE_VIEWHOLDER_BIND", character.toString())
val id = Integer.toString(character.charId)
val id_mess = "Character ID: $id"
char_id.setText(id_mess)
val char_name_mess = "Name: ${character.charName}"
char_name.setText(char_name_mess)
char_descp.setText(character.charDescp)
}
}
}
-
Character模型类:
package com.example.marvelapp
data class Character(
val charId: Int,
val charName: String,
val charDescp: String,
){
}
我是一名 android 初学者,并且在这方面已经坚持了很长一段时间,任何帮助将不胜感激。 提前致谢!
【问题讨论】:
-
在
CharactersListFragment的onCreateView中,您正在执行getCharacterList()。所以从我对android的理解来看,这不是一个内联调用吗?我的意思是这个方法调用不会阻塞主线程吧?我认为您应该在收到数据后初始化适配器类。 -
您需要使用
charItems.addAll(characterlist)而不是charItems = characterlist。你还需要在它之后调用notifyDatasetChanged()。 -
目前您可能正在获取一些数据,并且您只是在更新适配器类中的数据列表,但您没有通知您的 recyclerview 刷新视图以显示新数据。因此,我认为如果您在设置新数据后只在适配器上调用
notifyDataSetChanged(),它应该可以工作。但我仍然建议您在收到来自getCharacterList()调用的数据后初始化 recyclerview。 -
非常感谢大家,原来我不得不重新排序
getCharacterList()的调用并添加notifyDatasetChanged()
标签: android kotlin android-fragments android-recyclerview