仅在单击重试按钮时才重新检查 flutter 中的互联网连接

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

要求:

  • 显示
    dialog
    如果互联网是
    unavailable
    整个应用程序
  • 仅当
    dialog
    被点击并且互联网为
    retry
    时才弹出
    available

需要建议:

  • 仅当
    dialog
    被点击并且互联网为
    retry
    时才弹出
    available

方法:

  • 我正在收听流,如果连接可用,则显示
    rest of app
    否则
    dialog
    。但是当
    retry
    被点击时什么也没做。

为什么?

  • isDialogDisplayed
    变量变化没有被听到,我不能在那里有
    setState

main

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  var isDialogDisplayed = false;
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    theme: CustomTheme.customTheme(),
    home: MultiBlocProvider(
        providers: Providers.getProviders,
        child: BlocConsumer<ConnectivityCubit, ConnectivityState>(
            listener: (context, state) {
          });
          if (state == ConnectivityState.disconnected) {
            isDialogDisplayed = true;
          }
          if (state == ConnectivityState.connected &&
              isDialogDisplayed == true) {
            isDialogDisplayed = false;
          }
        }, builder: (context, state) {
          if (state == ConnectivityState.init) {
            return const Scaffold(body: ShimmerHome()); 
          }
          return isDialogDisplayed
              ? Scaffold(
                  body: NoDataHelper(
                        ...
                        onTap: () {
                        if (state == ConnectivityState.connected) {
                          // isDialogDisplayed = false;          // Doesn't work
                        }
                      }),
                )
              : state == ConnectivityState.connected
                  ? MaterialApp.router(
                     ...
                    )
                  : const Scaffold(body: Center(child: ShimmerHome()));
        })),
  ));
}

Cubit

class ConnectivityCubit extends Cubit<ConnectivityState> {
  final Connectivity _connectivity = Connectivity();
  StreamSubscription<ConnectivityResult>? _subscription;
  late Stream<ConnectivityResult> streamValue;

  ConnectivityCubit() : super(ConnectivityState.init) {
    streamValue = _connectivity.onConnectivityChanged;
    _subscription = _connectivity.onConnectivityChanged.listen((result) {
      checkConnectivity(result);
    });
  }

  checkConnectivity(ConnectivityResult result) async {
    if (result == ConnectivityResult.none) {
      emit(ConnectivityState.disconnected);
    } else {
      bool isInternetAvailable = await checkInternetConnectivity();
      if (isInternetAvailable) {
        emit(ConnectivityState.connected);
      } else {
        emit(ConnectivityState.disconnected);
      }
    }
  }

  Future<bool> checkInternetConnectivity() async {
    try {
      final response = await http
          .get(Uri.parse("https://www.google.com"))
          .timeout(Duration(seconds: 10)); // Set a 10-second timeout
      if (response.statusCode == 200) {
        return true;
      } else {
        return false;
      }
    } catch (e) {
      return false;
    }
  }

  @override
  Future<void> close() {
    _subscription?.cancel();
    return super.close();
  }
}

我在找什么?

  • 修复将不胜感激。
  • 我也对不同的架构和更好的方法持开放态度。
flutter dart stream flutter-bloc internet-connection
1个回答
0
投票

我对你的逻辑做了一些修改。

  1. 在网络更改侦听器订阅的情况下,您应该只在网络断开时发出状态。
  2. 无需使用BlocListener,直接将AlertDialog做成Scaffold的body即可

这是我想出的代码

import 'dart:async';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:http/http.dart' as http;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    MultiBlocProvider(
      providers: [BlocProvider(create: (_) => ConnectivityCubit())],
      child: BlocBuilder<ConnectivityCubit, ConnectivityState>(
        builder: (context, state) {
          if (state == ConnectivityState.init) {
            return const MaterialApp(home: Scaffold(body: SizedBox.shrink()));
          } else if (state == ConnectivityState.disconnected) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(
                  title: const Text('Connectivity Check'),
                ),
                body: AlertDialog(
                  actions: [
                    ElevatedButton(
                      onPressed: () {
                        context.read<ConnectivityCubit>().checkConnectivity();
                      },
                      child: const Text('Retry'),
                    ),
                  ],
                  title: const Text('Internet not available'),
                ),
              ),
            );
          } else if (state == ConnectivityState.connected) {
            // repalce this with MaterialApp.router
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(
                  title: const Text('Connectivity Check'),
                ),
                body: const Center(child: Text('Connected')),
              ),
            );
          } else {
            assert(false, "state not mapped");
            return const SizedBox.shrink();
          }
        },
      ),
    ),
  );
}

enum ConnectivityState {
  init,
  disconnected,
  connected,
}

class ConnectivityCubit extends Cubit<ConnectivityState> {
  final Connectivity _connectivity = Connectivity();
  StreamSubscription<ConnectivityResult>? _subscription;
  ConnectivityCubit() : super(ConnectivityState.init) {
    checkConnectivity();
    _subscription = _connectivity.onConnectivityChanged.listen((result) {
      if (result == ConnectivityResult.none) {
        emit(ConnectivityState.disconnected);
      }
    });
  }

  checkConnectivity() async {
    final result = await _connectivity.checkConnectivity();
    if (result == ConnectivityResult.none) {
      emit(ConnectivityState.disconnected);
    } else {
      bool isInternetAvailable = await checkInternetConnectivity();
      if (isInternetAvailable) {
        emit(ConnectivityState.connected);
      } else {
        emit(ConnectivityState.disconnected);
      }
    }
  }

  Future<bool> checkInternetConnectivity() async {
    try {
      final response = await http
          .get(Uri.parse("https://www.google.com"))
          .timeout(const Duration(seconds: 10)); // Set a 10-second timeout
      return response.statusCode == 200;
    } catch (e) {
      return false;
    }
  }

  @override
  Future<void> close() {
    _subscription?.cancel();
    return super.close();
  }
}

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