use*_*730 6 android android-fragments kotlin android-recyclerview
我一直在网上跟踪创建RecyclerView的示例。我唯一不同的是将RecyclerView放入Fragment中,而不是将其放入MainActivity中。RecyclerView可以很好地显示数据。但是,当我导航到另一个Fragment时,应用程序崩溃,并抛出与RecyclerView相关的异常:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
Run Code Online (Sandbox Code Playgroud)
这是一个重现的最小示例:
主要活动:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_layout)
}
}
Run Code Online (Sandbox Code Playgroud)
main_layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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="match_parent">
<fragment class="package.RecyclerFragment"
android:id="@+id/fragment"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
RecyclerFragment:
class RecyclerFragment : Fragment() {
private val data = listOf("Moscow", "Washington")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
setHasOptionsMenu(true)
val view = inflater.inflate(R.layout.recycler_list, container, false)
view.findViewById<RecyclerView>(R.id.list)?.apply {
adapter = RecyclerAdapter(data)
}
return view
}
override fun onCreateOptionsMenu(menu: Menu?, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
return when (item?.itemId) {
R.id.navigate -> {
fragmentManager?.beginTransaction()?.replace(R.id.fragment, HelloFragment())?.commit()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
Run Code Online (Sandbox Code Playgroud)
recycler_list:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list"
android:orientation="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)
RecyclerAdapter:
class RecyclerAdapter(private val data: List<String>):
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
inner class ViewHolder(val view: CardView): RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(root: ViewGroup, viewType: Int): ViewHolder {
val listItem = LayoutInflater.from(root.context)
.inflate(R.layout.list_item, root, false) as CardView
return ViewHolder(listItem)
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.view.findViewById<TextView>(R.id.text).text = data[position]
}
override fun getItemCount() = data.size
}
Run Code Online (Sandbox Code Playgroud)
项目清单:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_margin="5sp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20sp"
android:textSize="20sp"
android:id="@+id/text"/>
</android.support.v7.widget.CardView>
Run Code Online (Sandbox Code Playgroud)
菜单:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/navigate"
android:title="Navigate"
app:showAsAction="ifRoom"/>
</menu>
Run Code Online (Sandbox Code Playgroud)
HelloFragment:
class HelloFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.hello, container, false)
}
}
Run Code Online (Sandbox Code Playgroud)
你好:
<?xml version="1.0" encoding="utf-8"?>
<TextView android:text="Hello"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"/>
Run Code Online (Sandbox Code Playgroud)
此实现有问题吗?如何在片段中使用RecyclerView?
方法一
只是不要RecyclerView在布局中用作父级RecyclerFragment。LinearLayout像这样把它包起来:
recycler_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="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
方法 2
在您当前的实现中,您已从 xml 添加RecyclerFragment,但当您尝试将其替换为 时HelloFragment,它不会被替换,而是将在其上方或下方添加新片段。
为了正确实现这一点,您应该RecyclerFragment从 Activity 的onCreate方法中添加如下所示的方法,并将其从 xml 中删除:
主要活动
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager.beginTransaction()
.add(R.id.root,RecyclerFragment())
.commit()
}
}
Run Code Online (Sandbox Code Playgroud)
活动主文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
当您想要替换选项项上的片段时,请单击如下所示:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.navigate -> {
requireActivity().supportFragmentManager.beginTransaction().replace(R.id.root, HelloFragment(), "Hello")
.commit()
true
}
else -> super.onOptionsItemSelected(item)
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您之前的片段将被删除,并添加新的片段。
| 归档时间: |
|
| 查看次数: |
305 次 |
| 最近记录: |