Android中Kotlin的Parcelable无法工作

10

我正在尝试将数据从一个片段传递到另一个片段,但是在从一个片段向另一个片段发送parcelable数据时遇到问题。

 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类

 @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)
        }
    }
}

另外一个片段,从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)
            }
        }
    }

}

我尝试了一些例子,但我无法清楚地理解 parcelable 在基于 Kotlin 和 build.gradle 文件的 Android 应用程序中是如何实现的。

 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'
}
7个回答

21
将以下代码添加到您的应用程序级别gradle中。
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

androidExtensions {
    experimental = true
}

查看图片


7
我已做相同的操作,添加了所有三个插件和androidExtensions,但导入仍然出现错误。 - Ashim Kansal

9

现在只需添加“kotlin-parcelize”插件即可。例如:

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

}


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

android {
    //

    androidExtensions {
        experimental = true
    }

}

插件的顺序很重要。kotlin-android 必须在 kotlin-android-extension 之前。然后清理项目。 无法添加 Kotlin Android 扩展

1
我建议您查看@Parcelize注释,该注释与Kotlin Android Extensions一起提供,它会为您生成所有必要的样板代码,因此您不必自己编写和维护该代码。

谢谢,它帮助了我。 - Ankit Tale
我不建议在生产应用中使用仍处于实验模式的功能:实验模式 - droide_91

1
需要在您的应用级别Gradle中添加这两个。
apply plugin: 'kotlin-android-extensions'

androidExtensions { experimental = true` }

enter image description here


此插件默认生成应用程序插件:'kotlin-android-extensions' @Rajneesh - Ankit Tale

0

在使用'kotlin-android-extensions'之前,应启用Kotlin插件

因此,请更改顺序为

apply plugin: 'com.android.application' #1
apply plugin: 'kotlin-android' #2
apply plugin: 'kotlin-android-extensions' #3

-1
大家好,我已经解决了这个问题,问题出在片段事务和可包含性上。
MainActivity用于设置片段。
    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()
    }
}

填充数据的第一个片段

 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()
    }
}

显示来自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
    }

}

Parcelable 实现的模型类

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

还有我的Gradle文件

    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
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接