Kotlin pass data between fragment from it main act

2019-08-21 15:27发布

问题:

I having difficulties to pass data from main activity to its fragment. Here main activity is ProductActivity.class that have two fragment using tablayout using Kotlin

Using bundle and set to argument seem not working as error by compiler because string was not save or maybe null after create new fragment.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
                                                                      at my.hipi.hipiboutique.fragments.ProductPageFragment.onCreateView(ProductPageFragment.kt:22)

i'm using this string example only to pass between two fragment for this question purpose but basically i'm using the the json string.

ProductActivity

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_product.*
import my.hipi.hipiboutique.fragments.ProductPageFragment
import java.util.ArrayList

class ProductActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_product)

        val product1 = this.intent.getStringExtra("array")
        val fullProduct = Gson().fromJson(product1, Product::class.java)

        val testString : String = "example only"
        var bundle = Bundle()
        bundle.putString("test", testString)
        var frag = ProductPageFragment()
        frag.arguments = bundle

        viewPager_fragment.adapter = TabsAdapter(supportFragmentManager)
        tabLayout.setupWithViewPager(viewPager_fragment)

    }


}

this is TabsAdapter

import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import my.hipi.hipiboutique.fragments.ProductDetailFragment
import my.hipi.hipiboutique.fragments.ProductPageFragment

class TabsAdapter(manager: FragmentManager) : FragmentPagerAdapter (manager) {

    private val fragmentTitles = arrayOf("Product", "Details", "Contacts")

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 ->  ProductPageFragment()
            1 ->  ProductDetailFragment()
            //2 ->  ContactsFragment()
            else ->  ProductPageFragment()
        }
    }

    override fun getCount(): Int {
         return 3
    }

    override fun getPageTitle(position: Int): CharSequence {
        return fragmentTitles[position]
    }

}

this is ProductPageFragemnt.class

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import my.hipi.hipiboutique.R

class ProductPageFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment

        var gt = this.arguments.getString("test")
        println(gt)

        return inflater!!.inflate(R.layout.fragment_product_page, container, false)  
    }
}

How to pass this data string to both fragments. Yes can pass to one fragment but if go to second tab,will cause null data. I want this data available to both fragments .Thank in advance.

回答1:

In your ProductActivity, you're creating a fragment and setting its arguments, but you're not doing anything with that fragment. It just gets thrown away:

val testString : String = "example only"
var bundle = Bundle()
bundle.putString("test", testString)
var frag = ProductPageFragment()
frag.arguments = bundle 

In your TabsAdapter, you create the fragments that actually get used, but you never set their arguments:

override fun getItem(position: Int): Fragment {
    return when (position) {
        0 ->  ProductPageFragment()
        1 ->  ProductDetailFragment()
        //2 ->  ContactsFragment()
        else ->  ProductPageFragment()
    }
}

You can delete the first section of code, but you'll want to apply that same logic in your adapter. Maybe something like this:

override fun getItem(position: Int): Fragment {
    return when (position) {
        0 -> {
            var bundle = Bundle()
            bundle.putString("test", "some string here")
            var frag = ProductPageFragment()
            frag.arguments = bundle
            frag
        }
        ...
    }
}