成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

移動端基于動態路由的架構設計

移動開發 iOS Android
最近在做混合App開發這塊,從開始的ionic 框架,到后來的mui框架,讓我在混合開發這塊有了更深的理解,如果在這塊要寫點什么無非漫天蓋地的這個指令怎么用,那個模版怎么用,數據怎么進行雙向綁定,等等,但是這些網上已經很多資料了,等不太忙了,我想我會總結一篇這些框架的使用心得吧。但是我今天不講這個,我們來談一談在原生app中(iOS android)如何使用動態路由機制來搭建整個app的框架。

好久好久沒寫過文章了,一是最近項目太忙了,沒時間寫。二是也沒有時間學習新的東西,想寫點什么卻又無從下筆。一味的去寫這個API怎么用,那個新技術怎么用,又顯的沒意思。沒有項目經驗總結的技術知識講解,總感覺有些蒼白。

最近在做混合App開發這塊,從開始的ionic 框架,到后來的mui框架,讓我在混合開發這塊有了更深的理解,如果在這塊要寫點什么無非漫天蓋地的這個指令怎么用,那個模版怎么用,數據怎么進行雙向綁定,等等,但是這些網上已經很多資料了,等不太忙了,我想我會總結一篇這些框架的使用心得吧。但是我今天不講這個,我們來談一談在原生app中(iOS android)如何使用動態路由機制來搭建整個app的框架。

路由機制在web開發中是比較常見的,app開發中還是很少聽到這種概念的,目前有些大公司采用的組件化開發(手淘,攜程,蘑菇街等),倒是跟我們講的有很多相同之處,不過它們的比較復雜,而且網上很多組件化開發,路由機制,沒有一個能給出完整代碼示例的,看著讓人云里霧里的。索性自己就借鑒它們的思想,加上一點個人的理解,搞出了一個簡單實用的可行性demo出來。我們主要介紹以下三方面內容:

1 什么是動態路由

2 它能解決我們什么問題

3 如何在項目中實現

一 什么是動態路由

原生開發沒這概念,我們借助angular路由機制來解釋這一概念,所謂路由,就是一套路徑跳轉機制,事先通過配置文件定義好一個路徑映射文件,跳轉時根據key去找到具體頁面,當然angular會做一些緩存,頁面棧的管理等等一些操作,它大致的定義是這樣的

  1. angular.module('app',[]) 
  2.            .config('$routeProvider',function  ($routeProvider) { 
  3.                $routeProvider 
  4.                    .when('/',{ 
  5.                        templateUrl:'view/home.html'
  6.                        controller:'homeCtrl' 
  7.                        } 
  8.                        ) 
  9.                    .when('/',{ 
  10.                        templateUrl:'view/home.html'
  11.                        controller:'homeCtrl' 
  12.                        } 
  13.                        ) 
  14.                    .when('/',{ 
  15.                        templateUrl:'view/home.html'
  16.                        controller:'homeCtrl' 
  17.                        } 
  18.                        ) 
  19.                    .ontherwise({ 
  20.                        redirective:'/' 
  21.                    }) 
  22.            })  

config函數是一個配置函數。在使用

$routeProvider這樣的一個服務。when:代表當你訪問這個“/”根目錄的時候 去訪問 templateUrl中的那個模板。 controller可想已知,就是我們配套的controller,就是應用于根目錄的這個 模板時的controller。

ontherwise 就是當你路徑訪問錯誤時,找不到。***跳到這個默認的 頁面。

為此我們可以總結一下幾個特點:

1 一個映射配置文件

2 路徑出錯處理機制

這就是路由的基本意思,我們看看,在原生開發中,采用此種方式,他能解決我們什么問題。

二 它能解決我們什么問題

首先我們來比較一下我們以前的結構模式以及與 加入路由機制后的項目結構,實現路由機制,不僅需要一個映射文件,還需要一套路由管理機制,那么采用路由機制,我們的項目架構就跟原來不一樣了,如下圖:

原先業務之間的調用關系 [[182219]] 

原先業務之間的調用關系.png 

 

 

加入路由后的頁面調用關系 

加入路由后的頁面調用關系.png

接下來我們看一下平時我們采用的頁面跳轉方法:

iOS 下

  1. [self presentViewController:controller animated:YES completion:nil]; 
  2. [self.navigationController pushViewController:controller animated:YES];  

android 下

  1. Intent intent = new Intent(this, A.class); startActivity(intent); startActivityForResult(Intent intent, Int requestCode) 

我們看一下它有哪些缺點:

(1)都要在當前頁面引入要跳轉頁面的class 類。這就造成了頁面的耦合性很高。

(2)遇到重大bug,不能夠及時的修復問題,需要等待更新發版后才能解決。

(3)推送消息,如果入口沒有關與頁面的引入處理,則不能跳轉到指定頁面。

引入路由機制后我們能否解決這些問題呢?

試想一下,如果我們通過一個配置文件來映射頁面跳轉關系,而且通過反射機制來取消頭文件的引入問題,是不是我們就可以解決以上那些弊端了呢,比如,我們線上應用出現bug, 導致某個頁面一打開,app就跪了,那我們是不是就可以通過更新路由配置文件,把它映射到另一個頁面去:一個錯誤提示文件,或者一個線上H5能實現相同功能的頁面。這樣的話,原生app也具有了一定的動態更新能力,其實想想還有很多好處,比如項目功能太多原生開發要很長時間,但是領導又急著要上線,那么我們是不是就可以先開發一個網頁版的模塊,app路由映射到這個web頁面,讓用戶先用著,等我們原生開發完了,然后再改一下映射文件,沒升級的依舊用H5的路由,升級的就用原生的路由,如果H5頁面我們要廢棄了,那我們整體就可以路由到一個升級提升的頁面去了。

總結一下路由機制能解決我們哪些問題:

1 避免引入頭文件,是頁面之間的依賴大大變少了(通過反射動態生成頁面實例)。

2 線上出現重大bug,給我們提供了一個及時修補的入口

3 網頁和原生切換更方便,更自由。

4 可以跳轉任意頁面 例如我們常用的推送,要打開指定的頁面,以前我們怎么做的,各種啟動判斷,現在呢,我們只要給發送消息配個路由路徑就行了,打開消息,就能夠跳轉到我們指定的頁面。

等等,其它好處自行發掘。

三 如何在項目中實現

說了這么多概念性問題,下面我們就用代碼來實現我們的構想, 下面先以IOS平臺為例:

我們先看一下demo結構 

 

 

iOS demo結構圖 

iOS demo結構圖.png

說明:WXRouter 路由管理文件

demo 路由使用示例

urlMap.plist 路由配置文件

我們主要講解一下 WXRouter里面的幾個文件,以及ViewController文件,還有urlmap.plist文件,其他請下載示例demo,文末我會給出demo地址。

  1. #import 
  2. #import 
  3. @interface WXRouter : NSObject 
  4. +(id)sharedInstance; 
  5. -(UIViewController *)getViewController:(NSString *)stringVCName; 
  6. -(UIViewController *)getViewController:(NSString *)stringVCName withParam:(NSDictionary *)paramdic; 
  7. @end 
  8.  
  9. #import "WXRouter.h" 
  10. #import "webView.h" 
  11. #import "RouterError.h" 
  12. #import "PlistReadUtil.h" 
  13. #define SuppressPerformSelectorLeakWarning(Stuff) \ 
  14. do { 
  15. _Pragma("clang diagnostic push") \ 
  16. _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ 
  17. Stuff; \ 
  18. _Pragma("clang diagnostic pop") \ 
  19. while (0) 
  20. @implementation WXRouter 
  21. +(id)sharedInstance { 
  22.     static dispatch_once_t onceToken; 
  23.     static WXRouter * router; 
  24.     dispatch_once(&onceToken,^{ 
  25.         router = [[WXRouter alloc] init]; 
  26. }); 
  27. return router; 
  28. -(UIViewController *)controller:(UIViewController *)controller withParam:(NSDictionary *)paramdic andVcname:(NSString *)vcName { 
  29. SEL selector = NSSelectorFromString(@"iniViewControllerParam:"); 
  30.     if(![controller respondsToSelector: selector]){  //如果沒定義初始化參數方法,直接返回,沒必要在往下做設置參數的方法 
  31.         NSLog(@"目標類:%@未定義:%@方法",controller,@"iniViewControllerParam:"); 
  32. return controller; 
  33. if(paramdic == nil) { 
  34. //如果參數為空 URLKEY 頁面唯一路徑標識別 
  35.         paramdic = [[NSMutableDictionary alloc] init]; 
  36.         [paramdic setValue: vcName forKey:@"URLKEY"]; 
  37. SuppressPerformSelectorLeakWarning([controller performSelector: selector withObject:paramdic]); 
  38. else { 
  39. [paramdic setValue: vcName forKey:@"URLKEY"]; 
  40. SuppressPerformSelectorLeakWarning( [controller performSelector:selector withObject:paramdic]); 
  41.     return controller; 
  42. -(UIViewController *)getViewController:(NSString *)stringVCName { 
  43. NSString *viewControllerName = [PlistReadUtil plistValueForKey: stringVCName]; 
  44. Class class = NSClassFromString(viewControllerName); 
  45.     UIViewController *controller = [[class alloc] init]; 
  46.     if(controller == nil){  //此處可以跳轉到一個錯誤提示頁面 
  47.         NSLog(@"未定義此類:%@",viewControllerName); 
  48.         return nil; 
  49. return controller; 
  50. -(UIViewController *)getViewController:(NSString *)stringVCName withParam:(NSDictionary *)paramdic { 
  51. UIViewController *controller = [self getViewController: stringVCName]; 
  52. if(controller != nil){ 
  53.         controller = [self controller: controller withParam:paramdic andVcname:stringVCName]; 
  54. else { 
  55. //異常處理  可以跳轉指定的錯誤頁面 
  56.         controller = [[RouterError sharedInstance] getErrorController]; 
  57. return controller; 
  58. @end  

說明:通過反射機制根據傳入的string來獲取 viewcontroller實例,實現了兩個方法,一個是不需要傳入參數的,一個是需要傳入參數的,當跳轉到第二個頁面需要傳值 就使用第二個帶參數的方法,所傳的值通過NSDictionary來進行封裝,跳轉后的頁面通過實現

-(void)iniViewControllerParam:(NSDictionary *)dic 方法來獲取傳過來的參數。

  1. #import 
  2. @interface PlistReadUtil : NSObject 
  3. @property(nonatomic,strong) NSMutableDictionary *plistdata; 
  4. +(id)sharedInstanceWithFileName:(NSString *)plistfileName; 
  5. +(NSString *)plistValueForKey:(NSString *)key
  6. @end 
  7.  
  8. #import "PlistReadUtil.h" 
  9. @implementation PlistReadUtil 
  10. +(id)sharedInstanceWithFileName:(NSString *)plistfileName { 
  11.     static dispatch_once_t onceToken; 
  12.     static PlistReadUtil * plistUtil; 
  13.     dispatch_once(&onceToken,^{ 
  14.         plistUtil = [[PlistReadUtil alloc] init]; 
  15.         NSString *plistPath = [[NSBundle mainBundle] pathForResource: plistfileName ofType:@"plist"]; 
  16.     plistUtil.plistdata = [[NSMutableDictionary alloc] initWithContentsOfFile: plistPath]; 
  17. }); 
  18. return plistUtil; 
  19. +(NSString *)plistValueForKey:(NSString *)key { 
  20. PlistReadUtil *plist =  [PlistReadUtil sharedInstanceWithFileName: @"urlMap"]; 
  21. return [plist.plistdata objectForKey: key]; 
  22. @end  

說明:路由配置文件讀取工具類,我這里讀取的是plist 文件,我這里也可以讀取json,或則訪問網絡獲取后臺服務器上的路由配置文件,這個根據我們業務需求的不同,可以添加不同的讀取方法。

  1. #import <Foundation/Foundation.h> 
  2. #import <UIKit/UIKit.h> 
  3. @interface RouterError : NSObject 
  4. +(id)sharedInstance; 
  5. -(UIViewController *)getErrorController; 
  6. @end 
  7.  
  8. #import "RouterError.h" 
  9. #import "WXRouter.h" 
  10. @implementation RouterError 
  11. +(id)sharedInstance { 
  12.     static dispatch_once_t onceToken; 
  13.     static RouterError * routerError; 
  14.     dispatch_once(&onceToken,^{ 
  15.         routerError = [[RouterError alloc] init]; 
  16. }); 
  17. return routerError; 
  18. #pragma mark  自定義錯誤頁面 此頁面一定確保能夠找到,否則會進入死循環 
  19. -(UIViewController *)getErrorController { 
  20. NSDictionary *diction = [[NSMutableDictionary alloc] init]; 
  21.     [diction setValue: @"https://themeforest.net/item/octopus-error-template/2562783" forKey:@"url"]; 
  22. UIViewController *errorController = [[WXRouter sharedInstance] getViewController: @"MSG003" withParam:diction]; 
  23. return errorController; 
  24. @end  

說明:在讀取配置文件時如果沒有讀到相應的路徑,或者未定義相應的class,我們可以在這里處理,我這邊處理的是如果出現錯誤,就返回一個webview頁面,我們可以在項目里寫一個統一的錯誤處理webview頁面,其實每個頁面默認都添加了一個參數[paramdic setValue:vcName forKey:@"URLKEY"]; 就是這個URLKEY,這個key標示配置文件中每個跳轉動作的key,這個key是唯一的,我們可以根據不同的URLKEY然后通過后臺統一的一個接口來判斷跳轉到不同的錯誤處理H5頁面。

  1. #import "ViewController.h" 
  2. #import "view2.h" 
  3. #import "WXRouter.h" 
  4. #import "PlistReadUtil.h" 
  5. @interface ViewController () 
  6. @end 
  7. @implementation ViewController 
  8. -(void)viewDidLoad { 
  9.     [super viewDidLoad]; 
  10.     UILabel *lable = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 100, 50)]; 
  11.     lable.textColor = [UIColor blueColor]; 
  12.     lable.text =@"hello word"
  13.     [self.view addSubview: lable]; 
  14.     UIButton *button = [[UIButton alloc] initWithFrame: CGRectMake(0, 50, 200, 50)]; 
  15.     [button setTitle: @"訪問view1" forState:UIControlStateNormal]; 
  16.     [button setTitleColor: [UIColor blackColor] forState:UIControlStateNormal]; 
  17.     button.tag = 1; 
  18.     [button addTarget: self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside]; 
  19.     [self.view addSubview: button]; 
  20.     UIButton *button2 = [[UIButton alloc] initWithFrame: CGRectMake(0, 110, 200, 50)]; 
  21.     [button2 setTitle: @"訪問view3" forState:UIControlStateNormal]; 
  22.     [button2 setTitleColor: [UIColor blackColor] forState:UIControlStateNormal]; 
  23.     button2.tag = 2; 
  24.     [button2 addTarget: self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside]; 
  25.     [self.view addSubview: button2]; 
  26.     UIButton *butto3 = [[UIButton alloc] initWithFrame: CGRectMake(0, 170, 200, 50)]; 
  27.     [butto3 setTitle: @"訪問webview" forState:UIControlStateNormal]; 
  28.     [butto3 setTitleColor: [UIColor blackColor] forState:UIControlStateNormal]; 
  29.     butto3.tag = 3; 
  30.     [butto3 addTarget: self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside]; 
  31.     [self.view addSubview: butto3]; 
  32.     UIButton *button4 = [[UIButton alloc] initWithFrame: CGRectMake(0, 230, 200, 50)]; 
  33.     [button4 setTitle: @"訪問wei定義的頁面" forState:UIControlStateNormal]; 
  34.     [button4 setTitleColor: [UIColor blackColor] forState:UIControlStateNormal]; 
  35.     button4.tag = 4; 
  36.     [button4 addTarget: self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside]; 
  37.     [self.view addSubview: button4]; 
  38. -(void)back:(UIButton *)btn { 
  39.     switch (btn.tag) { 
  40.         case 1: { 
  41.             NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; 
  42.     [dic setValue: @"nihao shijie" forKey:@"title"]; 
  43.     UIViewController *controller = [[WXRouter sharedInstance] getViewController: @"MSG001" withParam:dic]; 
  44.     [self presentViewController: controller animated:YES completion:nil]; 
  45. break; 
  46.         case 2: { 
  47.     NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; 
  48.             [dic setValue: @"nihao shijie" forKey:@"title"]; 
  49.     UIViewController *controller = [[WXRouter sharedInstance] getViewController: @"MSG002"  withParam:dic]; 
  50.     [self presentViewController: controller animated:YES completion:nil]; 
  51. break; 
  52.         case 3: { 
  53.     NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; 
  54.             [dic setValue: @"https://www.baidu.com" forKey:@"url"]; 
  55.     UIViewController *controller = [[WXRouter sharedInstance] getViewController: @"MSG003" withParam:dic]; 
  56.     [self presentViewController: controller animated:YES completion:nil]; 
  57. break; 
  58.         case 4: { 
  59.     UIViewController *controller = [[WXRouter sharedInstance] getViewController: @"MSG005"  withParam:nil]; 
  60.     [self presentViewController: controller animated:YES completion:nil]; 
  61. default
  62.             break; 
  63. -(void)didReceiveMemoryWarning { 
  64. [super didReceiveMemoryWarning]; 
  65.     // Dispose of any resources that can be recreated. 
  66. @end  

說明:這個是使用示例,為了獲取***的靈活性,這里我并沒有把跳轉動作presentViewcontroller,pushViewController,以及參數的組裝封裝在路由管理類里。看過很多大神寫的路由庫,有些也通過url schema的方式。類似于:xml:id/123/name/xu,這樣的路徑方式,但是個人感覺,如果界面之間傳遞圖片對象,或者傳嵌套的類對象,就有點麻煩了。因為怕麻煩,所以就先寫個簡單的吧。

  1. #import "view3.h" 
  2. @interface view3 () 
  3. @end 
  4. @implementation view3 
  5. - (void)viewDidLoad { 
  6.     [super viewDidLoad]; 
  7.     UILabel *lable = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 100, 50)]; 
  8.     lable.textColor = [UIColor blueColor]; 
  9.     lable.text =@"我是view3"
  10.     [self.view addSubview: lable]; 
  11.     UIButton *button = [[UIButton alloc] initWithFrame: CGRectMake(200, 200, 200, 200)]; 
  12.     [button setTitle: @"back" forState:UIControlStateNormal]; 
  13.     [button setTitleColor: [UIColor blackColor] forState:UIControlStateNormal]; 
  14.     [button addTarget: self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; 
  15.     [self.view addSubview: button]; 
  16. -(void) back { 
  17.     [self dismissViewControllerAnimated: YES completion:nil]; 
  18. -(void)iniViewControllerParam:(NSDictionary *)dic { 
  19.     self.title = [dic objectForKey: @"title"]; 
  20.  

說明:這個是要跳轉的頁面我們可以通過iniViewControllerParam:(NSDictionary *)dic方法獲取上一個界面傳過來的參數。 

 

 

urlMap.plist 

urlMap.plist

說明:路由配置文件,key:value的形式,頁面里的每個跳轉動作都會對應一個唯一的key,這里如果兩個頁面都跳轉到同一個頁面,就會產生不同的key 對應相同的value,感覺是有點冗余了,如果有更好的優化,我會更新下文章的,這里的配置文件我們可以怎么玩,由于我在android的這塊的描述已經很詳細了,所以這里就不再贅述。只是android的配置有點坑,類前需要加上包名,這點就沒有iOS方便靈活了,至此iOS示例我就講完了。

總結:代碼是簡陋的,只是簡單的實現了自己的構想,還有很多值得細細琢磨的地方,關鍵是架構思路,通過中間路由根據下發的路由配置文件來動態跳轉頁面,解決原生開發的遇到的一些問題,不同的項目有不同的業務邏輯,這種思路有什么缺陷,或者解決不了什么問題,大家一起討論分享。基于這種思路搭建架子的話,對于將來的組件化開發,應該也會很方便轉換吧。😊

demo地址

android:https://github.com/lerpo/WXAndroidRouter.git

iOS :https://github.com/lerpo/WXiOSRouter.git

責任編輯:龐桂玉 來源: iOS大全
相關推薦

2017-01-19 19:43:53

2010-01-15 10:15:34

分布式交換技術

2023-03-31 13:31:45

2010-08-10 10:10:28

系統架構

2025-04-15 04:00:00

2018-05-10 13:42:11

Hadoop架構大數據

2022-02-18 11:13:53

監控架構系統

2011-06-16 10:00:28

視覺設計

2013-05-27 10:58:28

Tumblr架構設計雅虎收購

2023-05-12 08:06:46

Kubernetes多云架構

2019-09-10 13:58:57

動態路由路由器網絡

2014-03-25 14:21:18

WebSocket實時

2025-05-09 08:45:13

2021-07-07 10:00:03

深度學習系統機構

2015-06-02 04:17:44

架構設計審架構設計說明書

2009-07-06 10:36:41

敏捷開發

2021-11-08 06:57:35

Redis架構設計

2011-08-29 10:59:47

QtWebkit嵌入式

2023-07-05 08:00:52

MetrAuto系統架構

2009-01-15 09:43:51

Web架構設計緩存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一级在线观看 | 91精品国产91久久久久久吃药 | 91精品久久久久久久久久 | 久久久久久国产精品久久 | 一区二区三区四区五区在线视频 | 日韩视频一区二区三区 | 国产黄色小视频在线观看 | 做a的各种视频 | 欧美黄色性生活视频 | 久久久影院 | 91看片在线观看 | 国产蜜臀 | 91在线视频观看 | 在线观看免费国产 | 欧美精品综合在线 | 亚洲高清免费 | 国产福利资源 | 精品精品 | 久久久xxx| av网站观看 | 国产欧美精品一区二区 | 国产探花在线精品一区二区 | 久久久久久国产精品三区 | 一级毛片观看 | 中文字幕在线一区 | 7777在线视频| 国产精品久久精品 | 免费一区二区 | 在线观看视频91 | 亚洲免费在线观看 | 久久久综合精品 | 国产午夜精品视频 | 国产精品日日摸夜夜添夜夜av | 亚洲精品黑人 | 欧洲精品视频一区 | 中文在线播放 | 亚洲第一av | 黄色免费在线观看网站 | 91小视频在线 | 在线观看国产www | 天天插天天干 |