如何同时使用Navigator.push和Navigator.push

问题描述

我已向Flutter应用程序添加了一些路线,以便在按下特定链接时将打开特定页面

这是主页的源代码

  import 'dart:convert';

import 'package:admob_Flutter/admob_Flutter.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:catcher/catcher.dart';
import 'package:dynamic_theme/dynamic_theme.dart';
import 'package:firebase_admob/firebase_admob.dart';
import 'package:Flutter/material.dart';
import 'package:Flutter_bloc/Flutter_bloc.dart';
import 'package:Flutter_local_notifications/Flutter_local_notifications.dart';
import 'package:Flutter_native_timezone/Flutter_native_timezone.dart';
import 'package:videos/c.dart';
import 'package:Flutter/foundation.dart';
import 'package:videos/post.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

import 'database/database.dart';
import 'database/database/mobile.dart' as mobile;
import 'src/app_route.dart';

void main() async{
  WidgetsFlutterBinding.ensureInitialized();
  FirebaseAdMob.instance.initialize(appId: APP_ID);
  Admob.initialize(APP_ID);
  await AndroidAlarmManager.initialize();

  CatcherOptions debugOptions =CatcherOptions(DialogReportMode(),[kIsWeb?ConsoleHandler(): EmailManualHandler(["ahmad.rajab@windowslive.com"])]);
  CatcherOptions releaSEOptions = CatcherOptions(DialogReportMode(),[
    kIsWeb?ToastHandler():EmailManualHandler(["ahmad.rajab@windowslive.com"])
  ]);
  Catcher(MyApp(),debugConfig: debugOptions,releaseConfig: releaSEOptions);
}

class MyApp extends StatefulWidget{
  @override
  State<StatefulWidget> createState()=>MyAppState();
}

class MyAppState extends State<MyApp> {

  static Future configureDatabase()async{
    /*database = await openDatabase(DATABASE_NAME,version: DATABASE_VERSION,onCreate: (Database db,int version) async {
      await db.execute('create table $WATCHED_VIDEOS ($VIDEO_ID text,$REACHED_SECOND integer default 0,$NOTE text)');
      await db.execute('create table $TABLE_FAVORITE_VIDEOS ($VIDEO_TITLE text,$VIDEO_ID text,$VIDEO_DESCRIPTION text,$VIDEO_THUMBURL text)');
      await db.execute('create table $CHANNELS ($ID integer,$NAME text,$LINK text,$PICTURE_LINK text,$VIEWED integer default 0,$GET_NOTIFICATIONS integer default 1,$LAST_VIDEO_TITLE text)');
     },onUpgrade: (db,oldVersion,newVersion)async {
       var tableColumns= await db.query('PRAGMA table_info($WATCHED_VIDEOS)');
       bool noteColumnExists=false;
       for(int c=0;c<tableColumns.length;c++){
         if(tableColumns[c]['name'].toString()==NOTE)noteColumnExists=true;
       }
       if(!noteColumnExists) await db.execute('alter table $WATCHED_VIDEOS add $NOTE text');
     },);
    */
  }

  AppRouterDelegate _routerDelegate = AppRouterDelegate();
  AppRouteinformationParser _routeinformationParser =
      AppRouteinformationParser();

  @override
  void initState() {
    super.initState();
    initialiseNotification();
    initialiseTimeZone();
    showDailyReminderNotification();
    configureDailyNewVideosFitch();
  }

  void configureDailyNewVideosFitch()async{
      await AndroidAlarmManager.periodic(const Duration(days: 1),DAILY_NEW_VIDEOS_FETCH_ALaraM_ID,()async{
        Database d=RepositoryProvider.of<Database>(context);
        List<Channel>subscribedChannels=await (d.select($ChannelsTable(d))..where((tbl) => tbl.getNotifications.equals(1))).get();
        String channelsIds='';
        for(int i=0;i<subscribedChannels.length;i++)channelsIds+=subscribedChannels[i].link+"/";
        Map<String,String> map=Map();
        map['channels']=channelsIds;
        Post p=Post(context,'getVideosFromTime.PHP',map);
        await p.fetchPost();
        if(p.connectionSucceed){
          dynamic resultJson=json.decode(p.result);
          if(resultJson['result']=='success'){
            for(int i=0;i<resultJson['data'].length;i++){
              dynamic videoJson=resultJson['data'][i];
              await FlutterlocalnotificationsPlugin.show(videoJson['id'],videoJson['channelName'],videoJson['title'],NotificationDetails(
                 android: AndroidNotificationDetails(
                   APP_NAME,APP_NAME,NEW_VIDEO_AVAILABLE,icon: '@mipmap/ic_launcher',ticker: videoJson['title']
               ),),payload:'/watch?v='+videoJson['videoId']
             );
            }
          }
        }
      },rescheduleOnReboot: true);

  }

  FlutterlocalnotificationsPlugin FlutterlocalnotificationsPlugin;

  void showDailyReminderNotification()async{
    const AndroidNotificationDetails androidplatformChannelSpecifics =
        AndroidNotificationDetails(APP_NAME,'dailyReminder'+APP_NAME,ticker: TIME_TO_LEARN);
    const NotificationDetails platformChannelSpecifics =
        NotificationDetails(android: androidplatformChannelSpecifics);
    await FlutterlocalnotificationsPlugin.periodicallyShow(DAILY_REMINDER_NOTIFICATION_ID,TIME_TO_LEARN,TIME_TO_LEARN_DESCRIPTION,RepeatInterval.daily,platformChannelSpecifics,androidAllowWhileIdle: false);
  }

  void initialiseTimeZone()async{
    tz.initializeTimeZones();
    tz.setLocalLocation(tz.getLocation(await FlutterNativeTimezone.getLocalTimezone()));
  }

  void initialiseNotification()async{
   FlutterlocalnotificationsPlugin =
      FlutterlocalnotificationsPlugin();
  // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  final IOSInitializationSettings initializationSettingsIOS =
      IOSInitializationSettings(
          /*onDidReceivelocalnotification: onDidReceivelocalnotification*/);
  final MacOSInitializationSettings initializationSettingsMacOS =
      MacOSInitializationSettings();
  final InitializationSettings initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,iOS: initializationSettingsIOS,macOS: initializationSettingsMacOS);
  await FlutterlocalnotificationsPlugin.initialize(initializationSettings,onSelectNotification: selectNotification);
  await FlutterlocalnotificationsPlugin.cancel(DAILY_REMINDER_NOTIFICATION_ID);
}

Future selectNotification(String payload) async {
    if(payload!=null)Navigator.pushNamed(context,payload);
}

  @override
  Widget build(BuildContext context) {
    return DynamicTheme(
          defaultBrightness: Brightness.light,data: (brightness) => ThemeData(
            primarySwatch: PRIMARY_COLOR,brightness: brightness
          ),themedWidgetBuilder: (context,data) {
     return RepositoryProvider<Database>(
      create:(context)=>mobile.constructDb(),child: BlocProvider(
        create: (context){
          //final db = RepositoryProvider.of<Database>(context);
          //return AppBloc(db);
        },child: MaterialApp.router(
              //title: 'Books App',theme: data,routerDelegate: _routerDelegate,routeinformationParser: _routeinformationParser,)
      )
     );
    }
  );
}
}

MobileAdtargetingInfo targetingInfo = MobileAdtargetingInfo(
  // ignore: deprecated_member_use
  gender: MobileAdGender.unkNown,childDirected: true
);

class AdmobAdd extends StatelessWidget{
    @override
  Widget build(BuildContext context) {
    return !PRO?AdmobBanner(
              adUnitId: kReleaseMode?BANNER_AD_UNIT_ID:BannerAd.testAdUnitId,adSize: AdmobBannerSize.BANNER,):Container();
  }
  }

InterstitialAd myInterstitial = InterstitialAd(
  adUnitId: InterstitialAd.testAdUnitId,targetingInfo: targetingInfo,);

这是路由配置文件的源代码

   import 'package:catcher/catcher.dart';
import 'package:Flutter/cupertino.dart';
import 'package:Flutter/material.dart';
import 'package:videos/home.dart';
import 'package:videos/video.dart';

class AppRouteinformationParser extends RouteinformationParser<AppRoutePath> {
  @override
  Future<AppRoutePath> parseRouteinformation(
      Routeinformation routeinformation) async {
    final uri = Uri.parse(routeinformation.location);
    // Handle '/'
    if (uri.pathSegments.length == 0) {
      return AppRoutePath.home();
    }

    // Handle '/watch?v=fsdfsdfsd
    if (uri.pathSegments.length == 1) {
      if (!uri.pathSegments[0].startsWith('/watch?')) return AppRoutePath.unkNown();
      if(uri.pathSegments[0].startsWith('/watch?v=')){
        var videoId=uri.queryParameters['v'];
        return AppRoutePath.video(videoId);
        /*var remaining = uri.pathSegments[1];
        var id = int.tryParse(remaining);
        if (id == null) return AppRoutePath.unkNown();
        return AppRoutePath.details(id);*/
      }
    }

    // Handle unkNown routes
    return AppRoutePath.unkNown();
  }

  @override
  Routeinformation restoreRouteinformation(AppRoutePath path) {
    if (path.isUnkNown) {
      return Routeinformation(location: '/404');
    }
    if (path.isHomePage) {
      return Routeinformation(location: '/');
    }
    if(path.isVideoPage){
      return Routeinformation(location: '/watch?v=${path.id}');
    }
    if (path.isDetailsPage) {
      return Routeinformation(location: '/book/${path.id}');
    }
    return null;
  }
}

class AppRouterDelegate extends RouterDelegate<AppRoutePath>
    with ChangeNotifier,PopNavigatorRouterDelegateMixin<AppRoutePath> {
  final GlobalKey<NavigatorState> navigatorKey;

  //Book _selectedBook;
  bool show404 = false;
  String videoId;
  /*List<Book> books = [
    Book('Stranger in a Strange Land','Robert A. Heinlein'),Book('Foundation','Isaac Asimov'),Book('Fahrenheit 451','Ray Bradbury'),];*/

  AppRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();

  AppRoutePath get currentConfiguration {
    if (show404) {
      return AppRoutePath.unkNown();
    }
    if(videoId!=null) return AppRoutePath.video(videoId);
    /*return _selectedBook == null
        ? AppRoutePath.home()
        : AppRoutePath.details(books.indexOf(_selectedBook));*/
    return AppRoutePath.home();
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: Catcher.navigatorKey,pages: [
        MaterialPage(
          key: ValueKey('Home'),child: MyHomePage()
        ),if (show404)
          MaterialPage(key: ValueKey('UnkNown'),child: UnkNownScreen())
        else if(videoId!=null) VideoPageRoute(videoId: videoId)
        /*else if (_selectedBook != null)
          BookDetailsPage(book: _selectedBook)*/
      ],onPopPage: (route,result) {
        if (!route.didPop(result)) {
          return false;
        }

        // Update the list of pages by setting _selectedBook to null
        //_selectedBook = null;
        videoId=null;
        show404 = false;
        notifyListeners();

        return true;
      },);
  }

  @override
  Future<void> setNewRoutePath(AppRoutePath path) async {
    if (path.isUnkNown) {
      //_selectedBook = null;
      videoId=null;
      show404 = true;
      return;
    }

    /*if (path.isDetailsPage) {
      if (path.id < 0 || path.id > books.length - 1) {
        show404 = true;
        return;
      }

      _selectedBook = books[path.id];
    } else {
      _selectedBook = null;
    }*/

    show404 = false;
  }

  void videoNotFound(){
    videoId=null;
    show404=true;
    notifyListeners();
  }

  /*void _handleBookTapped(Book book) {
    _selectedBook = book;
    notifyListeners();
  }*/
}

class AppRoutePath {
  final String id;
  final bool isUnkNown;

  AppRoutePath.home()
      : id = null,isUnkNown = false;

  AppRoutePath.details(this.id) : isUnkNown = false;

  AppRoutePath.video(this.id): isUnkNown=false;

  AppRoutePath.unkNown()
      : id = null,isUnkNown = true;

  bool get isHomePage => id == null;

  bool get isDetailsPage => id != null;

  bool get isVideoPage => id!=null;
}

/*class BooksListScreen extends StatelessWidget {
  final List<Book> books;
  final ValueChanged<Book> onTapped;

  BooksListScreen({
    @required this.books,@required this.onTapped,});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),body: ListView(
        children: [
          for (var book in books)
            ListTile(
              title: Text(book.title),subtitle: Text(book.author),onTap: () => onTapped(book),)
        ],);
  }
}
*/
/*class BookDetailsScreen extends StatelessWidget {
  final Book book;

  BookDetailsScreen({
    @required this.book,body: Padding(
        padding: const EdgeInsets.all(8.0),child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,children: [
            if (book != null) ...[
              Text(book.title,style: Theme.of(context).textTheme.headline6),Text(book.author,style: Theme.of(context).textTheme.subtitle1),],);
  }
}
*/
class UnkNownScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),body: Center(
        child: Text('404!'),);
  }
}

问题是我有几个没有特定URL的屏幕,我不想为它们提供路由,我只想使用Navigator.push()

这很好,但是当按下“后退”按钮或我使用Navigator.pop()时,应用程序将完全关闭,而不是导航回上一页

如何仅将Navigator.pushNamed用于命名路由,如何将Navigator.push用于其他页面,而不会导致问题发生

预先感谢

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)