[英]How can I pass the fragment context to the adapter?
我正在做一个项目,现在坚持了 3 天。 该项目使用适配器和片段读取 json。
json: https ://opendata.visitflanders.org/accessibility/activities/sport_v2.json
fragment_list_of_sports.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=".ListOfSportsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="List of sports and locations"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.022" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSportList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btnBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.049"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.976" />
</androidx.constraintlayout.widget.ConstraintLayout>
ListOfSportsFragment.kt:
package vives.be.bedoerikproject
import SportsAdapter
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.get
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_list_of_sports.*
import kotlinx.android.synthetic.main.fragment_list_of_sports.view.*
import org.json.JSONException
import org.json.JSONObject
class ListOfSportsFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_list_of_sports, container, false)
val sportList: ArrayList<SportModelClass> = ArrayList()
try {
// As we have JSON object, so we are getting the object
//Here we are calling a Method which is returning the JSON object
val obj = JSONObject("Sports.json")
// fetch JSONArray named users by using getJSONArray
val sportsArray = obj.getJSONArray("sports")
// Get the users data using for loop i.e. id, name, email and so on
for (i in 0 until sportsArray.length()) {
// Create a JSONObject for fetching single User's Data
val sport = sportsArray.getJSONObject(i)
// Fetch id store it in variable
val id = sport.getInt("business_product_id")
val name = sport.getString("name")
val city_name = sport.getString("city_name")
val postal_code = sport.getInt("postal_code")
val website = sport.getString("website")
val phone = sport.getString("phone1")
val email = sport.getString("email")
// Now add all the variables to the data model class and the data model class to the array list.
val sportDetails =
SportModelClass(id, name, postal_code, city_name, phone, email, website)
// add the details in the list
sportList.add(sportDetails)
}
} catch (e: JSONException) {
//exception
e.printStackTrace()
}
// Set the LayoutManager that this RecyclerView will use.
rvSportList.layoutManager = LinearLayoutManager(activity) //rv = reciycleview
// Adapter class is initialized and list is passed in the param.
val itemAdapter = SportsAdapter(requireContext(), sportList)
// adapter instance is set to the recyclerview to inflate the items.
rvSportList.adapter = itemAdapter
return view
}
}
运动适配器:
import vives.be.bedoerikproject.SportModelClass
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import vives.be.bedoerikproject.R
import kotlinx.android.synthetic.main.sport_model_layout.view.*
class SportsAdapter(val context: Context, val items: ArrayList<SportModelClass>) :
RecyclerView.Adapter<SportsAdapter.ViewHolder>() {
/**
* Inflates the item views which is designed in xml layout file
*
* create a new
* {@link ViewHolder} and initializes some private fields to be used by RecyclerView.
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(
R.layout.sport_model_layout,
parent,
false
)
)
}
/**
* Binds each item in the ArrayList to a view
*
* Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent
* an item.
*
* This new ViewHolder should be constructed with a new View that can represent the items
* of the given type. You can either create a new View manually or inflate it from an XML
* layout file.
*/
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items.get(position)
holder.name.text = item.name
holder.city_name.text = item.city_name
holder.postal_code.text = item.postal_code.toString()
holder.website.text = item.website
holder.phone1.text = item.phone1
holder.email.text = item.email
}
/**
* Gets the number of items in the list
*/
override fun getItemCount(): Int {
return items.size
}
/**
* A ViewHolder describes an item view and metadata about its place within the RecyclerView.
*/
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
// Holds the TextView that will add each item to
val name = view.name
val city_name = view.city_name
val postal_code = view.postal_code
val website = view.website
val phone1 = view.phone1
val email = view.email
}
}
SportModelClass.kt:
package vives.be.bedoerikproject
class SportModelClass (
val business_product_id : Int,
val name : String,
val postal_code : Int,
val city_name : String,
val phone1 : String,
val email : String,
val website : String
)
我在第 60 行的 ListOfSportsFragment 中收到一个错误: E/AndroidRuntime: FATAL EXCEPTION: main Process: vives.be.bedoerikproject, PID: 7302 java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.recyclerview.widget.RecyclerView$LayoutManager androidx.recyclerview.widget.RecyclerView.getLayoutManager()' on a null object reference at vives.be.bedoerikproject.ListOfSportsFragment.onCreateView(ListOfSportsFragment.kt:60) at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1764) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701) at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) Disconnected from the target VM, address: 'localhost:52495', transport: 'socket'
E/AndroidRuntime: FATAL EXCEPTION: main Process: vives.be.bedoerikproject, PID: 7302 java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.recyclerview.widget.RecyclerView$LayoutManager androidx.recyclerview.widget.RecyclerView.getLayoutManager()' on a null object reference at vives.be.bedoerikproject.ListOfSportsFragment.onCreateView(ListOfSportsFragment.kt:60) at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1764) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701) at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) Disconnected from the target VM, address: 'localhost:52495', transport: 'socket'
您可以在 xml 文件中设置布局管理器。
...
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSportList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
...
而且您不必将上下文传递给您的适配器,您可以像这样在 onCreateViewHolder 中访问上下文
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.sport_model_layout,
parent,
false
)
)
}
像这样使用 requireActivity() :
rvSportList.layoutManager = LinearLayoutManager(requireActivity())
您能否尝试将代码从 onCreateView 移动到片段上的 onViewCreated fun 并使用“context”而不是“requireContext()”。 希望它有帮助。
只有在片段onCreateView()
返回后,您才能像这样使用合成视图绑定。
使用诸如rvSportList.layoutManager = LinearLayoutManager(activity) //rv = reciycleview
类的合成方法将视图设置代码移动到例如onViewCreated()
。
另外值得注意的是,提供合成视图绑定的 kotlin-android-extensions 插件已被弃用。 考虑改用视图绑定。
这是你的错误:
java.lang.NullPointerException: Attempt to invoke virtual method
'androidx.recyclerview.widget.RecyclerView$LayoutManager
androidx.recyclerview.widget.RecyclerView.getLayoutManager()'
on a null object reference at
vives.be.bedoerikproject.ListOfSportsFragment.onCreateView(ListOfSportsFragment.kt:60)
它试图在应该是RecyclerView
的东西上调用方法( getLayoutManager()
),但它不是 - 它是空的。 不能在空对象上调用方法,所以你得到NullPointerException
这是第 60 行,日志告诉您正在发生错误:
rvSportList.layoutManager = LinearLayoutManager(activity) //rv = reciycleview
因此,如果问题是在 null RecyclerView
上调用方法,并且它发生在该行上,那么rvSportList
不是RecyclerView
,它是null 。
您从您正在使用的 Kotlin 综合扩展中获得了神奇的rvSportList
变量,该扩展已被弃用了很长时间。 您应该改用View Binding - 但与此同时,试试这个 - 查找视图的基本方法:
val rvSportList = view.findViewById<RecyclerView>(R.id.rvSportList)
rvSportList.layoutManager = LinearLayoutManager(requireContext())
// etc
您能否尝试将代码从 onCreateView 移动到片段上的 onViewCreated fun 并使用“上下文”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.