Flutter監聽路由返回

Tecode發表於2020-05-06

前言

我們通常有這樣一個需求:點選修改使用者資訊需要跳轉頁面,修改完成以後返回之前的頁面我們需要重新獲取新的資料重新整理修改後的資料。於是就找方法去實現,目前我用過的就是以下三種方法。

程式碼地址

Navigator.of(context).pushNamed().then()

優點

  • 可以在返回頁面的時候在pop中傳入引數Navigator.pop(context, '資料傳參').then(value => print(value)),value的值就是資料傳參。(使用手勢返回接收不到引數值列印為null
  • .then方法中可以監聽到手勢返回和Navigator.pop 返回。

缺點

  • 頁面上跳轉不同頁面較多需要在每一個then方法中處理,哪怕寫成公共方法也需要都加一次。

用法

// 路由跳轉監聽返回該頁面
Navigator.of(context).pushNamed(
    '/newView',
    arguments: NewView(
        content: '網路搜尋結果漢語- 維基百科,自由的百科全書',
    ),
).then((value) => print(value));

// 返回之前的頁面帶上引數
Navigator.pop(context, '資料傳參');
複製程式碼

效果展示

Flutter監聽路由返回

deactivate

優點

  • 返回到該頁面的時候我們只需要在一個地方發請求獲取新的資料,不需要單獨加在每一個頁面跳轉的then 方法內,理論上可以滿足我們的需求。

缺點

  • 雖然deactivate會被觸發,但是進入頁面或者返回頁面都會被觸發,於是使用ModalRoute.of(context).isCurrent判斷是否是當前頁面,為true就發請求獲取新的頁面。當使用手勢返回的時一直是false,就會導致不發請求重新整理資料。
  • 不能直接獲取到引數

用法

  void deactivate() {
    super.deactivate();
    var bool = ModalRoute.of(context).isCurrent;
    if (bool) {
      // 監聽到頁面返回,發請求重新整理頁面操作
      print('返回NewView頁面');
    }
  }
複製程式碼

效果展示

Flutter監聽路由返回

didPopNext

優點

  • didPopNext可以彌補手勢返回不觸發的問題,我們也不需要去寫額外的判斷。

缺點

  • 不能直接獲取到引數

用法

// 在MaterialApp中監聽

class DynamicTheme extends StatefulWidget {
  const DynamicTheme();
  static final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
  @override
  _DynamicThemeState createState() => _DynamicThemeState();
}

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dynamic Theme',
      theme: lightTheme.copyWith(platform: _options.platform),
      darkTheme: darkTheme.copyWith(platform: _options.platform),
      themeMode: _options.themeMode,
      ...
      navigatorObservers: [DynamicTheme.routeObserver],
      ...
      routes: _buildRoutes(),
    );
  }
  
  // 頁面使用
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class NewView extends StatefulWidget {
  final String content;
  const NewView({
    this.content,
  });
  static const String routeName = '/newView';

  @override
  _NewViewState createState() => _NewViewState();
}

class _NewViewState extends State<NewView> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    DynamicTheme.routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void didPopNext() {
    // Covering route was popped off the navigator.
    print('返回NewView');
  }

  @override
  void didPush() {
    // Route was pushed onto navigator and is now topmost route.
    print('進入NewView');
  }

  @override
  void dispose() {
    DynamicTheme.routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
//    final NewView param = ModalRoute.of(context).settings.arguments;

    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        leading: CupertinoButton(
          padding: EdgeInsets.zero,
          child: Text('返回'),
          onPressed: () {
            // The demo is on the root navigator.
//            Navigator.of(context, rootNavigator: true).maybePop();
            Navigator.pop(context, '資料傳參');
          },
        ),
      ),
      child: Material(
        child: ScrollConfiguration(
          behavior: CustomBehavior(),
          child: ListView.builder(
            primary: true,
            itemCount: 60,
            itemBuilder: (BuildContext context, int index) {
              return Ink(
                child: InkWell(
                  splashColor: Colors.transparent,
                  onTap: () => Navigator.of(context).pushNamed(
                    Detail.routeName,
                    arguments: Detail(value: '引數'),
                  ),
                  child: Container(
                    height: 44.0,
                    width: MediaQuery.of(context).size.width,
                    child: Center(child: Text('Data-$index')),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}
複製程式碼

效果展示

Flutter監聽路由返回

總結

需要監聽頁面返回獲取新的資料只有一個跳轉使用then方法監聽就可以,如果跳轉比較多返回以後都需要重新整理資料建議使用didPopNext

相關文章