欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter自動路由插件auto_route使用詳解

 更新時間:2022年08月11日 14:08:04   作者:xiangzhihong  
這篇文章主要為大家介紹了Flutter自動路由插件auto_route的基本使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、簡介

在Flutter應(yīng)用開發(fā)過程中,多個頁面的跳轉(zhuǎn)需要使用路由,除了官方提供的Navigator外,我們還可以使用一些第三方路由框架來實現(xiàn)頁面的管理和導(dǎo)航,如Fluro、Frouter等。不過,今天要給大家介紹的是另一款路由框架auto_route。

auto_route是一個設(shè)計精簡、低耦合的路由框架,支持自動生成路由代碼、動態(tài)添加路由、以及路由的參數(shù)傳遞等功能。相比其他的路由框架,auto_route的使用也更加簡潔。

二、基本使用

2.1 安裝插件

和其他Flutter插件的使用流程一樣,使用之前需要先在項目中安裝auto_route插件,安裝的的腳本如下:

dependencies:              
  auto_route: [latest-version]              
dev_dependencies:              
  auto_route_generator: [latest-version]              
  build_runner:       

2.2 定義路由表

接下來,定義一個路由表的管理類,用來同意管理應(yīng)用的路由,需要使用@MaterialAutoRouter注解進(jìn)行標(biāo)識,如下。       

@MaterialAutoRouter(              
  replaceInRouteName: 'Page,Route',              
  routes: <AutoRoute>[              
    AutoRoute(page: BookListPage, initial: true),              
    AutoRoute(page: BookDetailsPage),              
  ],              
)              
class $AppRouter {}

要生成路由文件的一部分而不是獨立的 AppRouter 類,只需將 Part 指令添加到AppRouter 并擴(kuò)展生成的私有路由器即可。

part 'app_router.gr.dart';      
@MaterialAutoRouter(              
  replaceInRouteName: 'Page,Route',              
  routes: <AutoRoute>[              
    AutoRoute(page: BookListPage, initial: true),              
    AutoRoute(page: BookDetailsPage),              
  ],              
)              
class AppRouter extends _$AppRouter{}

接下來,我們使用build_runner提供的命令即可生成路由代碼。

//自動刷新路由表
flutter packages pub run build_runner watch       
//生成路由代碼
flutter packages pub run build_runner build 

等待命令執(zhí)行完成之后,即可在app_router.dart同級的目錄下生成一個app_route.gr.dart文件,也是我們執(zhí)行路由跳轉(zhuǎn)時需要用到的代碼。最后,我們打開main.dart入口文件,然后注冊路由文件。

class App extends StatelessWidget {      
  final _appRouter = AppRouter();      
  @override      
  Widget build(BuildContext context){      
    return MaterialApp.router(      
      routerDelegate: _appRouter.delegate(),      
      routeInformationParser: _appRouter.defaultRouteParser(),      
    );      
  }      
}

2.3 生成路由

當(dāng)然,auto_route還支持為每個聲明的 AutoRoute 生成一個 PageRouteInfo 對象,這些對象包含路徑信息以及從頁面的默認(rèn)構(gòu)造函數(shù)中提取的強(qiáng)類型頁面參數(shù)。

class BookListRoute extends PageRouteInfo {              
  const BookListRoute() : super(name, path: '/books');              
  static const String name = 'BookListRoute';              
}

并且,如果聲明的路由有子路由,那么 AutoRoute 會在其構(gòu)造函數(shù)中添加一個子參數(shù),如下。

class UserRoute extends PageRouteInfo {              
   UserRoute({List<PagerouteInfo> children}) :              
    super(              
         name,               
         path: '/user/:id',              
         initialChildren: children);              
  static const String name = 'UserRoute';              
}

2.4 路由跳轉(zhuǎn)

和其他的路由框架一樣,AutoRouter 也提供常見的 push、pop 和 remove 方法。比如,我們要打一個新的頁面,那么可以使用下面

AutoRouter.of(context).replaceAll([const LoginRoute()]);  //LoginRoute為路由
//或者
AutoRouter.of(context).navigate(const BooksListRoute())       

如果我們使用的是命名路由,那么可以使用navigateNamed()方法,如下。

AutoRouter.of(context).pushNamed('/books') ;

當(dāng)然,很多時候,路由的跳轉(zhuǎn)還會涉及很多的參數(shù)傳遞,那么對于需要傳遞參數(shù)的路由,我們需要怎么處理呢?對于參數(shù)傳遞,我們可以在目標(biāo)路由頁面使用構(gòu)造函數(shù)的方式,然后再用AutoRouter進(jìn)行傳遞。

AutoRouter.of(context).pushAll([IndexRoute(login: true)]);

除了跳轉(zhuǎn),我們還可能需要處理路由彈棧的場景,對于彈棧,需要用到pop()函數(shù)。和其他的路由框架一樣,pop()默認(rèn)只彈出一個,如果要彈出多個,可以使用下面的方式。

//彈出到指定的路由        
context.router.popUntilRouteWithName('HomeRoute');          
//彈出到最頂部
context.router.popUntilRoot();            

 如果要清除,或者刪除路由棧里面的內(nèi)容,可以是呀AutoRouter還提供了remove()函數(shù)。

context.router.removeLast();           
context.router.removeWhere((route) => );                  

下面是AutoRouter常用方法的一個匯總。

context.pushRoute(const BooksListRoute());          
context.replaceRoute(const BooksListRoute());          
context.navigateTo(const BooksListRoute());          
context.navigateNamedTo('/books');          
context.navigateBack();         
context.popRoute();

2.5 處理返回結(jié)果

有時候,兩個路由之間,需要獲取頁面的處理結(jié)果,并將結(jié)果返回給上一個頁面。對于這種場景,只需要在返回的時候返回結(jié)果即可,并在上一個路由使用await進(jìn)行接收。

router.pop<bool>(true);    
var result = await router.push<bool>(LoginRoute()); 

三、路由導(dǎo)航

3.1 嵌套導(dǎo)航

在應(yīng)用開發(fā)中,嵌套導(dǎo)航是一種比較常見的場景,這意味著,在一個路由頁面中嵌套另外的多個路由。

嵌套路由就像父路由的子字段一樣。在上面的示例中,UsersPage、PostsPage 和SettingsPage就是DashboardPage的子路由,所以它們的定義如下。

@MaterialAutoRouter(              
  replaceInRouteName: 'Page,Route',              
  routes: <AutoRoute>[              
    AutoRoute(              
      path: '/dashboard',              
      page: DashboardPage,              
      children: [              
        AutoRoute(path: 'users', page: UsersPage),              
        AutoRoute(path: 'posts', page: PostsPage),          
        AutoRoute(path: 'settings', page: SettingsPage),                
      ],              
    ),          
    AutoRoute(path: '/login', page: LoginPage)          
  ],              
)              
class $AppRouter {}

要完成嵌套路由渲染和構(gòu)建,我們需要在嵌套路由的最外層使用AutoRouter 的小部件,如下。

class DashboardPage extends StatelessWidget {          
  @override          
  Widget build(BuildContext context) {          
    return Row(          
      children: [          
        Column(          
          children: [          
            NavLink(label: 'Users', destination: const UsersRoute()),          
            NavLink(label: 'Posts', destination: const PostsRoute()),          
            NavLink(label: 'Settings', destination: const SettingsRoute()),          
          ],          
        ),          
        Expanded(          
          // nested routes will be rendered here          
          child: AutoRouter(),          
        )          
      ],          
    );          
  }          
}

如果我們需要跳轉(zhuǎn)到嵌套路由的子組件,我們使用下面的方式就可以導(dǎo)航到嵌套路由的子路由。

AutoRoute(              
      path: '/dashboard',              
      page: DashboardPage,              
      children: [              
        AutoRoute(path: '', page: UsersPage),          
        //The same thing can be done using the initial flag          
        //AutoRoute(page: UsersPage,initial: true),              
        AutoRoute(path: 'posts', page: PostsPage),              
      ],              
    ),     

3.2 Tab 導(dǎo)航

前面我們介紹的都是棧管理,即StackRouter,遵循先進(jìn)后出的邏輯。除了支持StackRouter,auto_route還支持Tab Navigation,下面是示例代碼。  

class DashboardPage extends StatelessWidget {          
  @override          
  Widget build(BuildContext context) {          
    return AutoTabsRouter(                 
      routes: const [          
        UsersRoute(),          
        PostsRoute(),          
        SettingsRoute(),          
      ],          
      builder: (context, child, animation) {                    
        final tabsRouter = AutoTabsRouter.of(context);                  
        return Scaffold(          
            body: FadeTransition(          
              opacity: animation,          
              child: child,          
            ),          
            bottomNavigationBar: BottomNavigationBar(          
              currentIndex: tabsRouter.activeIndex,          
              onTap: (index) {             
                tabsRouter.setActiveIndex(index);          
              },          
              items: [          
                BottomNavigationBarItem(label: 'Users',...),          
                BottomNavigationBarItem(label: 'Posts',...),          
                BottomNavigationBarItem(label: 'Settings',...),          
              ],          
            ));          
      },          
    );          
  }          
}

當(dāng)然,上面的代碼看起來有點復(fù)雜,所以如果我們只是實現(xiàn)Tab導(dǎo)航,那么可以使用下面的簡潔代碼。

class DashboardPage extends StatelessWidget {          
 @override            
Widget build(context) {            
 @override          
  Widget build(context) {          
    return AutoTabsScaffold(          
       routes: const [          
        UsersRoute(),          
        PostsRoute(),          
        SettingsRoute(),          
      ],          
      bottomNavigationBuilder: (_,tabsRouter) {          
          return BottomNavigationBar(          
              currentIndex: tabsRouter.activeIndex,          
              onTap: tabsRouter.setActiveIndex          
              items: [          
                BottomNavigationBarItem(label: 'Users',...),          
                BottomNavigationBarItem(label: 'Posts',...),          
                BottomNavigationBarItem(label: 'Settings',...),          
              ],          
            )),                 
       }          
    );          
}

3.3 PageView

當(dāng)然,我們也可以使用 AutoTabsRouter.pageView 構(gòu)造函數(shù)來實現(xiàn)使用 PageView 的選項卡。

AutoTabsRouter.pageView(      
     routes: [      
        BooksTab(),      
        ProfileTab(),      
        SettingsTab(),      
        ],     
     builder: (context, child, _) {      
        return Scaffold(      
              appBar: AppBar(      
              title: Text(context.topRoute.name),      
              leading: AutoLeadingButton()),      
              body: child,      
              bottomNavigationBar: BottomNavigationBar(          
                    currentIndex: tabsRouter.activeIndex,          
                    onTap: tabsRouter.setActiveIndex          
                    items: [          
                      BottomNavigationBarItem(label: 'Books',...),          
                      BottomNavigationBarItem(label: 'Profile',...),          
                      BottomNavigationBarItem(label: 'Settings',...),          
                    ],          
                  ),    
            ),      
      ); },    
   ); 

3.4 聲明式導(dǎo)航

聲明式導(dǎo)航需要與 auto_route 一起使用,只需要使用 AutoRouter.declarative 構(gòu)造函數(shù)并返回基于狀態(tài)的路由列表即可。

AutoRouter.declarative(      
  routes: (handler) => [      
     BookListRoute(),      
     if(_selectedBook != null)      
     BookDetailsRoute(id: _selectedBook.id),      
 ],);

四、高級用法

4.1 路由控制器

事實上,每個嵌套的 AutoRouter 都有自己的路由控制器來管理其內(nèi)部的堆棧,獲得路由控制器最簡單的方法是使用上下文。在前面的示例中,我們調(diào)用的 AutoRouter.of(context) 就是用來獲得根路由控制器的。

需要說明的是,對于渲染嵌套路由的 AutoRouter 小部件,我們使用上面的方式獲取的 是小部件樹中最近的父控制器而不是根控制器,下面是一個典型的路由控制器的結(jié)構(gòu)示意圖。

從上圖中可以看出,我們可以通過調(diào)用 router.parent() 來訪問父路由控制器,對于這個通用函數(shù),在真正調(diào)用的時候,我們還需要指定類型,比如StackRouter/TabsRouter。

router.parent<StackRouter>()  
router.parent<TabsRouter>()

當(dāng)然,如果是獲取根路由控制器,那么是不需要進(jìn)行類型轉(zhuǎn)換的,因為它始終是 StackRouter。

router.root

另一方面,為了在其他地方使用這個路由控制器,可以定義一個全局的key,比如。

class DashboardPage extends StatefulWidget {          
  @override          
  _DashboardPageState createState() => _DashboardPageState();          
}          
class _DashboardPageState extends State<DashboardPage> {          
  final _innerRouterKey = GlobalKey<AutoRouterState>();          
  @override          
  Widget build(BuildContext context) {          
    return Row(          
      children: [          
        Column(          
          children: [          
            NavLink(label: 'Users',          
            onTap:(){          
               final router = _innerRouterKey.currentState?.controller;          
               router?.push(const UsersRoute());          
             }          
            ),          
            ...          
          ],          
        ),          
        Expanded(          
          child: AutoRouter(key: _innerRouterKey),          
        )          
      ],          
    );          
  }          
}

當(dāng)然,我們也可以在沒有全局key的情況下,使用下面的方式獲取路由控制器,條件是這個路由已經(jīng)啟動,這個有點類似于Java的反射機(jī)制。            

context.innerRouterOf<StackRouter>(UserRoute.name)                        
context.innerRouterOf<TabsRouter>(UserRoute.name)

4.2 Paths

在 AutoRoute 中,使用路徑是可選的,因為 PageRouteInfo 對象是按名稱匹配的,除非使用根委托中的 initialDeepLink、pushNamed、replaceNamed和navigateNamed 等方法。

如果我們不指定路徑,系統(tǒng)將自動生成路徑,例如BookListPage 將“book-list-page”作為路徑,如果初始 arg 設(shè)置為 true,則路徑將為“/”。在Flutter開發(fā)中,當(dāng)頁面層級比較深時,就可以使用paths方式。

AutoRoute(path: '/books', page: BookListPage),

4.2.1 Path Parameters

當(dāng)然,我們還可以在paths中添加參數(shù)。

AutoRoute(path: '/books/:id', page: BookDetailsPage),

然后,我們只需要在目標(biāo)路由使用 @PathParam('optional-alias') 方式即可獲取傳遞的參數(shù),比如。

class BookDetailsPage extends StatelessWidget {              
  const BookDetailsPage({@PathParam('id') this.bookId});          
  final int bookId;              
  ...              

4.2.2 Inherited Path Parameters

不過,如果使用 @PathParm() 標(biāo)識的構(gòu)造函數(shù)參數(shù)與路由沒有同名的路徑參數(shù)但它的父級有,那么該路徑參數(shù)將被繼承并且生成的路由不會將此作為參數(shù)。

AutoRoute(  
	  path: '/product/:id',  
	  page: ProductScreen,  
	  children: [  
		  AutoRoute(path: 'review',page: ProductReviewScreen),  
	 ],
 ),

當(dāng)然,我們還可以在路由頁面添加一個名為 id 的路徑參數(shù),從上面的示例中,我們知道ProductReviewScreen沒有路徑參數(shù),在這種情況下,auto_route 將檢查是否有任何祖先路徑可以提供此路徑參數(shù),如果有則會標(biāo)記它作為路徑參數(shù),否則會引發(fā)錯誤。

class ProductReviewScreen extends StatelessWidget {  
  const ProductReviewScreen({super.key, @pathParam required String id}); 
}

4.2.3 Query Parameters 

和前面的查詢參數(shù)的方式相同,只需使用 @QueryParam('optional-alias') 注解構(gòu)造函數(shù)參數(shù)即可獲取參數(shù)的值。

RouteData.of(context).pathParams;                          
context.routeData.queryParams

如果參數(shù)名稱與路徑/查詢參數(shù)相同,則可以使用 const @pathParam 或者@queryParam 并且不需要傳遞 slug/別名,比如。

class BookDetailsPage extends StatelessWidget {              
  const BookDetailsPage({@pathParam this.id});          
  final int id;              
  ...

4.2.4 Redirecting Paths

當(dāng)然,我們也可以使用RedirectRoute來實現(xiàn)路徑的重定向,重定向路徑時需要使用redirectTo參數(shù)指定重定后的路由,比如。

<AutoRoute> [              
     RedirectRoute(path: '/', redirectTo: '/books'),              
     AutoRoute(path: '/books', page: BookListPage),              
 ]    

當(dāng)然,使用重定向時還可以跟一些參數(shù),比如。

<AutoRoute> [              
     RedirectRoute(path: 'books/:id', redirectTo: '/books/:id/details'),              
     AutoRoute(path: '/books/:id/details', page: BookDetailsPage),              
 ]

除此之外,auto_route 還支持使用通配符來匹配無效或未定義的路徑,可以將它作為默認(rèn)的路徑。

AutoRoute(path: '*', page: UnknownRoutePage)                        
AutoRoute(path: '/profile/*', page: ProfilePage)                            
RedirectRoute(path: '*', redirectTo: '/')

4.3 路由守護(hù)

我們可以將路由守衛(wèi)視為中間件或者攔截器,不經(jīng)過分配的守衛(wèi)無法將路由添加到堆棧中,這對于限制對某些路由的訪問是很有用,相當(dāng)于在執(zhí)行路由跳轉(zhuǎn)前我們可以對路由做一些限制。

下面,我們使用 AutoRouteGuard 創(chuàng)建一個路由保護(hù),然后在 onNavigation 方法中實現(xiàn)我們的路由邏輯。

class AuthGuard extends AutoRouteGuard {          
 @override          
 void onNavigation(NavigationResolver resolver, StackRouter router) {          
      //觸發(fā)條件          
     if(authenitcated){                 
        resolver.next(true);          
      }else{                 
         router.push(LoginRoute(onResult: (success){              
               resolver.next(success);          
          }));          
         }              
     }          
}

在onNavigation方法中,NavigationResolver 對象包含可以調(diào)用的屬性,所以我們可以使用resolver.route 訪問的受保護(hù)路由,以及調(diào)用resolver.pendingRoutes 訪問掛起的路由列表。

接下來,我們將守衛(wèi)分配給我們想要保護(hù)的路線即可,使用方式如下。

AutoRoute(page: ProfileScreen, guards: [AuthGuard]); 

有時候,我們希望獲取父窗口包裹的小部件的上下文提供的一些值,那么只需實現(xiàn) AutoRouteWrapper,并讓 WrapRoute(context) 方法返回小部件的子級即可。

class ProductsScreen extends StatelessWidget implements AutoRouteWrapper {          
  @override          
  Widget wrappedRoute(BuildContext context) {          
  return Provider(create: (ctx) => ProductsBloc(), child: this);      
  }          
  ...

4.4 路由觀察者

為了方便查看路由棧的具體情況,我們可以通過擴(kuò)展 AutoRouterObserver 來實現(xiàn),然后重寫里面的函數(shù)來進(jìn)行查看,比如。

class MyObserver extends AutoRouterObserver {          
  @override          
  void didPush(Route route, Route? previousRoute) {          
    print('New route pushed: ${route.settings.name}');          
  }                  
 @override          
  void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {          
    print('Tab route visited: ${route.name}');          
  } 
  @override          
  void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {          
    print('Tab route re-visited: ${route.name}');          
  }          
}

然后,我們將觀察者傳遞給根委托 AutoRouterDelegate。

return MaterialApp.router(          
      routerDelegate: AutoRouterDelegate(          
        _appRouter,          
        navigatorObservers: () => [MyObserver()],          
      ),          
      routeInformationParser: _appRouter.defaultRouteParser(),        
    );

以上就是Flutter自動路由插件auto_route使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter自動路由插件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android開發(fā)中記一個SwipeMenuListView側(cè)滑刪除錯亂的Bug

    Android開發(fā)中記一個SwipeMenuListView側(cè)滑刪除錯亂的Bug

    這篇文章主要介紹了Android開發(fā)中記一個SwipeMenuListView側(cè)滑刪除錯亂的Bug的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • Ionic2創(chuàng)建App啟動頁左右滑動歡迎界面

    Ionic2創(chuàng)建App啟動頁左右滑動歡迎界面

    使用Ionic2創(chuàng)建應(yīng)用非常簡單,只需在V1的命令后跟上--v2即可.這篇文章主要介紹了Ionic2創(chuàng)建App啟動頁左右滑動歡迎界面的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Android Animation實戰(zhàn)之屏幕底部彈出PopupWindow

    Android Animation實戰(zhàn)之屏幕底部彈出PopupWindow

    這篇文章主要為大家介紹了Android Animation動畫實戰(zhàn)項目,屏幕底部彈出PopupWindow,如何實現(xiàn)?文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-01-01
  • android,不顯示標(biāo)題的方法小例子

    android,不顯示標(biāo)題的方法小例子

    android,不顯示標(biāo)題的方法小例子,需要的朋友可以參考一下
    2013-05-05
  • Android系統(tǒng)對話框使用詳解(最詳細(xì))

    Android系統(tǒng)對話框使用詳解(最詳細(xì))

    這篇文章主要介紹了Android系統(tǒng)對話框使用詳解(最詳細(xì)),需要的朋友可以參考下
    2017-10-10
  • Android編程之菜單Menu的創(chuàng)建方法示例

    Android編程之菜單Menu的創(chuàng)建方法示例

    這篇文章主要介紹了Android編程之菜單Menu的創(chuàng)建方法,結(jié)合實例形式分析了Android菜單Menu的布局、響應(yīng)及功能實現(xiàn)技巧,需要的朋友可以參考下
    2017-08-08
  • android獲取圖片尺寸的兩種方式及bitmap的縮放操作

    android獲取圖片尺寸的兩種方式及bitmap的縮放操作

    這篇文章主要介紹了android獲取圖片尺寸的兩種方式及bitmap的縮放操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Android Studio使用小技巧:自定義Logcat

    Android Studio使用小技巧:自定義Logcat

    這篇文章主要介紹了Android Studio使用小技巧:自定義Logcat,本文講解如何自定義Logcat的顏色,實現(xiàn)區(qū)別verbose、debug、error等分類信息,需要的朋友可以參考下
    2015-05-05
  • 最新評論