Android : 序列化 Parcelable 简单应用

1.Parcelable 介绍

Parcelable 是 Android 提供的一个序列化接口,用于将数据写入 Parcel,以及从 Parcel 中读取数据。一个类只要实现了这个接口,该类的对象就可以被序列化,主要用于 IPC(进程间通信)、Binder 和 Activity 之间的对象传递。

实现 Parcelable 接口需要实现以下方法:

  1. describeContents():这个方法是内容接口描述,默认返回 0 就可以。
  2. writeToParcel(Parcel dest, int flags):该方法将类的数据写入外部提供的 Parcel 中,即打包须要传递的数据到 Parcel 容器保存,以便从 Parcel 容器获取数据。
  3. Parcelable.Creator:这是一个静态的接口,包含两个方法,用于从 Parcel 中构造实现了 Parcelable 的类的实例。

Parcelable 接口的效率比实现 Serializable 接口高,并且支持用于 Intent 数据传递。需要注意的是,只有实现了 Parcelable 接口的类才能被放入 Parcel 中。

2.简单应用 实现跨进程传递数据

使用了dataBinding 简化开发

// 在 build.gradle 文件中加入
android{

    ...
    defaultConfig{
        ...
        //加入
         dataBinding.enabled true
    }

}

1.主页面 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/etName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:ems="10"
            android:hint="姓名"
            android:inputType="text"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etAge"
            app:layout_constraintEnd_toStartOf="@+id/guideline4"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/guideline2"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.059" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.1" />

        <EditText
            android:id="@+id/etAge"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:ems="10"
            android:hint="年龄"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etChinese"
            app:layout_constraintEnd_toEndOf="@+id/etName"
            app:layout_constraintStart_toStartOf="@+id/etName"
            app:layout_constraintTop_toBottomOf="@+id/etName"
            app:layout_constraintVertical_bias="0.182" />

        <EditText
            android:id="@+id/etMaths"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="数学"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etEnglish"
            app:layout_constraintEnd_toEndOf="@+id/etChinese"
            app:layout_constraintStart_toStartOf="@+id/etChinese"
            app:layout_constraintTop_toBottomOf="@+id/etChinese" />

        <EditText
            android:id="@+id/etChinese"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="语文"
            android:inputType="numberSigned"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etMaths"
            app:layout_constraintEnd_toEndOf="@+id/etAge"
            app:layout_constraintStart_toStartOf="@+id/etAge"
            app:layout_constraintTop_toBottomOf="@+id/etAge" />

        <EditText
            android:id="@+id/etEnglish"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="英语"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toEndOf="@+id/etMaths"
            app:layout_constraintStart_toStartOf="@+id/etMaths"
            app:layout_constraintTop_toBottomOf="@+id/etMaths" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.6" />

        <Button
            android:id="@+id/btnSave"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="保存"
            app:layout_constraintStart_toStartOf="@+id/guideline2"
            app:layout_constraintTop_toTopOf="@+id/guideline3" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.7" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

2.跳转的页面 activity_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MenuActivity">

        <EditText
            android:id="@+id/etName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:ems="10"
            android:hint="姓名"
            android:inputType="text"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etAge"
            app:layout_constraintEnd_toStartOf="@+id/guideline4"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/guideline2"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.059" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.1" />

        <TextView
            android:id="@+id/tvGrade"
            android:layout_width="0dp"
            android:layout_height="77dp"
            android:gravity="center"
            android:hint="等级"
            android:textSize="30sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.872"
            app:layout_constraintStart_toStartOf="@+id/guideline4"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.047" />

        <EditText
            android:id="@+id/etAge"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:ems="10"
            android:hint="年龄"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etChinese"
            app:layout_constraintEnd_toEndOf="@+id/etName"
            app:layout_constraintStart_toStartOf="@+id/etName"
            app:layout_constraintTop_toBottomOf="@+id/etName"
            app:layout_constraintVertical_bias="0.182" />

        <EditText
            android:id="@+id/etMaths"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="数学"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etEnglish"
            app:layout_constraintEnd_toEndOf="@+id/etChinese"
            app:layout_constraintStart_toStartOf="@+id/etChinese"
            app:layout_constraintTop_toBottomOf="@+id/etChinese" />

        <EditText
            android:id="@+id/etChinese"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="语文"
            android:inputType="numberSigned"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/etMaths"
            app:layout_constraintEnd_toEndOf="@+id/etAge"
            app:layout_constraintStart_toStartOf="@+id/etAge"
            app:layout_constraintTop_toBottomOf="@+id/etAge" />

        <EditText
            android:id="@+id/etEnglish"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="英语"
            android:inputType="number"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toEndOf="@+id/etMaths"
            app:layout_constraintStart_toStartOf="@+id/etMaths"
            app:layout_constraintTop_toBottomOf="@+id/etMaths" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.6" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.7" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

3.Score.java

package com.example.parcelabledemo;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * 序列化 implements Parcelable
 * 用于跨进程传递数据
 */
public class Score implements Parcelable {
    private float math;
    private float english;
    private float chinese;
    private String grade;

    public Score(float math, float english, float chinese) {
        this.math = math;
        this.english = english;
        this.chinese = chinese;
        if (math >= 90 && english >= 90 && chinese >= 90) {
            this.grade = "A";
        } else if (math >= 80 && english >= 80 && chinese >= 80) {
            this.grade = "B";
        } else {
            this.grade = "C";
        }
    }

    protected Score(Parcel in) {
        math = in.readFloat();
        english = in.readFloat();
        chinese = in.readFloat();
        grade = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeFloat(math);
        dest.writeFloat(english);
        dest.writeFloat(chinese);
        dest.writeString(grade);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Score> CREATOR = new Creator<Score>() {
        @Override
        public Score createFromParcel(Parcel in) {
            return new Score(in);
        }

        @Override
        public Score[] newArray(int size) {
            return new Score[size];
        }
    };

    public float getMath() {
        return math;
    }

    public void setMath(float math) {
        this.math = math;
    }

    public float getEnglish() {
        return english;
    }

    public void setEnglish(float english) {
        this.english = english;
    }

    public float getChinese() {
        return chinese;
    }

    public void setChinese(float chinese) {
        this.chinese = chinese;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }
}

4.Student.java

package com.example.parcelabledemo;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * 序列化 implements Parcelable
 * 用于跨进程传递数据
 */
public class Student implements Parcelable {
    private String name;
    private int age;
    private Score score;

    public Student(String name, int age, Score score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    protected Student(Parcel in) {
        name = in.readString();
        age = in.readInt();
        score = in.readParcelable(Score.class.getClassLoader());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeParcelable(score, flags);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }

        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Score getScore() {
        return score;
    }

    public void setScore(Score score) {
        this.score = score;
    }
}

5. MyApplication.java

package com.example.parcelabledemo;

import android.app.Application;

public class MyApplication extends Application {
    //整个Activity有效 设置全局属性
    // 用于测试 Application不能跨进程传递数据
    Student student;
}

6.MainActivity.java

package com.example.parcelabledemo;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.example.parcelabledemo.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        //保存数据跳转页面事件
        binding.btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                float math = Float.parseFloat(binding.etMaths.getText().toString());
                float english = Float.parseFloat(binding.etEnglish.getText().toString());
                float chinese = Float.parseFloat(binding.etChinese.getText().toString());
                Score score = new Score(math, english, chinese);

                String name = binding.etName.getText().toString();
                int age = Integer.parseInt(binding.etAge.getText().toString());
                Student student = new Student(name, age, score);
                //传递数据
//                MyApplication myApplication = (MyApplication) getApplication();
//                myApplication.student = student;

                //意图跳转页面
                Intent intent = new Intent(MainActivity.this, MenuActivity.class);
                //bundle 传递 Parcelable 数据
                Bundle bundle = new Bundle();
                bundle.putParcelable("studentData", student);
                intent.putExtra("data", bundle);
                //跳转
                startActivity(intent);
            }
        });
    }
}

7.MenuActivity.java

package com.example.parcelabledemo;

import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.example.parcelabledemo.databinding.ActivityMenuBinding;

public class MenuActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_menu);
        ActivityMenuBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_menu);
        //获取数据
        Intent intent = getIntent();
        Bundle bundle = intent.getBundleExtra("data");
        Student student = bundle.getParcelable("studentData");

//        MyApplication myApplication = (MyApplication) getApplication();
//        Student student = myApplication.student;

        binding.etName.setText(student.getName());
        binding.etAge.setText(String.valueOf(student.getAge()));
        binding.etChinese.setText(String.valueOf(student.getScore().getChinese()));
        binding.etMaths.setText(String.valueOf(student.getScore().getMath()));
        binding.etEnglish.setText(String.valueOf(student.getScore().getEnglish()));
        binding.tvGrade.setText(student.getScore().getGrade());
    }
}

8.AndroidManifest.xml        创建新进程测试数据传递

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 引用全局变量  android:name=".MyApplication" -->
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Parcelabledemo">

        <!--   android:process=":process2" 创建一个新的进程 -->
        <activity
            android:name=".MenuActivity"
            android:process=":process2"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

猜你喜欢

转载自blog.csdn.net/jiayou2020527/article/details/134953842