在 Kotlin 中将值从 Activity 传递到 Fragment

Posted

技术标签:

【中文标题】在 Kotlin 中将值从 Activity 传递到 Fragment【英文标题】:Passing a value from Activity to Fragment in Kotlin 【发布时间】:2019-05-26 15:27:50 【问题描述】:

我在我的项目中创建了一个底部导航活动,其中包含一个活动和两个片段。在主活动中,我将值存储在一个变量中,但如果我将值传递给片段,那么我会收到 NullPointer 异常错误。我在我的项目中使用 kotlin,感谢您的帮助。 期待

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

使用的语言

Kotlin

主要活动

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")
....

错误

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)

【问题讨论】:

您可以分享正确的日志,例如您在哪里获得 NPE,并尝试添加更多代码细节,例如您在哪个函数中传递/访问数据等。 你什么时候调用参数!!.getString("name")?同时,尽量避免在代码中强制展开(使用!!)。 @AdrianComan 感谢您的评论。如果我这样做了,那么我的变量输出中就会出现空值。 val testName= arguments?.getString("name") 正确,因为参数为空,但是您在代码中何时何地调用它?您可以发布片段类的示例吗? 我在 onCreateView 函数中调用它。 【参考方案1】:

以下是用于创建FragmentsnewInstance 模式示例。

这是在companion object 中,这几乎只是一种表达“这些东西是静态的”的方式。

首先,您应该为您的Bundle 名称定义常量,这将有助于保持所有内容对齐。接下来,定义一个接受参数的newInstance 方法,例如name

在那里,您将创建您的Fragment 并返回它。这样,您的Activity 就不必担心Bundle 或其他任何事情。您所有的逻辑都在一个地方,用于存储/检索,都在您的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)
        // ...
    

现在,您可以通过执行以下操作轻松获取您的Fragment

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)
    


希望对您有所帮助!

【讨论】:

感谢您的评论。你能解释一下关于 MyActivity 代码的更多信息吗?我不确定在哪里写那段代码,比如在活动中还是在片段中 @JoshJo - MyActivity 代码进入您所在的任何Activity。假设您在您的MainActivity 上,并且您想显示您的TestOneFragment,您的MainActivity可以调用TestOneFragment.newInstance("name"),准备好Fragment,然后随心所欲地显示它。 如果您编辑您的问题以包括您将如何在您的MainActivty 中显示您的Fragment,我将编辑我的答案更具体。 我正在寻找另一个方向。我需要将活动值放入片段中。 MainActivity---->TestOneFragment 是的,我明白了。 MainActivty 有一些数据,您想用这些数据创建一个新的Fragment。对吗?

以上是关于在 Kotlin 中将值从 Activity 传递到 Fragment的主要内容,如果未能解决你的问题,请参考以下文章

将可空值从 Activity 传递到 Fragment

如何将值从基本适配器传递到 Android 中的 Activity

如何在 QWebEngineView 中将值从 QML 传递到 JavaScript

如何在 Codeigniter 中将值从视图传递到模型

在java中将Arraylist值从servlet传递到JSP?

在ionic 3中将标签文本的值从html传递到.ts?