Search code examples
androidandroid-studiokotlinspinner

Spinner is always null in Kotlin


Edit: To clarify things since they're a bit messy, my spinner is in the signUpFragment class, this is the class for a fragment which is inside a viewPager that's inside a fragment called sign_up_login, I'm setting the viewcontent to the sign_up_login fragment from my main aciticity. I'm getting the error on my spinner in the signUpFragment.kt which is country_list which says "null object refrence"

My Spinner is in a fragment in a ViewPager inside another fragment, the code for the spinner is:

class signupFragment : Fragment() {

val values: Array<String> = arrayOf("Test1", "Test2", "Test3")

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val adapter = ArrayAdapter(requireContext(),
        android.R.layout.simple_spinner_item, values)
    country_list.adapter = adapter


   country_list.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
        override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
            Toast.makeText(requireContext(), "Selected "+ values[p2], Toast.LENGTH_SHORT).show()
        }

        override fun onNothingSelected(p0: AdapterView<*>?) {
        }

    }

}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_signup, container, false)
}

}

This fragment is in a frame layout which is inside a fragment in a view pager contained in another fragment called fragment_sign_up_login. The XML file for signUpFragment is:

<?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=".signupFragment">

<com.google.android.material.textfield.TextInputEditText
    android:id="@+id/lastNameInput"
    android:layout_width="150dp"
    android:layout_height="50dp"
    android:layout_marginTop="30dp"
    android:layout_marginEnd="56dp"
    android:hint="Last Name"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/passwordSignUp" />

<EditText
    android:id="@+id/email_signUp"
    android:layout_width="300dp"
    android:layout_height="50dp"
    android:layout_marginTop="10dp"
    android:ems="10"
    android:hint="Email"
    android:inputType="textEmailAddress"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.textfield.TextInputEditText
    android:id="@+id/firstNameInput"
    android:layout_width="150dp"
    android:layout_height="50dp"
    android:layout_marginTop="30dp"
    android:hint="First Name"
    app:layout_constraintEnd_toStartOf="@+id/lastNameInput"
    app:layout_constraintTop_toBottomOf="@+id/passwordSignUp" />

<EditText
    android:id="@+id/editTextNumber"
    android:layout_width="70dp"
    android:layout_height="48dp"
    android:layout_marginStart="54dp"
    android:layout_marginTop="30dp"
    android:ems="10"
    android:hint="Age"
    android:inputType="number"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/firstNameInput" />

<Spinner
    android:id="@+id/country_list"
    android:layout_width="200dp"
    android:layout_height="48dp"
    android:layout_marginTop="30dp"
    android:layout_marginEnd="56dp"
    android:background="@android:drawable/btn_dropdown"
    android:backgroundTint="@color/lightWhite"
    android:spinnerMode="dropdown"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/lastNameInput" />

<EditText
    android:id="@+id/passwordSignUp"
    android:layout_width="300dp"
    android:layout_height="50dp"
    android:layout_marginTop="30dp"
    android:layout_marginEnd="56dp"
    android:ems="10"
    android:hint="Password"
    android:inputType="textPassword"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/email_signUp" />

<Button
    android:id="@+id/signUpButton"
    android:layout_width="120dp"
    android:layout_height="50dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="40dp"
    android:backgroundTint="@color/white"
    android:text="Sign up"
    android:textAllCaps="false"
    android:textColor="@color/black"
    app:layout_constraintStart_toStartOf="@+id/country_list"
    app:layout_constraintTop_toBottomOf="@+id/country_list" />

  </androidx.constraintlayout.widget.ConstraintLayout>

My main activity is this:

class MainActivity : AppCompatActivity() {


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.fragment_sign_up_login)
    tabBarSL()
}

override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
    return super.onCreateView(name, context, attrs)
}

fun replaceFragment(fragment: Fragment){
    val fragmentManager = supportFragmentManager.beginTransaction()
    fragmentManager.replace(R.id.frameLayout, fragment).commit()
}


fun tabBarSL(){
    viewPagerSL.adapter = TPA(this,tabLayoutSL.tabCount)
    viewPagerSL.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback(){
        override fun onPageSelected(position: Int) {
            tabLayoutSL.selectTab(tabLayoutSL.getTabAt(position))
        }
    })

tabLayoutSL.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener{
    override fun onTabSelected(tab: TabLayout.Tab) {
        viewPagerSL.currentItem = tab.position
    }

    override fun onTabUnselected(tab: TabLayout.Tab?) {
    }

    override fun onTabReselected(tab: TabLayout.Tab?) {
    }

})
}

}

The XML for the signUpLogin fragment:

<?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=".SignUpLoginFragment"
android:background="@drawable/backgroundsl">

<FrameLayout
    android:id="@+id/frameLayoutSignLogin"
    android:layout_width="match_parent"
    android:layout_height="450dp"
    android:layout_marginTop="205dp"
    app:layout_constraintTop_toTopOf="parent"
    tools:layout_editor_absoluteX="-45dp">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPagerSL"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tabLayoutSL"
    android:layout_width="236dp"
    android:layout_height="46dp"
    android:layout_marginTop="124dp"
    android:layout_marginEnd="88dp"
    android:background="@color/transparent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <com.google.android.material.tabs.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sign up"
        />

    <com.google.android.material.tabs.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Log in" />

</com.google.android.material.tabs.TabLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

I keep getting the error null object reference on my spinner country_list, here's the full error output:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.viegera, PID: 10039
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Spinner.setAdapter(android.widget.SpinnerAdapter)' on a null object reference
    at com.example.viegera.signupFragment.onCreate(signupFragment.kt:33)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2949)
    at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:475)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
    at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1971)
    at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:305)
    at androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder(FragmentStateAdapter.java:341)
    at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:276)
    at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:67)
    at androidx.recyclerview.widget.RecyclerView.dispatchChildAttached(RecyclerView.java:7556)
    at androidx.recyclerview.widget.RecyclerView$5.addView(RecyclerView.java:860)
    at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
    at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8601)
    at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8559)
    at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8547)
    at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1641)
    at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
    at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
    at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
    at android.view.View.layout(View.java:23717)
    E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at com.android.internal.policy.DecorView.onLayout(DecorView.java:797)
    at android.view.View.layout(View.java:23717)
    at android.view.ViewGroup.layout(ViewGroup.java:6413)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3892)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3282)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2278)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8933)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1230)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1238)
    at android.view.Choreographer.doCallbacks(Choreographer.java:898)
    at android.view.Choreographer.doFrame(Choreographer.java:831)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1213)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7892)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Solution

  • The spinner is null, because spinner itself is not initialzed. Spinner will be initialized only when fragment view is created. You are trying to access the spinner when it was null.

    You need to move this code from onCreate to onViewCreated or onCreateView. Because view will be created only when onCreateView is called. onCreate is called before onCreateView . You can see here to know more about fragment lifecycle.

    Also Kotlin synthetics are deprecated because Android kotlin extensions gradle plugin was deprecated. So its recommended to migrate to viewBinding

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
        val adapter = ArrayAdapter(requireContext(),
            android.R.layout.simple_spinner_item, values)
        country_list.adapter = adapter
    
    
       country_list.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
                Toast.makeText(requireContext(), "Selected "+ values[p2], Toast.LENGTH_SHORT).show()
            }
    
            override fun onNothingSelected(p0: AdapterView<*>?) {
            }
    
        }
    }