Android Parcelable for Kotlin is not working

12,902

Solution 1

Hello All I had solved this question and there was issue with fragment transaction and parcelable

MainActivity to setup fragment

    class MainActivity : AppCompatActivity() {

    val manager = supportFragmentManager

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

        val fragment = DetailFragment()
        manager.findFragmentById(R.id.fragmentContainer)
        manager.beginTransaction().add(R.id.fragmentContainer, fragment).commit()
    }
}

First fragment to fill data

 class DetailFragment : Fragment(), View.OnClickListener {

    var editTextName: EditText? = null
    var editTextLast: EditText? = null
    var buttonNextFragment: Button? = null
    var firstName: String? = null
    var lastName: String? = null

    companion object {
        val KEY_PARSE_DATA = "detailData"
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        val view: View = inflater!!.inflate(R.layout.fragment_detail, container, false)
        editTextName = view.findViewById(R.id.ed_firstName) as EditText
        editTextLast = view.findViewById(R.id.ed_lastName) as EditText
        buttonNextFragment = view.findViewById(R.id.btn_nextfragment) as Button
        buttonNextFragment!!.setOnClickListener(this)
        return view
    }

    override fun onClick(v: View?) {
        firstName = editTextName!!.text.toString()
        lastName = editTextLast!!.text.toString()
        Toast.makeText(context, firstName, Toast.LENGTH_SHORT).show()
//        val viewFragment = ViewFragment()
//        val transaction = fragmentManager.beginTransaction()
//        transaction.replace(R.id.fragmentContainer, viewFragment)
//        transaction.commit()

        var details = Details(firstName!!, lastName!!)
        val viewFragment = ViewFragment()
        val bundle = Bundle()
        bundle.putParcelable(KEY_PARSE_DATA, details)
        viewFragment.setArguments(bundle)
        val transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.fragmentContainer, viewFragment)
        transaction.commit()
    }
}

Display data coming from parcelable

    class ViewFragment : Fragment() {

    var textViewName: TextView? = null
    var textViewLastName: TextView? = null

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val view: View = inflater!!.inflate(R.layout.fragment_view, container, false)

        textViewName = view.findViewById(R.id.text_name_another) as TextView
        textViewLastName = view.findViewById(R.id.text_surname_another) as TextView

        val bundle = arguments
        if (bundle != null) {
            val details = bundle.getParcelable<Details>(KEY_PARSE_DATA)
            textViewName!!.setText(details.firstName)
            textViewLastName!!.setText(details.lastName)
        }


        return view
    }

}

Model class for implementation of parcelable

    @Parcelize
class Details(val firstName: String, val lastName: String) : Parcelable

and my gradle file

    android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.assignment.ankitt.kotlintwo"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    androidExtensions {
        experimental = true
    }
}

Solution 2

Add below code into your App Level gradle.

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

androidExtensions {
    experimental = true
}

Check IMG

Solution 3

Now it is enough to add 'kotlin-parcelize' plugin. So for example:

 plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-parcelize'

}

Solution 4

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    //

    androidExtensions {
        experimental = true
    }

}

The order of plugin matters. kotlin-android must be before kotlin-android-extension. Then clean project. Unable to add kotlin android extension

Solution 5

I'd recommend taking a look at the @Parcelize annotation provided with the Kotlin Android Extensions, it generates all necessary boilerplate for you so you don't have to write and maintain that code yourself.

Share:
12,902
Ankit Tale
Author by

Ankit Tale

An Mobile Developer by Profession on the way to become Full Stack Developer, an tech enthusiast who love to explore technology read magazine. I am here to answer the question and help the budding developer with an experience and helpful knowledge

Updated on June 09, 2022

Comments

  • Ankit Tale
    Ankit Tale almost 2 years

    I am trying to pass data from one fragment to another but I am facing issue with sending data from parcelable from one fragment to another.

     class MainFragment : Fragment() {
    
    
        companion object {
            public val KEY_PARSE_DATA = "parseData"
        }
    
        private var parseData: ParseData? = null
    
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            // Inflate the layout for this fragment
            return inflater!!.inflate(R.layout.fragment_main, container, false).apply {
                val editName = findViewById(R.id.edit_Name) as EditText
                val editSurname = findViewById(R.id.edit_Surname) as EditText
                val buttonNext = findViewById(R.id.btn_Next) as Button
                buttonNext.setOnClickListener(View.OnClickListener {
                    val fragment = AnotherFragment()
    
                    if (parseData != null) {
                        var parseData = ParseData(editName.text.toString(), editSurname.text.toString())
                        val fragment = AnotherFragment()
                        val bundle = Bundle()
                        bundle.putParcelable(KEY_PARSE_DATA, parseData)
                        fragment.setArguments(bundle)
                        fragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commitAllowingStateLoss()
    
                    }
    
                })
            }
        }
    
    
    }// Required empty public constructor
    

    Parcelable class for implementing it

     @SuppressLint("ParcelCreator")
    @Parcelize
    data class ParseData(val firstName: String, val lastName: String) : Parcelable {
    
    
        constructor(parcel: Parcel) : this(
                parcel.readString(),
                parcel.readString()) {
        }
    
        override fun toString(): String {
            return "ParseData(firstName='$firstName', lastName='$lastName')"
        }
    
    
        companion object : Parceler<ParseData> {
    
            override fun ParseData.write(parcel: Parcel, flags: Int) {
                parcel.writeString(firstName)
                parcel.writeString(lastName)
            }
    
            override fun create(parcel: Parcel): ParseData {
                return ParseData(parcel)
            }
        }
    }
    

    And another fragment which grab data from parcelable class in android

        class AnotherFragment : Fragment() {
    
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            // Inflate the layout for this fragment
            return inflater!!.inflate(R.layout.fragment_another, container, false).apply {
    
                val textName = findViewById<TextView>(R.id.textFirst)
                val textSurname = findViewById<TextView>(R.id.textSecond)
                val bundle = arguments
                if (bundle != null) {
                    val parseData = bundle.getParcelable<ParseData>(KEY_PARSE_DATA)
                    textName.setText(parseData.firstName)
                    textSurname.setText(parseData.lastName)
                }
            }
        }
    
    }
    

    I tried some example but I cant get clear idea how parcelable is implemented in andoid application based on kotlin and build.gradle file

     apply plugin: 'com.android.application'
    
    apply plugin: 'kotlin-android'
    
    apply plugin: 'kotlin-android-extensions'
    
    android {
        compileSdkVersion 26
        defaultConfig {
            applicationId "com.assignment.ankitt.kotlinsecond"
            minSdkVersion 19
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    androidExtensions {
        experimental = true
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
        implementation 'com.android.support:appcompat-v7:26.1.0'
        implementation 'com.android.support.constraint:constraint-layout:1.0.2'
        implementation 'com.android.support:support-v4:26.1.0'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.1'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    }
    
  • Ankit Tale
    Ankit Tale about 6 years
    Thanks it helped me out
  • droide_91
    droide_91 about 6 years
    I would not recommend using functionality that is still in experimental mode for production apps: experimental-mode
  • Ashim Kansal
    Ashim Kansal almost 5 years
    i did the same , i added all three plugins and androidExtensions but still import is throughing an error
  • Ankit Tale
    Ankit Tale about 4 years
    This plugin is by default generated apply plugin: 'kotlin-android-extensions' @Rajneesh