3. 多 Activity 跳转与 Intent 传参

多 Activity 跳转与 Intent 传参 学习卡片

显式 Intent 跳转与 Parcelable 传参的完整链路

本例在已有工程中新增一个 DetailActivity,由 MainActivity 通过显式 Intent 启动,并携带三类数据:基本类型(String、int)、Parcelable 对象、以及用于回传结果的请求码。目标页解析展示后,通过 setResult 把处理结果回传给调用方。

1. 定义可传递的 Parcelable 对象

Android 推荐用 Parcelable 在 Activity 间传递结构化对象,比 Serializable 更快。下面是一个最小可用的 User 类,包含姓名、年龄、是否 VIP 三个字段。

package com.example.intentdemo;

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

public class User implements Parcelable {
    private String name;
    private int age;
    private boolean vip;

    public User(String name, int age, boolean vip) {
        this.name = name;
        this.age = age;
        this.vip = vip;
    }

    protected User(Parcel in) {
        name = in.readString();
        age = in.readInt();
        vip = in.readByte() != 0;
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeByte((byte) (vip ? 1 : 0));
    }

    public String getName() { return name; }
    public int getAge() { return age; }
    public boolean isVip() { return vip; }
}
写入与读取顺序必须严格一致:writeString → writeInt → writeByte 对应 readString → readInt → readByte,顺序错位会导致字段值串位。

2. MainActivity 发起跳转并传参

使用显式 Intent 指定目标类,通过 putExtra 写入基本类型与 Parcelable 对象,再用 startActivityForResult 携带请求码启动,以便接收返回结果。

package com.example.intentdemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_DETAIL = 1001;
    private TextView tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvResult = findViewById(R.id.tv_result);
        Button btnOpen = findViewById(R.id.btn_open_detail);

        btnOpen.setOnClickListener(v -> {
            User user = new User("张三", 28, true);

            Intent intent = new Intent(MainActivity.this, DetailActivity.class);
            intent.putExtra("extra_title", "用户详情页");
            intent.putExtra("extra_count", 3);
            intent.putExtra("extra_user", user);

            startActivityForResult(intent, REQUEST_DETAIL);
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_DETAIL && resultCode == Activity.RESULT_OK && data != null) {
            String feedback = data.getStringExtra("extra_feedback");
            tvResult.setText("返回结果:" + feedback);
        }
    }
}

3. DetailActivity 解析展示并回传结果

目标页从 getIntent() 取出数据,注意 Parcelable 的读取方式与基本类型不同,需要指定 CREATOR。点击按钮后通过 setResult 回传结果并结束自身。

package com.example.intentdemo;

import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class DetailActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);

        TextView tvTitle = findViewById(R.id.tv_title);
        TextView tvCount = findViewById(R.id.tv_count);
        TextView tvUser = findViewById(R.id.tv_user);
        Button btnBack = findViewById(R.id.btn_back);

        Intent intent = getIntent();
        String title = intent.getStringExtra("extra_title");
        int count = intent.getIntExtra("extra_count", 0);

        User user;
        if (Build.VERSION.SDK_INT >= 33) {
            user = intent.getParcelableExtra("extra_user", User.class);
        } else {
            user = intent.getParcelableExtra("extra_user");
        }

        tvTitle.setText(title);
        tvCount.setText("数量:" + count);
        if (user != null) {
            tvUser.setText("姓名:" + user.getName()
                    + ",年龄:" + user.getAge()
                    + ",VIP:" + user.isVip());
        }

        btnBack.setOnClickListener(v -> {
            Intent result = new Intent();
            result.putExtra("extra_feedback", "已确认 " + (user != null ? user.getName() : ""));
            setResult(RESULT_OK, result);
            finish();
        });
    }
}
Android 13(API 33)起 getParcelableExtra(String) 已废弃,需使用带 Class 参数的重载;低版本仍用旧方法,因此上面做了版本分支。

4. 注册 Activity 与传参链路

新增的 DetailActivity 必须在 AndroidManifest.xml 中注册,否则启动时会抛出 ActivityNotFoundException。

<activity android:name=".DetailActivity"
    android:exported="false" />
MainActivity putExtra("extra_title","用户详情页") putExtra("extra_count", 3) putExtra("extra_user", User) startActivityForResult(…, 1001) onActivityResult 接收回传 显式 Intent 目标类:DetailActivity.class 基本类型 + Parcelable 请求码 REQUEST_DETAIL=1001 DetailActivity getStringExtra / getIntExtra getParcelableExtra(…, User.class) setResult(RESULT_OK, data) finish() 回传 extra_feedback 去程:携带数据 回程:RESULT_OK + 结果 User (Parcelable) writeString(name) writeInt(age) writeByte(vip ? 1 : 0) CREATOR 按同序读取 序列化写入 Parcel

5. 验证与结果判断

  • 点击按钮后应跳转到 DetailActivity,页面显示标题“用户详情页”、数量 3、以及“姓名:张三,年龄:28,VIP:true”。
  • 点击返回按钮后回到 MainActivity,结果文本应显示“返回结果:已确认 张三”。
  • 若目标页显示 null,优先检查 key 是否拼写一致、Parcelable 读写顺序是否匹配。
  • 若启动即崩溃并提示 ActivityNotFoundException,检查 Manifest 是否注册了 DetailActivity。