Why is val rv: RecyclerView = findViewById(R.id.material_list_rv)
returning null?
MainActivity
class MainActivity : AppCompatActivity() {
var adaptor: MaterialListAdaptor = MaterialListAdaptor()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<MaterialListFragment>(R.id.fragment_container_view)
}
}
initRecyclerView()
setRecyclerViewData()
}
private fun initRecyclerView(){
val rv: RecyclerView = findViewById(R.id.material_list_rv)
rv.layoutManager = LinearLayoutManager(this@MainActivity)
rv.adapter = adaptor
}
private fun setRecyclerViewData(){
val l = DataSource.createMaterialList()
adaptor.setDataSet(l)
}
}
activity_main
<?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">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MaterialListFragment
class MaterialListFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_material_list, container, false)
}
}
fragment_material_list
<?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=".MaterialListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/material_list_rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/material_list_rv_list_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
You placed the call to findViewById
in MainActivity.onCreate
. It's too early for that, the Fragment's view hasn't been created at that point.
You should be looking for the view in your MaterialListFragment
. If you call findViewById
in onCreateView
, it will work. Like this:
val root = inflater.inflate(R.layout.fragment_material_list, container, false)
val rv = root.findViewById(R.id. material_list_rv)
// Do whatever (eg assign rv to a field in the Fragment to use it later)
return root
Even if your code worked, try to have Activities, Fragments and custom Views manage their own children.
If the upper containers dive deep into their children, it's very easy to make mistakes (like the one here!) and you lose the ability to update internal details of Fragments and Views without breaking the containing Activity.
To orient yourself, keep this in mind (though this diagram is EXTREMELY simplified):