【Android开发实战】实现页面跳转(超详细讲解+完整代码+原理解析)
下面开始正文:
一、项目介绍
在 Android 应用中,页面跳转(Navigation) 是最基础也是最关键的功能之一。它承载了用户流转、信息展示、功能隔离等核心逻辑。一个完备的页面跳转方案,不仅要实现“从 A 页面跳转到 B 页面”,还要兼顾以下要点:
传递参数:基本类型、复杂对象、序列化/Parcelable 数据;
返回结果:B 页面操作完成后通知 A 页面;
动画效果:入场/出场动画提升用户体验;
统一管理:集中管理路由、避免硬编码 Intent;
架构兼容:支持 Activity、Fragment、Jetpack Navigation;
安全性:防止未授权跳转、保护隐私参数;
可测试:易于单元测试和 UI 自动化测试。
本篇教程将从基础原理到高级扩展,全方位剖析 Android 页面跳转机制,演示多种实现方式(Intent、startActivityForResult、Jetpack Navigation Component、自定义 Router),并提供统一封装的路由工具类,实现高复用、可测试、可扩展的页面跳转方案。全文超 10000 字,所有 Java/Kotlin 类与 XML 布局整合在一个代码块,通过注释区分,便于复制与集成。
二、相关知识详解
Intent 基础
分类:显式 Intent、隐式 Intent;
组成:Action、Data、Category、Extras、Flags;
参数传递:putExtra()(基本类型、Bundle)、Serializable、Parcelable。
Activity 间跳转
startActivity(Intent)、startActivityForResult(Intent, requestCode);
onActivityResult() 处理返回结果;
Flags:FLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_NEW_TASK 等。
Fragment 跳转
FragmentManager、FragmentTransaction 的 add()、replace()、addToBackStack();
getParentFragmentManager() vs getChildFragmentManager();
返回栈管理与自定义动画:setCustomAnimations()。
Jetpack Navigation Component
NavHostFragment、NavController、Navigation Graph;
Safe Args 插件生成类型安全跳转方法;
Deep Link 支持。
路由框架
ARouter、ActivityRouter、自定义 Router;
注解 + 反射/APT 方式自动生成跳转表;
动画与过度
overridePendingTransition() 设置 Activity 转场动画;
FragmentTransaction.setTransition() 或 setCustomAnimations()。
安全跳转
跳转前校验权限、登录状态;
参数签名与加密。
三、项目实现思路
分层结构
UI 层(Activity/Fragment)只负责展示与交互;
路由层(Router)负责 Intent 构造与跳转;
结果回调层(Callback)解耦来源与目标页面;
配置层(RouteConfig)集中管理路由路径与参数键名。
核心流程
A 调用 Router.navigateTo(context, RouteConfig.PAGE_B, params);
Router 根据路径构建 Intent/Bundle 并启动;
B 在 onCreate() 中读取参数;
B 调用 Router.finishWithResult(this, resultParams) 返回;
Router 在 A 的 onActivityResult() 中分发回调。
技术实现
使用 注解+APT(AutoService + JavaPoet)生成 RouteRegistry;
Router 调用 RouteRegistry.getIntent(context, path, bundle);
支持 Activity 和 Fragment 两种跳转目标。
// ======================================================
// 文件:app/src/main/java/com/example/router/RouteConfig.java
// 作用:集中管理路由路径与参数键名
// ======================================================
package com.example.router;
public class RouteConfig {
public static final String PAGE_HOME = "/home";
public static final String PAGE_DETAIL = "/detail";
public static final String KEY_ITEM_ID = "item_id";
public static final String KEY_USER_NAME = "user_name";
public static final int REQ_DETAIL = 1001;
}
// ======================================================
// 文件:app/src/main/java/com/example/router/Router.java
// 作用:路由工具类,封装跳转与结果回调
// ======================================================
package com.example.router;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
public class Router {
// 跳转到指定页面
public static void navigateTo(@NonNull Context ctx, @NonNull String path, Bundle params) {
Intent intent = new Intent(ctx, getActivityClass(path));
if (params != null) intent.putExtras(params);
ctx.startActivity(intent);
if (ctx instanceof Activity) {
((Activity) ctx).overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
}
// 带返回结果的跳转
public static void navigateForResult(@NonNull Activity act, @NonNull String path, Bundle params, int requestCode) {
Intent intent = new Intent(act, getActivityClass(path));
if (params != null) intent.putExtras(params);
act.startActivityForResult(intent, requestCode);
act.overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
// 从回调中获取结果
public static Bundle handleResult(int requestCode, int resultCode, Intent data) {
if (data != null && data.getExtras() != null) {
return data.getExtras();
}
return null;
}
// 简单映射路径到 Activity class
private static Class> getActivityClass(String path) {
switch (path) {
case RouteConfig.PAGE_HOME: return com.example.ui.HomeActivity.class;
case RouteConfig.PAGE_DETAIL: return com.example.ui.DetailActivity.class;
default: throw new IllegalArgumentException("Unknown path: " + path);
}
}
}
// ======================================================
// 文件:app/src/main/java/com/example/ui/HomeActivity.java
// 作用:首页,演示无参跳转与带参跳转
// ======================================================
package com.example.ui;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.example.router.RouteConfig;
import com.example.router.Router;
public class HomeActivity extends AppCompatActivity {
private Button btnToDetail, btnToDetailForResult;
@Override protected void onCreate(Bundle s) {
super.onCreate(s);
setContentView(R.layout.activity_home);
btnToDetail = findViewById(R.id.btnToDetail);
btnToDetailForResult = findViewById(R.id.btnToDetailForResult);
btnToDetail.setOnClickListener(v -> {
// 无参跳转
Router.navigateTo(this, RouteConfig.PAGE_DETAIL, null);
});
btnToDetailForResult.setOnClickListener(v -> {
// 带参跳转并期待结果
Bundle params = new Bundle();
params.putInt(RouteConfig.KEY_ITEM_ID, 123);
params.putString(RouteConfig.KEY_USER_NAME, "张三");
Router.navigateForResult(this, RouteConfig.PAGE_DETAIL, params, RouteConfig.REQ_DETAIL);
});
}
@Override protected void onActivityResult(int req, int res, Intent data) {
super.onActivityResult(req, res, data);
if (req == RouteConfig.REQ_DETAIL && res == RESULT_OK) {
Bundle result = Router.handleResult(req, res, data);
if (result != null) {
String msg = "Detail 返回: " + result.getString(RouteConfig.KEY_USER_NAME);
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
}
}
}
// ======================================================
// 文件:app/src/main/java/com/example/ui/DetailActivity.java
// 作用:详情页,演示接收参数与返回结果
// ======================================================
package com.example.ui;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.router.RouteConfig;
import com.example.router.Router;
public class DetailActivity extends AppCompatActivity {
private TextView tvInfo;
private Button btnFinish;
@Override protected void onCreate(Bundle s) {
super.onCreate(s);
setContentView(R.layout.activity_detail);
tvInfo = findViewById(R.id.tvInfo);
btnFinish = findViewById(R.id.btnFinish);
// 读取传参
Bundle params = getIntent().getExtras();
if (params != null) {
int itemId = params.getInt(RouteConfig.KEY_ITEM_ID, -1);
String name= params.getString(RouteConfig.KEY_USER_NAME, "未提供");
tvInfo.setText("接收到参数:itemId=" + itemId + ",userName=" + name);
}
btnFinish.setOnClickListener(v -> {
// 返回结果
Intent data = new Intent();
Bundle result = new Bundle();
result.putString(RouteConfig.KEY_USER_NAME, "李四-回传");
data.putExtras(result);
setResult(RESULT_OK, data);
finish();
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
});
}
}
// ======================================================
// 文件:res/layout/activity_home.xml
// 作用:首页布局
// ======================================================
android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp">
// ======================================================
// 文件:res/layout/activity_detail.xml
// 作用:详情页布局
// ======================================================
android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> android:id="@+id/tvInfo" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="详情信息"/> android:id="@+id/btnFinish" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="返回并携带结果"/>
五、代码解读
RouteConfig:集中定义页面路径与键名常量,避免硬编码字符串和 requestCode 冲突。
Router:封装跳转逻辑,统一管理动画与 Intent 构建,简化调用。
HomeActivity:演示无参跳转与带参跳转并期待结果,回调通过 onActivityResult 分发。
DetailActivity:读取传入参数,渲染 UI,完成后通过 setResult 返回结果。
布局文件:简洁明了,配合 DataBinding 或 ViewBinding 可进一步优化。
六、项目总结与拓展
项目收获
系统理解 Intent、startActivityForResult、FragmentTransaction、Jetpack Navigation 的异同;
掌握参数传递与结果返回的标准流程;
学会封装高复用、易维护的路由工具类;
性能优化
对频繁跳转页面使用 FLAG_ACTIVITY_SINGLE_TOP、launchMode 控制栈行为;
使用 Jetpack Navigation 生成 Safe Args,减少手写 Bundle 错误;
高级拓展
Fragment 跳转:Router 分支支持 NavController.navigate();
深度链接:配置 AndroidManifest 中
动态权限:跳转前校验所需权限,如相册、摄像头;
跨模块路由:使用 APT 生成跨组件路由表,实现解耦;