I'm encountering a NullPointerException when trying to use VideoSupportFragment in my Activity. I've added the fragment directly to the Activity, but it throws this error.
FATAL EXCEPTION: main
Process: com.example.firstdemotv, PID: 32115
java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.leanback.widget.VerticalGridView androidx.leanback.app.RowsSupportFragment.getVerticalGridView()' on a null object reference
at androidx.leanback.app.PlaybackSupportFragment.setupChildFragmentLayout(PlaybackSupportFragment.java:780)
at androidx.leanback.app.PlaybackSupportFragment.onStart(PlaybackSupportFragment.java:955)
at androidx.fragment.app.Fragment.performStart(Fragment.java:3021)
at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:589)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:300)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
I've tried all the suggested solutions, but the only thing that fixes the issue is changing the fragment type from VideoSupportFragment to Fragment. This makes the fragment work correctly, but it also means I can't utilize the specific features of VideoSupportFragment anymore.
I have upgraded my leanback library version to 1.2.0-alpha04 from 1.0.0
my Listfragment which type is RowsSupportFragment()
class ListFragment : RowsSupportFragment() {
private var itemSelectedListener: ((DataModel.Result.Detail) -> Unit)? = null
private var itemClickListener: ((DataModel.Result.Detail) -> Unit)? = null
private val listRowPresenter = object : ListRowPresenter(FocusHighlight.ZOOM_FACTOR_MEDIUM) {
override fun isUsingDefaultListSelectEffect(): Boolean {
return false
}
}.apply {
shadowEnabled = false
}
private var rootAdapter: ArrayObjectAdapter = ArrayObjectAdapter(listRowPresenter)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = rootAdapter
onItemViewSelectedListener = ItemViewSelectedListener()
onItemViewClickedListener = ItemViewClickListener()
}
fun bindData(dataList: DataModel) {
dataList.result.forEachIndexed { index, result ->
val arrayObjectAdapter = ArrayObjectAdapter(ItemPresentor())
result.details.forEach {
arrayObjectAdapter.add(it)
}
val headerItem = HeaderItem(result.title)
val listRow = ListRow(headerItem, arrayObjectAdapter)
rootAdapter.add(listRow)
}
}
fun bindCastData(list: List<CastResponse.Cast>) {
val arrayObjectAdapter = ArrayObjectAdapter(CastItemPresenter())
list.forEach { content ->
arrayObjectAdapter.add(content)
}
val headerItem = HeaderItem("Cast & Crew")
val listRow = ListRow(headerItem, arrayObjectAdapter)
rootAdapter.add(listRow)}}
i'm calling my listFragment in two different screens one in DetialActivity : FragmentActivity()
class DetailActivity : FragmentActivity() {
private lateinit var binding: ActivityDetailBinding
lateinit var viewmodel: DetailViewmodel
val castFragment = ListFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_detail)
addFragment(castFragment)
val movieId = intent.getIntExtra("id", 0)
val repository = (application as MyApplication).tmdbRepo
viewmodel = ViewModelProvider(
owner = this,
factory = DetailViewmodelFactory(repository, movieId)
)[DetailViewmodel::class.java]
viewmodel.movieDetails.observe(this) {
when (it) {
is Response.Loading -> {
}
is Response.Success -> {
setData(it.data)
}
is Response.Error -> {
}
else -> {}
}
}
viewmodel.castDetails.observe(this) {
when (it) {
is Response.Loading -> {
}
is Response.Success -> {
if (!it.data?.cast.isNullOrEmpty()) {
castFragment.bindCastData(it.data?.cast!!)
}
}
is Response.Error -> {
}
else -> {}
}
}
binding.addToMylist.setOnKeyListener { view, keyCode, keyEvent ->
when (keyCode) {
KeyEvent.KEYCODE_DPAD_DOWN -> {
if (keyEvent.action == KeyEvent.ACTION_DOWN) {
castFragment.requestFocus()
}
}
}
false
}
binding.play.setOnClickListener {
val intent = Intent(this@DetailActivity, PlaybackActivity::class.java)
startActivity(intent)
}
}
and in HomeFragment : Fragment()
class HomeFragment : Fragment() {
private lateinit var binding: FragmentHomeBinding
val listFragment = ListFragment()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val transaction = requireActivity().supportFragmentManager.beginTransaction()
transaction.add(binding.listFragments.id, listFragment)
transaction.commit()
val gson = Gson()
val i: InputStream = requireContext().assets.open("movies.json")
val br = BufferedReader(InputStreamReader(i))
val dataList: DataModel = gson.fromJson(br, DataModel::class.java)
listFragment.bindData(dataList)
listFragment.setOnContentSelectedListener {
updateBanner(it)
}
listFragment.setOnItemClickListener {
val intent = Intent(requireActivity(), DetailActivity::class.java)
intent.putExtra("id", it.id)
startActivity(intent)
requireActivity().finish()
}
}