• Android笔记(四)Activity之间传递可序列化的数据的优化处理


    Activity之间传递可序列化的数据

    Android应用开发会常常处理数据的序列化和传递。在Android中往往采用两种方式实现数据的可序列化:(1)实现java.io.Serializable接口(2)实现android.os.Parcelable接口。
    类定义为android.os.Parcelable接口的方式,实际上是利用Parcel提供了一套机制,将一个完整的对象进行分解,而分解后的每一部分的数据都属于Intent支持的数据类型。可以将分解后的可序列化的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象通过这种方式来实现传递对象的功能。因为这种数据传递方式效率更高,成为Android进行可序列化传递数据的主要方式。
    在这里插入图片描述
    现在有一个简单实例,就是从主活动MainActivity发送分别发送不同类型数据对象给两个不同的活动,例如将Student类型的数据对象发送给FirstActivity和将Teacher类型的数据对象发送给SecondActivity. 运行效果如下图所示:
    在这里插入图片描述

    一、定义实现Parcelable数据类

    1.Student类

    data class Student(val id:String,val name:String,val gender:String,val className:String):Parcelable{
        constructor(parcel: Parcel) : this(
            parcel.readString()!!,
            parcel.readString()!!,
            parcel.readString()!!,
            parcel.readString()!!
        )
    
        override fun describeContents(): Int=0
    
        override fun writeToParcel(dest: Parcel, flags: Int) {
            dest.writeString(id)
            dest.writeString(name)
            dest.writeString(gender)
            dest.writeString(className)
        }
    
        companion object CREATOR : Parcelable.Creator<Student> {
            override fun createFromParcel(parcel: Parcel): Student {
                return Student(parcel)
            }
    
            override fun newArray(size: Int): Array<Student?> {
                return arrayOfNulls(size)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.结合kotlin-parcelize插件简化数据类的定义

    上述可序列化的数据类的定义形式非常复杂,可以结合kotlin-parcelize插件简化数据类的定义。要使用kotlin-parcelize插件,需要在模块对应的build.gradle.kts中增加kotlin-parcelize插件的处理:

    plugins {

    id (“kotlin-parcelize”)
    }

    同步配置后,修改上述的Student类和Teacher类为如下形式:
    Student类修改为:

    @Parcelize
    data class Student(val id:String,val name:String,val gender:String,val className:String):Parcelable
    
    • 1
    • 2

    定义的Teacher类形式如下:

    @Parcelize
    data class Teacher(val id:String,val name:String,val gender:String):Parcelable
    
    • 1
    • 2

    二、结合JetPack Compose组件定义界面

    1.定义MainActivity及其对应的界面

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                        MainScreen()
            }
        }
    }
    
    @Composable
    fun MainScreen(modifier: Modifier = Modifier) {
        val context = LocalContext.current
        Box(contentAlignment= Alignment.Center){
            Column(horizontalAlignment = Alignment.CenterHorizontally){
                Button(modifier = Modifier.width(200.dp),onClick={
                    val intent = Intent(context,FirstActivity::class.java)
                    intent.putExtra("data",
                        Student("20234454","张三","男","计算机2231班"))
                    context.startActivity(intent)
                }){
                    Text(text = "FirstActivity",fontSize = 18.sp)
                    Icon(imageVector=Icons.Filled.ArrowForward,contentDescription = "第一个活动")
                }
    
                Button(modifier = Modifier.width(200.dp),onClick={
                    val intent = Intent(context,SecondActivity::class.java)
                    intent.putExtra("data",Teacher("20234458","李四","男"))
                    context.startActivity(intent)
                }){
                    Text(text = "SecondActivity",fontSize = 18.sp)
                    Icon(imageVector=Icons.Filled.ArrowForward,contentDescription = "第二个活动")
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在MainActivity中通过两个按钮发送数据给不同的活动,发送的数据对象所属的类各不相同。

    2.以传统的方式接受传递的数据

    传统的方式,就是通过具体指定类型来接受指定类型的数据。
    以FirstActivity接受数据为例:

    class FirstActivity : ComponentActivity()  {
        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent{
                FirstScreen()
            }
        }
    }
    
    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    @Composable
    fun FirstScreen(){
        val context = LocalContext.current as Activity
        val receivedData = context.intent.getParcelableExtra("data",Student::class.java)
        Box(modifier= Modifier
            .fillMaxSize()
            .background(Color.Green),
            contentAlignment = Alignment.Center){
            Text( text ="第一个界面,接受数据是${receivedData}",fontSize=30.sp,color = Color.Yellow)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    以SecondActivity为例:

    class SecondActivity : ComponentActivity()  {
        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent{
                SecondScreen()
            }
        }
    }
    
    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    @Composable
    fun SecondScreen(){
        val context = LocalContext.current as Activity
        val receivedData = context.intent.getParcelableExtra("data",Teacher::class.java)
        Box(modifier= Modifier
            .fillMaxSize()
            .background(Color.Green),
            contentAlignment = Alignment.Center){
            Text( text ="第二个界面,接受数据是${receivedData}",fontSize=30.sp,color = Color.Yellow)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    观察上述两个活动对应的界面,可以发现,它们主要是处理(1)前后景颜色不同;(2)接受传递的数据类型不同;(3)显示文本的内容不同。其他的具体操作非常类似。因此考虑简化代码,定义一个通用的界面函数。

    3.定义通用界面简化处理

    定义通用的界面组合函数SubScreen如下:

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    @Composable
    fun <T:Parcelable> SubScreen(title:String,
                                 preColor:Color,
                                 backgroundColor:Color,
                                 receivedDataType:Class<T>){
        val context = LocalContext.current as Activity
        val data = context.intent.getParcelableExtra("data",receivedDataType)
        Box(modifier= Modifier
            .fillMaxSize()
            .background(backgroundColor),
            contentAlignment = Alignment.Center){
            Text( text ="$title,接受数据是${data}",fontSize=30.sp,color = preColor)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    将两个界面不同的内容:(1)前后景颜色不同;(2)接受传递的数据类型不同;以参数的方式进行传递。
    在上述代码中T表示实现接口Parcelable的类型参数,然后指定接受数据的类型参数receivedDataType设置为通用的表示:Class。经过这样的处理,在接受数据时,就达到了不管发送方发送的数据对象所属类型到底是什么类型,只要它实现了android.os.Parcelable接口,就可以直接接受这样类型的对象实例。

    val context = LocalContext.current as Activity
    val data = context.intent.getParcelableExtra(“data”,receivedDataType)

    通过这样的处理,代码会更简单。

    4.不同活动调用通用界面

    重新修改FirstActivity,调用SubScreen函数定义界面,代码如下:

    class FirstActivity : ComponentActivity()  {
        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent{
                SubScreen(title = "第一个界面", backgroundColor=Color.Green,
                    preColor = Color.Yellow, receivedDataType = Student::class.java)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    重新修改SecondActivity,调用SubScreen函数定义界面,代码如下:

    class SecondActivity : ComponentActivity()  {
        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent{
                SubScreen(title = "第二个界面", backgroundColor = Color.Blue,
                preColor = Color.Yellow, receivedDataType = Teacher::class.java)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    参考文献

    **陈轶《Android移动应用开发(微课版)》[M] 北京:清华大学出版社 2022

  • 相关阅读:
    不用开会员就能在线编辑、管理及分享各类地理空间数据!
    java计算机毕业设计ssm养老院敬老院系统 elementui
    苹果重新设计开源官网;阿里云开放 YoC 源代码;GitHub 开发 Code Search 功能 | 开源日报
    JMeter 安装教程(详细安装教程)
    一篇文章带你搞懂使用PID
    Linux C | Linux标准I/O编程
    5 分钟学会ECharts如何使用
    【车】亚洲龙车辆学习使用
    IDEA页面展示;Module的概念和使用
    Java GUI小程序之图片浏览器
  • 原文地址:https://blog.csdn.net/userhu2012/article/details/133747681