你好,我正在做一个小应用程序,我想在应用程序上显示我的php api数据。但是Recycler View在适配器代码运行之前发送了这个消息2022-04-25 00:41:36.662 13593-13593/net.robcorp.finalapp E/RecyclerView: No adapter attached; skipping layout
,因为这个消息2022-04-25 00:41:36.907 13593-13593/net.robcorp.finalapp I/System.out: [Drivers(pos=1, name=Charles Leclerc, nb=16, points=71, title=Ferrari), Drivers(pos=2, name=Esteban Ocon, nb=31, points=20, title=Alpine)]
在前一个消息之后显示,并且应该在适配器之前运行。下面是DriversFragment.kt:
package net.robcorp.finalapp
import android.content.Context
import android.graphics.Insets.add
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.core.view.OneShotPreDrawListener.add
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.FragmentDriversBinding
import net.robcorp.finalapp.drivers.DriverFragmentAdapter
import net.robcorp.finalapp.drivers.Drivers
import org.json.JSONArray
class DriversFragment : Fragment(R.layout.fragment_drivers) {
private lateinit var recyclerView: RecyclerView
private lateinit var myAdapter: DriverFragmentAdapter;
lateinit var binding: FragmentDriversBinding
private val drivers = ArrayList<Drivers>()
val url = "https://robcorp.net/f1api/getdrivers.php"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentDriversBinding.inflate(layoutInflater)
recyclerView = binding.driversRecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
recyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
fun downloadDrivers() {
val task = Volley.newRequestQueue(this.context)
val request = StringRequest(Request.Method.GET, url, {
response ->
val data = response.toString()
val jArray = JSONArray(data)
// Log.e("Error",response.toString())
for (i in 0..jArray.length()-1) {
val json_data = jArray.getJSONObject(i)
// Log.e("Jobject",json_data.toString())
val pos = i+1
val name = json_data.getString("Name")
val nb = json_data.getString("NB")
val points = json_data.getString("Points")
val title = json_data.getString("Title")
val driver = Drivers(pos, name, nb, points, title)
drivers.add(driver)
}
println(drivers)
myAdapter.notifyDataSetChanged()
}, {
error ->
println(error)
})
task.add(request)
}
}
下面是驱动程序碎片适配器.kt:
package net.robcorp.finalapp.drivers
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.DriverListBinding
class DriverFragmentAdapter(private var driversList: List<Drivers>): RecyclerView.Adapter<DriverFragmentAdapter.MyViewHolder>() {
class MyViewHolder(val binding: DriverListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(driver: Drivers) {
val context = itemView.context
val pos = itemView.findViewById<TextView>(R.id.driver_position)
val bar = itemView.findViewById<TextView>(R.id.driver_bar)
val name = itemView.findViewById<TextView>(R.id.driver_name)
val nb = itemView.findViewById<TextView>(R.id.driver_number)
val team = itemView.findViewById<TextView>(R.id.driver_team)
val points = itemView.findViewById<TextView>(R.id.driver_points)
pos.text = driver.pos.toString()
name.text = driver.name
nb.text = driver.nb
team.text = driver.title
points.text = driver.points
if (driver.title == "Ferrari") {
bar.background = ContextCompat.getDrawable(context, R.drawable.ferrari_bar)
} else if (driver.title == "Alpine") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alpine_bar)
} else if (driver.title == "Red Bull") {
bar.background = ContextCompat.getDrawable(context, R.drawable.redbull_bar)
} else if (driver.title == "Mercedes") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mercedes_bar)
} else if (driver.title == "McLaren") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mclaren_bar)
} else if (driver.title == "Alfa Romeo") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alfaromeo_bar)
} else if (driver.title == "AlphaTauri") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alphatauri_bar)
} else if (driver.title == "Williams") {
bar.background = ContextCompat.getDrawable(context, R.drawable.williams_bar)
} else if (driver.title == "Aston Martin") {
bar.background = ContextCompat.getDrawable(context, R.drawable.astonmartin_bar)
} else if (driver.title == "Haas") {
bar.background = ContextCompat.getDrawable(context, R.drawable.haas_bar)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(DriverListBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun getItemCount(): Int {
return driversList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val driver = driversList[position]
holder.binding.apply {
println("je suis dans le binding")
holder.bind(driver)
}
}
fun setDriversList(driversList: List<Drivers>) {
this.driversList = driversList
notifyDataSetChanged()
}
}
fragment_drivers.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- TODO: Update blank fragment layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/primary"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp">
<TextView
android:id="@+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:fontFamily="@font/marianneb"
android:text="Pilotes"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="25sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/drivers_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="@+id/header"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
driver_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:elevation="8dp"
android:orientation="horizontal"
android:padding="10dp"
android:background="@drawable/rectangle">
<TextView
android:id="@+id/driver_position"
android:layout_width="30dp"
android:layout_height="match_parent"
android:fontFamily="@font/marianneb"
android:text="1"
android:textColor="@color/black"
android:textSize="25sp"
android:textAlignment="center"/>
<ImageView
android:id="@+id/driver_bar"
android:layout_width="20px"
android:layout_height="match_parent"
android:background="@drawable/ferrari_bar"/>
<LinearLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/driver_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fontFamily="@font/marianneb"
android:text="Charles Leclerc"
android:textColor="@color/black"
android:textSize="15sp"
android:layout_marginStart="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/driver_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="@font/mariannem"
android:text="16"
android:textColor="@color/black"
android:textSize="10sp" />
<TextView
android:id="@+id/driver_team"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="@font/mariannem"
android:text="Ferrari"
android:textColor="@color/black"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/driver_points"
android:layout_width="50dp"
android:layout_height="match_parent"
android:fontFamily="@font/marianneb"
android:text="578"
android:textColor="@color/black"
android:textSize="25sp"/>
</LinearLayout>
2条答案
按热度按时间n8ghc7c11#
这是一个无害的警告。由于RecyclerView已经在布局中,它试图在视图层次结构变为可见时绘制它,看到没有分配适配器,所以它只是发出警告,而不绘制它。
也许创建适配器(带有空列表)并在膨胀视图时立即分配它,然后在数据准备就绪时更新其列表会更简洁。
顺便说一下,在
onCreate
中膨胀布局是不正确的。应该在onCreateView
中完成。编辑:
这里的代码将布局扩大了两次,一次用于变量
v
,一次用于属性binding
。首先,没有理由扩大两次。其次,由于使用v
作为onCreateView
的返回值,因此对binding
中的视图所做的任何操作都是无意义的,对实际在屏幕上的视图没有任何影响。您应该只扩大视图一次(使用绑定)并返回绑定的视图:
另外,在
onViewCreated()
中设置视图比在onCreateView()
中设置视图更合适。如果你这样做,你实际上可以通过将视图ID传递给Fragment构造函数,将inflation移动到超构造函数调用中,然后绑定到现有视图,而不是inflation绑定。看起来如下:yebdmbv42#
为了给@Tenfour04的回答增加一点清晰度。
你不能删除这个。他们告诉你如何正确地膨胀它与视图绑定
还有一个小提示:
您应该这样销毁绑定以防止内存泄漏
现在到了这个问题。
最后一个问题很可能是您的布局。由于所有内容都包含在线性布局中,约束布局位置线不起任何作用。我删除了无用的线性布局。希望这样可以修复任何问题。
对不起的格式btw只是使用CTRL + ALT + L自动格式化它