简体   繁体   中英

Passing a value from Activity to Fragment in Kotlin

I created a bottom navigation activity in my project, which contains one activity and two fragments. In Main Activity I have value stored in a variable but if I pass the value to the fragments then I am getting NullPointer Exception error. I am using kotlin in my project and any help is appreciated. Expectation

Get Value into Fragment from MainActivity. MainActivity--->TestOneFragment

Language Used

Kotlin

Main Activity

class Test : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener
{
    private val KEY_POSITION = "keyPosition"
    private var navPosition: BottomNavigationPosition = BottomNavigationPosition.ONE
    private lateinit var toolbar: Toolbar
    private lateinit var bottomNavigation: BottomNavigationView

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        restoreSaveInstanceState(savedInstanceState)
        setContentView(R.layout.activity_test)
        toolbar = findViewById(R.id.toolbar)
        bottomNavigation = findViewById(R.id.bottom_navigation)
        setSupportActionBar(toolbar)
        initBottomNavigation()
        initFragment(savedInstanceState)
        var Name:String=intent.getStringExtra("name")
        println("Test CLLicked: $Name")


        //This code is to pass the value to Fragment
        var bundle=Bundle()
        bundle.putString("name",Name)
        var frag=TestFragment()
        frag.arguments=bundle
    }

    override fun onSaveInstanceState(outState: Bundle?)
    {
        outState?.putInt(KEY_POSITION, navPosition.id)
        super.onSaveInstanceState(outState)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean
    {
        navPosition = findNavigationPositionById(item.itemId)
        return switchFragment(navPosition)
    }

    private fun restoreSaveInstanceState(savedInstanceState: Bundle?)
    {
        savedInstanceState?.also {
            val id = it.getInt(KEY_POSITION, BottomNavigationPosition.ONE.id)
            navPosition = findNavigationPositionById(id)
        }
    }

    private fun initBottomNavigation()
    {
        bottomNavigation.active(navPosition.position)
        bottomNavigation.setOnNavigationItemSelectedListener(this)
    }

    private fun initFragment(savedInstanceState: Bundle?)
    {
        savedInstanceState ?: switchFragment(BottomNavigationPosition.ONE)
    private fun switchFragment(navPosition: BottomNavigationPosition): Boolean {
        return supportFragmentManager.findFragment(navPosition).let {
            if (it.isAdded) return false
            supportFragmentManager.detach() // Extension function
            supportFragmentManager.attach(it, navPosition.getTag()) // Extension function
            supportFragmentManager.executePendingTransactions()
        }
    }
    private fun FragmentManager.findFragment(position: BottomNavigationPosition): Fragment
    {
        return findFragmentByTag(position.getTag()) ?: position.createFragment()
    }
}

TestOneFragment

 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
    val testName= arguments!!.getString("name")
....
}

Error

kotlin.KotlinNullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)

Here is an example of the newInstance pattern for creating Fragments .

This is within a companion object , which is pretty much just a way to say "these things are Static."

First, you should define constants for your Bundle names, this will help keep everything aligned. Next, define a newInstance method that takes your parameters, such as the name .

And within there, you will create your Fragment and return it. This way, your Activity doesn't have to worry about the Bundle or anything. All your logic is within one place, for storing/retrieving, all within your Fragment .

class TestOneFragment {

    companion object {
        const val ARG_NAME = "name"


        fun newInstance(name: String): TestOneFragment {
            val fragment = TestOneFragment()

            val bundle = Bundle().apply {
                putString(ARG_NAME, name)
            }

            fragment.arguments = bundle

            return fragment
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val name = arguments?.getString(ARG_NAME)
        // ...
    }
}

And now, you can easily get your Fragment by doing the following.

class Test : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        // ...

        val name = intent.getStringExtra("name")

        // Creating the new Fragment with the name passed in.
        val fragment = TestFragment.newInstance(name)
    }

}

Hopefully that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM