iOS和Android对比系列(二):页面跳转和传参
[TOC]
iOS
跳转页面方式
-
UIViewController
-
present
:- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
-
dismiss
:- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
-
-
UINavigationController
-
push
:- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
-
pop
:-
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;
: 返回到上一个页面 -
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
: 返回到指定页面 -
- (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
: 返回到根控制器
-
-
-
UITabBarController
: 系统自己处理,也可自己手动选中@property(nonatomic) NSUInteger selectedIndex;
页面传递参数
正向传递: 在 .h
文件中设置需要传递的参数
@interface MHConfirmOrderVC : KindergartenBase
@property (nonatomic, strong) ProductObject *product;
@end
注意:正向传递的参数在
init
方法中获取不到的,在loadView
中以及后续的生命周期中可以获取到
反向传递:
方法一:使用代理(协议)
例子:
-
MHMessageListVC
正向传递参数给MHMessageDetailVC
-
MHMessageDetailVC
反向传递参数给MHMessageListVC
MHMessageListVC
代码
@interface MHMessageListVC ()<MHMessageDetailVCDelegate>
// ......
@end
@implementation MHMessageListVC
// ......
// 正向传递参数和跳转控制器
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MHMessageCellLayout *cellLayout = [self.viewModel.dataSource objectAtIndex:indexPath.section];
MHMessageDetailVC *vc = [[MHMessageDetailVC alloc] init];
vc.index = indexPath.section; // 传递参数
vc.delegate = self; // 设置代理
[self.navigationController pushViewController:vc animated:YES]; // 跳转控制器
}
// 接受反向传递的参数结果
- (void)messageDetailDidLook:(NSInteger)index {
// ......
}
@end
MHMessageDetailVC
代码
// .h 文件
@protocol MHMessageDetailVCDelegate <NSObject>
@optional
/// 消息已读
- (void)messageDetailDidLook:(NSInteger)index;
@end
@interface MHMessageDetailVC : MHBaseViewController
/// 操作的索引
@property (nonatomic, assign) NSInteger index;
/// 代理
@property (nonatomic, weak, nullable) id<MHMessageDetailVCDelegate> delegate;
@end
// .m 文件
@implementation MHMessageDetailVC
// ......
// 在 viewDidLoad 方法只是一个示例,根据实际情况调用
- (void)viewDidLoad {
[super viewDidLoad];
// 反向传递参数,和参数访问
if (self.delegate && [self.delegate respondsToSelector:@selector(messageDetailDidLook:)]) {
[self.delegate messageDetailDidLook:_index];
}
}
@end
方法二:遍历控制器进行设置
思路是获取到当前的控制器栈
,然后进行遍历,找到目标控制器,然后进行处理,例子如下:
UIViewController *popToController = nil;
NSArray *controllers = self.navigationController.viewControllers;
for (UIViewController *controller in controllers) {
if ([NSStringFromClass([controller class]) isEqualToString:@"MHNewWebViewVC"]) {
popToController = controller;
break;
}
}
if (popToController) {
// 刷新页面
if ([popToController isKindOfClass:[MHNewWebViewVC class]]) {
MHNewWebViewVC *popVC = (MHNewWebViewVC *)popToController;
[popVC reloadWebView]; // 这里除了刷新页面,还可以传递参数(修改属性的值),调用方法等等
}
[self.navigationController popToViewController:popToController animated:YES];
} else {
// ..... 父类方法
}
Android
Activity
跳转页面和传参,使用 Intent
格式:
Intent intent = new Intent(当前Activity.this, 目标.class);
startActivity(intent);
跳转页面(不传递参数)
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
跳转页面 (传递简单的参数) putExtra()
使用Intent
的 putExtra()
方法
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.putExtra("key", "value");
startActivity(intent);
目标LoginActivity
在onCreate()
方法中获取
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Log.e(TAG, "onCreate -- " );
String value = getIntent().getStringExtra("key");
Log.e(TAG, "getIntent 结果 : " + value );
}
打印结果:
E/LoginActivity: getIntent 结果 : value
注意:
put
和get
的值类型
需要对应
跳转页面 (传递复杂的参数) Bundle
的putSerializable()
使用 Bundle
的 putSerializable()
// 1、自定义的类,实现 Serializable 接口
public class VipService implements Serializable {
private Long productId;
private String productName;
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}
// 2、跳转传参
VipService vipService = new VipService();
vipService.setProductId((long) 100);
vipService.setProductName("测试商品");
Bundle bundle = new Bundle();
bundle.putSerializable("vipKey", vipService);
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.putExtra("key", "value");
intent.putExtras(bundle); // 传递自定义类对象
startActivity(intent);
// 3、获取传递的参数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Log.e(TAG, "onCreate -- " );
String value = getIntent().getStringExtra("key");
Log.e(TAG, "getIntent 结果 : " + value );
VipService vipService = (VipService) getIntent().getSerializableExtra("vipKey");
Log.e(TAG, "vipService - productId : " + vipService.getProductId());
Log.e(TAG, "vipService - productName : " + vipService.getProductName());
}
打印结果:
E/LoginActivity: getIntent 结果 : value
vipService - productId : 100
vipService - productName : 测试商品
跳转页面 (获取结果)
- 使用方法
startActivityForResult()
- 监听结果方法
onActivityResult()
- 两个
code
: 请求requestCode
和结果resultCode
例子:
// 1、使用 startActivityForResult() 方法进行跳转 activity, MainActivity 跳转到 LoginActivity
VipService vipService = new VipService();
vipService.setProductId((long) 100);
vipService.setProductName("测试商品");
Bundle bundle = new Bundle();
bundle.putSerializable("vipKey", vipService);
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.putExtra("key", "value");
intent.putExtras(bundle); // 传递自定义类对象
// startActivity(intent);
startActivityForResult(intent, LoginActivity.REQUEST_CODE); // 需要获取返回结果
// 2、监听返回结果
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LoginActivity.REQUEST_CODE) {
if (resultCode == LoginActivity.RESULT_CODE) {
String name = data.getStringExtra("name");
String desc = data.getStringExtra("desc");
Log.e(TAG, "接受到页面传参啦 ---- ");
Log.e(TAG, "name=" + name);
Log.e(TAG, "desc=" + desc);
}
}
}
// 3、请求码和返回码
public static int REQUEST_CODE = 100;
public static int RESULT_CODE = 1000;
// 4、LoginActivity 返回的时候 向 MainActivity 传递参数
Intent intent = new Intent ();
intent.putExtra("name", "返回啦");
intent.putExtra("desc", "页面传参描述");
setResult(RESULT_CODE, intent);
finish();
打印结果:
E/MainActivity: 接受到页面传参啦 ----
name=返回啦
desc=页面传参描述
对比
- 正向传递参数的获取:
-
iOS
需要在loadView
方法中以及之后的生命周期方法中都可以获取到,一般是viewDidLoad
-
Android
需要在onCreate()
方法中获取
-
- 反向传递参数:
-
iOS
使用代理协议,后者进行遍历 -
Android
使用startActivityForResult()
-
iOS
传递简单或对象都是和控制器UIViewController
挂钩的
Android
传递参数都是通过Intent
,自定义的类对象还需要使用Bundle
传递;