iOS和Android對比系列(二):頁面跳轉(zhuǎn)和傳參
[TOC]
iOS
跳轉(zhuǎn)頁面方式
-
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: 系統(tǒng)自己處理,也可自己手動選中@property(nonatomic) NSUInteger selectedIndex;
頁面?zhèn)鬟f參數(shù)
正向傳遞: 在 .h 文件中設(shè)置需要傳遞的參數(shù)
@interface MHConfirmOrderVC : KindergartenBase
@property (nonatomic, strong) ProductObject *product;
@end
注意:正向傳遞的參數(shù)在
init方法中獲取不到的,在loadView中以及后續(xù)的生命周期中可以獲取到
反向傳遞:
方法一:使用代理(協(xié)議)
例子:
-
MHMessageListVC正向傳遞參數(shù)給MHMessageDetailVC -
MHMessageDetailVC反向傳遞參數(shù)給MHMessageListVC
MHMessageListVC 代碼
@interface MHMessageListVC ()<MHMessageDetailVCDelegate>
// ......
@end
@implementation MHMessageListVC
// ......
// 正向傳遞參數(shù)和跳轉(zhuǎn)控制器
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MHMessageCellLayout *cellLayout = [self.viewModel.dataSource objectAtIndex:indexPath.section];
MHMessageDetailVC *vc = [[MHMessageDetailVC alloc] init];
vc.index = indexPath.section; // 傳遞參數(shù)
vc.delegate = self; // 設(shè)置代理
[self.navigationController pushViewController:vc animated:YES]; // 跳轉(zhuǎn)控制器
}
// 接受反向傳遞的參數(shù)結(jié)果
- (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 方法只是一個示例,根據(jù)實(shí)際情況調(diào)用
- (void)viewDidLoad {
[super viewDidLoad];
// 反向傳遞參數(shù),和參數(shù)訪問
if (self.delegate && [self.delegate respondsToSelector:@selector(messageDetailDidLook:)]) {
[self.delegate messageDetailDidLook:_index];
}
}
@end
方法二:遍歷控制器進(jìn)行設(shè)置
思路是獲取到當(dāng)前的控制器棧,然后進(jìn)行遍歷,找到目標(biāo)控制器,然后進(jìn)行處理,例子如下:
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]; // 這里除了刷新頁面,還可以傳遞參數(shù)(修改屬性的值),調(diào)用方法等等
}
[self.navigationController popToViewController:popToController animated:YES];
} else {
// ..... 父類方法
}
Android
Activity跳轉(zhuǎn)頁面和傳參,使用 Intent
格式:
Intent intent = new Intent(當(dāng)前Activity.this, 目標(biāo).class);
startActivity(intent);
跳轉(zhuǎn)頁面(不傳遞參數(shù))
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
跳轉(zhuǎn)頁面 (傳遞簡單的參數(shù)) putExtra()
使用Intent 的 putExtra() 方法
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.putExtra("key", "value");
startActivity(intent);
目標(biāo)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 結(jié)果 : " + value );
}
打印結(jié)果:
E/LoginActivity: getIntent 結(jié)果 : value
注意:
put和get的值類型需要對應(yīng)
跳轉(zhuǎn)頁面 (傳遞復(fù)雜的參數(shù)) Bundle的putSerializable()
使用 Bundle 的 putSerializable()
// 1、自定義的類,實(shí)現(xiàn) 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、跳轉(zhuǎn)傳參
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、獲取傳遞的參數(shù)
@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 結(jié)果 : " + value );
VipService vipService = (VipService) getIntent().getSerializableExtra("vipKey");
Log.e(TAG, "vipService - productId : " + vipService.getProductId());
Log.e(TAG, "vipService - productName : " + vipService.getProductName());
}
打印結(jié)果:
E/LoginActivity: getIntent 結(jié)果 : value
vipService - productId : 100
vipService - productName : 測試商品
跳轉(zhuǎn)頁面 (獲取結(jié)果)
- 使用方法
startActivityForResult() - 監(jiān)聽結(jié)果方法
onActivityResult() - 兩個
code: 請求requestCode和結(jié)果resultCode
例子:
// 1、使用 startActivityForResult() 方法進(jìn)行跳轉(zhuǎn) activity, MainActivity 跳轉(zhuǎn)到 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); // 需要獲取返回結(jié)果
// 2、監(jiān)聽返回結(jié)果
@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, "接受到頁面?zhèn)鲄⒗?---- ");
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 傳遞參數(shù)
Intent intent = new Intent ();
intent.putExtra("name", "返回啦");
intent.putExtra("desc", "頁面?zhèn)鲄⒚枋?);
setResult(RESULT_CODE, intent);
finish();
打印結(jié)果:
E/MainActivity: 接受到頁面?zhèn)鲄⒗?----
name=返回啦
desc=頁面?zhèn)鲄⒚枋?
對比
- 正向傳遞參數(shù)的獲取:
-
iOS需要在loadView方法中以及之后的生命周期方法中都可以獲取到,一般是viewDidLoad -
Android需要在onCreate()方法中獲取
-
- 反向傳遞參數(shù):
-
iOS使用代理協(xié)議,后者進(jìn)行遍歷 -
Android使用startActivityForResult()
-
iOS傳遞簡單或?qū)ο蠖际呛涂刂破?code>UIViewController掛鉤的
Android傳遞參數(shù)都是通過Intent,自定義的類對象還需要使用Bundle傳遞;