Reputation: 1
I have encountered a puzzling problem. When I create a Fragment in an Android View and create a ViewBinding inside the Fragment, and then declare android:configChanges="orientation|screenSize|screenLayout"
in the manifest file, why does calling the ViewBinding created inside the Fragment by calling the Activity's onMultiWindowModeChanged()
cause NPE of the ViewBinding created inside the Fragment when the screen is rotated?
Following is my source code:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewPagerAdapter: ViewPagerAdapter
private lateinit var fragmentAdapter: FragmentAdapter
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewPagerAdapter = ViewPagerAdapter(this)
fragmentAdapter = FragmentAdapter()
binding.viewPager.adapter = viewPagerAdapter
}
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration) {
super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig)
fragmentAdapter.changeListStaggeredGridLayout()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
fragmentAdapter.changeListStaggeredGridLayout()
}
}
class FragmentAdapter : Fragment() {
private var _binding: RecycleViewMainBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = RecycleViewMainBinding.inflate(inflater, container, false)
binding.recycleView.adapter = RecycleViewAdapter((1..30).toList())
changeListStaggeredGridLayout()
return binding.root
}
// This method is called when the external activity triggers onMultiWindowModeChanged() and onConfigurationChanged()
// Then it reports an error NPE: binding not initialized
fun changeListStaggeredGridLayout() {
val screenWidthDp = (Resources.getSystem().displayMetrics.widthPixels).pxToDp
val screenHeightDp = (Resources.getSystem().displayMetrics.heightPixels).pxToDp
binding.recycleView.apply {
layoutManager = if (screenHeightDp >= 600) {
when {
screenWidthDp in 600..840 -> StaggeredGridLayoutManager(
2, StaggeredGridLayoutManager.VERTICAL
)
screenWidthDp > 840 -> StaggeredGridLayoutManager(
3, StaggeredGridLayoutManager.VERTICAL
)
else -> LinearLayoutManager(this.context)
}
} else LinearLayoutManager(this.context)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
class ViewPagerAdapter(context: Context) :
FragmentStateAdapter(context as MainActivity) {
override fun getItemCount(): Int = 1
override fun createFragment(position: Int): Fragment {
return FragmentAdapter()
}
}
class RecycleViewAdapter(private val list: List<Int>) :
RecyclerView.Adapter<RecycleViewAdapter.ViewHolder>() {
inner class ViewHolder(binding: CardViewMainBinding) :
RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding =
CardViewMainBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
}
override fun getItemCount(): Int {
return list.size
}
}
Upvotes: 0
Views: 18