在没有网络连接的情况下,如何在 Flutter 中循环 AlertDialog?

问题描述 投票:0回答:1

我正在尝试循环显示“没有互联网连接。请检查您的互联网连接并重试。”的 AlertDialog。如果没有互联网连接,我希望当我按“重试”按钮时继续显示该对话框,但一旦它已经连接到互联网,警报对话框将停止并继续登录。

import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:namer_app/Passenger_Widgets/GuestRegistration.dart';
import 'package:namer_app/login_auth/login_method.dart';
import 'package:namer_app/login_auth/resetpass_method.dart';
import 'package:namer_app/Passenger_Widgets/ScheduleWindow.dart';
import 'package:namer_app/prf_login/my_buttons.dart';
import 'package:namer_app/prf_login/my_textfields.dart';
import 'package:namer_app/prf_login/snackbar_ext.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Supabase.initialize(
    url: 'https://',
    anonKey:
        '0000',
  );

  final prefs = await SharedPreferences.getInstance();
  final bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;

  List<ConnectivityResult> connectivityResults = await (Connectivity().checkConnectivity());

  ConnectivityResult connectivityResult = connectivityResults.first;

  runApp(
    MaterialApp(
      home: MyApp(connectivityResult, prefs, isLoggedIn),
    ),
  );
}

class MyApp extends StatelessWidget {
  final ConnectivityResult connectivityResult;
  final SharedPreferences prefs;
  final bool isLoggedIn;

  MyApp(this.connectivityResult, this.prefs, this.isLoggedIn);

  @override
  Widget build(BuildContext context) {
    if (connectivityResult == ConnectivityResult.none) {
      // Show a popup to inform the user that there's no internet connection
      WidgetsBinding.instance.addPostFrameCallback((_) {
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text('No Internet Connection'),
            content: Text('Please check your internet connection and try again.'),
            actions: [
              ElevatedButton(
                child: Text('Retry'),
                onPressed: () => Navigator.pop(context),
              ),
            ],
          ),
        );
      });
    }

    return MaterialApp(
      theme: ThemeData(
        appBarTheme: AppBarTheme(
          iconTheme: IconThemeData(
            color: Colors.white,
          ), // Set back button color to white
        ),
      ),
      home: isLoggedIn ? ScheduleWindow(prefs: prefs) : LOGIN_passenger(),
    );
  }
}


class LOGIN_passenger extends StatefulWidget {
  LOGIN_passenger({super.key});

  @override
  State<LOGIN_passenger> createState() => _LOGIN_passengerState();
}

class _LOGIN_passengerState extends State<LOGIN_passenger> {
  GlobalKey<FormState> _formkey = GlobalKey();
  bool _isLoading = false;
  late TextEditingController emailController;
  late TextEditingController passController;

  //LOGIN ATTEMPTS TIMER
  int _loginAttempts = 0;
  bool _isCooldown = false;
  Timer? _cooldownTimer;
  int _cooldownTime = 60; // Cooldown time in seconds

  @override
  void initState() {
    super.initState();
    emailController = TextEditingController();
    passController = TextEditingController();
  }

  @override
  void dispose() {
    emailController.dispose();
    passController.dispose();
    _cooldownTimer?.cancel();
    super.dispose();
  }

  bool isValidEmail(String input) {
    final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
    return emailRegex.hasMatch(input);
  }

  bool isValidPhoneNumber(String input) {
    final phoneWithPrefix = '63$input';
    final phoneRegex = RegExp(r'^63\d{10}$');
    return phoneRegex.hasMatch(phoneWithPrefix);
  }

  void insertPrefs(AuthResponse response) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    if (response.user != null) {
      final user = response.user?.id;
      final selectQuery = await Supabase.instance.client
          .from('registered_passenger')
          .select()
          .eq('user_id', user.toString());

      if (selectQuery.isNotEmpty) {
        prefs.setBool('isLoggedIn', true);
        prefs.setString('userId', selectQuery[0]['user_id']);
        prefs.setString('lastName', selectQuery[0]['last_name']);
        prefs.setString('firstName', selectQuery[0]['first_name']);
        prefs.setString('middleInitial', selectQuery[0]['middle_initial']);
        prefs.setString('email', selectQuery[0]['email']);
        prefs.setString('password', selectQuery[0]['password']);
        prefs.setString('profession', selectQuery[0]['profession']);
        String contactNumber = selectQuery[0]['phone'];
        prefs.setString('contactNumber', contactNumber.substring(2));
        prefs.setString('age', selectQuery[0]['age']);
        prefs.setString('gender', selectQuery[0]['gender']);
        prefs.setString('region', selectQuery[0]['region']);
        prefs.setString('province', selectQuery[0]['province']);
        prefs.setString('municipality', selectQuery[0]['municipality']);
        prefs.setString('barangay', selectQuery[0]['barangay']);
        prefs.setString('titlePage', 'Schedule');
        navigatetoSched(prefs);
      }
    }
  }

void _login() async {
  final connectivityResult = await (Connectivity().checkConnectivity());

  if (connectivityResult == ConnectivityResult.none) {
    context.showSnackbar(
      message: 'No internet connection. Please check your internet connection and try again.',
      backgroundColor: Colors.red,
    );
    setState(() {
      _isLoading = false;  // Reset _isLoading so the button can be clicked again
    });
    return;
  }

  if (_isCooldown) {
    context.showSnackbar(
      message: 'Too many attempts. Please wait $_cooldownTime seconds.',
      backgroundColor: Colors.red,
    );
    return;
  }

  final isValid = _formkey.currentState?.validate();

  if (isValid != null && isValid) {
    setState(() {
      _isLoading = true;
    });

    try {
      final input = emailController.text;
      final password = passController.text;
      final response;

      if (isValidEmail(input)) {
        response = await Supabase.instance.client.auth.signInWithPassword(
          email: input,
          password: password,
        );
        insertPrefs(response);
      } else if (isValidPhoneNumber(input)) {
        response = await Supabase.instance.client.auth.signInWithPassword(
          phone: '63$input',
          password: password,
        );
        insertPrefs(response);
      } else {
        throw AuthException('Invalid email or phone number');
      }

      setState(() {
        _isLoading = false;
      });
      context.showSnackbar(
        message: 'LOGIN SUCCESSFUL',
        backgroundColor: Colors.green,
      );
    } on AuthException catch (e) {
      if (e.message.contains('SocketException')) {
        context.showSnackbar(
          message: 'No internet connection. Please check your internet connection and try again.',
          backgroundColor: Colors.red,
        );
      } else {
        context.showSnackbar(
          message: e.message,
          backgroundColor: Colors.red,
        );
      }
      setState(() {
        _isLoading = false; // Reset _isLoading in case of an error
      });
    } catch (e) {
      context.showSnackbar(
        message: e.toString(),
        backgroundColor: Colors.red,
      );
      setState(() {
        _isLoading = false; // Reset _isLoading for other types of errors
      });
    }
  }
}


  

  /*Future<void> _logout() async {
  if (selectedFerry != null) {
    await _supabaseClient
        .from('boats')
        .update({'is_active': false}) // Set ferry as inactive
        .eq('boat_name', selectedFerry!)
  }

  // Continue with logout process
}*/

  void _handleLoginFailure(String errorMessage) {
    context.showSnackbar(message: errorMessage, backgroundColor: Colors.red);

    setState(() {
      _isLoading = false;
      _loginAttempts++;
    });

    if (_loginAttempts >= 3) {
      _startCooldown();
    }
  }

  void _startCooldown() {
    setState(() {
      _isCooldown = true;
    });

    _cooldownTimer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {
        _cooldownTime--;
      });

      if (_cooldownTime == 0) {
        timer.cancel();
        setState(() {
          _isCooldown = false;
          _loginAttempts = 0;
          _cooldownTime = 60; // Reset cooldown time
        });
      }
    });
  }

  void navigatetoSched(SharedPreferences prefs) {
    Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (_) => ScheduleWindow(prefs: prefs)),
        (route) => false);
  }

  void _forgotPassword() {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (_) => ResetpassMethod()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(270.0),
        child: AppBar(
          centerTitle: true,
          flexibleSpace: Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('images/bgprf1.png'),
                fit: BoxFit.fill,
              ),
            ),
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Image.asset(
                    'images/prf_logo.png',
                    width: 155.0,
                    height: 155.0,
                  ),
                  SizedBox(height: 10.0),
                  Text(
                    'PASIG RIVER FERRY PORTAL',
                    style: TextStyle(
                      color: Color(0xFF33385F),
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
      backgroundColor: Colors.white,
      body: Container(
        padding: EdgeInsets.all(20.0),
        child: SingleChildScrollView(
          child: Form(
            key: _formkey, // Associate the Form with the GlobalKey
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                SizedBox(height: 30.0),
                Text(
                  'WELCOME',
                  style: TextStyle(
                    color: Color(0xFF33385F),
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                Text(
                  'Please, Login to your account!',
                  style: TextStyle(
                    color: Color(0xFF666666),
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                  ),
                ),

                const SizedBox(height: 20.0),
                // Textfield for Email/Username
                Textfield_auth(
                  controller: emailController,
                  prefixIcon: Icon(Icons.person),
                  hintText: 'Enter Email/Username',
                  labelText: 'Email/Username',
                  obscureText: false,
                ),

                const SizedBox(height: 15.0),
                // Textfield for Password
                Textfield_authpass(
                  controller: passController,
                  prefixIcon: Icon(Icons.lock),
                  hintText: 'Enter Password',
                  labelText: 'Password',
                ),

                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    GestureDetector(
                      onTap: _forgotPassword,
                      child: Text(
                        'Forgot Password?',
                        style: TextStyle(
                          color: Color(0xFF666666),
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(height: 30.0),

                LoginButton(
                  onTap: _isLoading || _isCooldown ? null : _login,
                ),
                if (_isCooldown)
                  Center(
                    child: Text(
                      'Please wait $_cooldownTime seconds to try again.',
                      style: TextStyle(
                        color: Colors.red,
                        fontSize: 16,
                      ),
                    ),
                  ),

                const SizedBox(height: 20.0),
                // Continue with Google account
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 5.0),
                  child: Row(
                    children: [
                      Expanded(
                        child: Divider(
                          thickness: 1,
                          color: Colors.grey,
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 10.0),
                        child: Text(
                          'OR',
                          style: TextStyle(color: Colors.grey),
                        ),
                      ),
                      Expanded(
                        child: Divider(
                          thickness: 1,
                          color: Colors.grey,
                        ),
                      ),
                    ],
                  ),
                ),

                SizedBox(height: 30.0),
                // GOOGLE SIGN IN
                Center(
                  child: Row(
                    mainAxisSize: MainAxisSize.max,
                    children: [
                      const SizedBox(height: 5),
                      GuestButton(
                        onTap: () {
                          
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => PrfGuestRegistration(),
                            ),
                          );
                        },
                      ),
                      SignUpButton(
                        onTap: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => ChooseLoginMethod(),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

我已经尝试在重试逻辑上使用

Connectivity().checkConnectivity()
ConnectivityResult.none

android flutter visual-studio-code connection
1个回答
0
投票

要循环

AlertDialog
直到有互联网连接,您可以修改代码以在按下“重试”按钮时持续检查互联网连接。如果仍然没有互联网,该对话框将再次显示;否则,它将关闭并允许进一步的操作。

以下是实现此方法的方法:

  1. 创建一个方法来检查连接并在需要时显示对话框。
  2. 保持对话框打开,直到检测到成功的连接。

这是更新后的代码:

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Supabase.initialize(
    url: 'https://',
    anonKey: '0000',
  );

  final prefs = await SharedPreferences.getInstance();
  final bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;

  runApp(MyApp(prefs, isLoggedIn));
}

class MyApp extends StatelessWidget {
  final SharedPreferences prefs;
  final bool isLoggedIn;

  MyApp(this.prefs, this.isLoggedIn);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      home: isLoggedIn ? ScheduleWindow(prefs: prefs) : LOGIN_passenger(),
    );
  }
}

class LOGIN_passenger extends StatefulWidget {
  @override
  State<LOGIN_passenger> createState() => _LOGIN_passengerState();
}

class _LOGIN_passengerState extends State<LOGIN_passenger> {
  bool _isLoading = false;
  late TextEditingController emailController;
  late TextEditingController passController;

  @override
  void initState() {
    super.initState();
    emailController = TextEditingController();
    passController = TextEditingController();
    _checkInternetConnection();
  }

  @override
  void dispose() {
    emailController.dispose();
    passController.dispose();
    super.dispose();
  }

  Future<void> _checkInternetConnection() async {
    var connectivityResult = await Connectivity().checkConnectivity();

    if (connectivityResult == ConnectivityResult.none) {
      _showNoInternetDialog();
    }
  }

  void _showNoInternetDialog() {
    showDialog(
      context: context,
      barrierDismissible: false, // Prevent dismissing the dialog by tapping outside
      builder: (context) => AlertDialog(
        title: Text('No Internet Connection'),
        content: Text('Please check your internet connection and try again.'),
        actions: [
          ElevatedButton(
            child: Text('Retry'),
            onPressed: () async {
              Navigator.of(context).pop(); // Close the dialog
              _retryConnection();
            },
          ),
        ],
      ),
    );
  }

  Future<void> _retryConnection() async {
    var connectivityResult = await Connectivity().checkConnectivity();

    if (connectivityResult == ConnectivityResult.none) {
      // Still no internet, show the dialog again
      _showNoInternetDialog();
    } else {
      // Internet is available, proceed with login or further actions
      _login();
    }
  }

  void _login() {
    // Login logic here
    print("Proceed to login.");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _checkInternetConnection,
          child: Text('Check Connection and Login'),
        ),
      ),
    );
  }
}

说明:

  1. 初始检查:
    initState()
    中,应用程序使用
    Connectivity().checkConnectivity()
    检查互联网连接。
  2. 无互联网对话框: 如果没有互联网,则
    _showNoInternetDialog()
    方法会显示警报对话框。此对话框将保留在屏幕上,直到用户按“重试”。
  3. 重试逻辑:当按下“重试”时,应用程序会再次检查连接。如果仍然没有连接,它将再次显示该对话框。如果连接恢复,登录过程将继续。

此方法可确保警报对话框一直显示,直到检测到有效的互联网连接。

© www.soinside.com 2019 - 2024. All rights reserved.