0
votes

I am trying to create a swipeable tab layout for an Android app I'm making. My first tab worked fine, but now that I've added the second tab, when I open the app, it crashes with the following error:

2019-11-01 20:26:17.457 26813-26813/com.example.nhlstats E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.nhlstats, PID: 26813
    kotlin.KotlinNullPointerException
        at com.example.nhlstats.ui.fragments.StandingsFragment.<init>(StandingsFragment.kt:24)
        at com.example.nhlstats.ui.adapters.HomePagerAdapter.getItem(HomePagerAdapter.kt:15)
        at androidx.fragment.app.FragmentPagerAdapter.instantiateItem(FragmentPagerAdapter.java:170)
        at androidx.viewpager.widget.ViewPager.addNewItem(ViewPager.java:1010)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1224)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
        at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24545)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:995)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:742)
        at android.view.View.measure(View.java:24545)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3006)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1833)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2122)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7598)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:725)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

I have put breakpoints in both methods of the fragment, but it crashes before it hits either one. I'm not sure what could be null based on that error output, especially if it isn't even getting into the fragment to hit those breakpoints.

My fragment class is here:

class StandingsFragment: Fragment() {
    private lateinit var binding: FragmentStandingsBinding
    private val rowHeaderList: List<RowHeader> = emptyList()
    private val columnHeaderList: List<ColumnHeader> = emptyList()
    private val cellList: List<List<Cell>> = emptyList()
    private val tableView: TableView = TableView(requireContext())
    private val tableViewAdapter: StandingsTableViewAdapter by lazy { StandingsTableViewAdapter(requireContext())}

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_standings, container, false)
        binding.lifecycleOwner = this

        return binding.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        tableView.adapter = tableViewAdapter
        tableViewAdapter.setAllItems(columnHeaderList, rowHeaderList, cellList)
    }
}

and this is my adapter class:

class HomePagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm){

    override fun getItem(position: Int): Fragment {
        when (position) {
            0 -> return ScoreboardFragment()
            1 -> return StandingsFragment()
        }

        return ScoreboardFragment()
    }

    override fun getCount(): Int {
        return 2
    }

    override fun getPageTitle(position: Int): CharSequence? {
        when (position) {
            0 -> return "Scores"
            1 -> return "Standings"
        }

        return "Scores"
    }
}

Thanks in advance.

1
My first suspect would be context!! in private val tableView: TableView = TableView(context!!).Michael Butscher

1 Answers

3
votes

It happens cause you are accessing the Fragment's Context before it's available and you are unwrapping it with !!. This throws a KotlinNullPointerException.

private val tableView: TableView = TableView(context!!)
private val tableViewAdapter: StandingsTableViewAdapter = StandingsTableViewAdapter(context!!)

To fix it, you can make it lazy so it will be evaluated only when you will actually use it (e.g. in your onViewCreated):

private val tableView: TableView by lazy { TableView(requireContext()) }
private val tableViewAdapter: StandingsTableViewAdapter by lazy { StandingsTableViewAdapter(requireContext()) }

Remember you can use requireContext() instead of context!! which throws a more clear exception.