dart 仅当单击“重试”按钮时,重新检查抖动中的Internet连接

p4tfgftt  于 2023-04-27  发布在  其他
关注(0)|答案(2)|浏览(106)

要求:

  • 显示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();
  }
}

我要找什么?

  • 费克斯会非常感激的。
  • 我也对不同的架构和更好的方法持开放态度。
iqjalb3h

iqjalb3h1#

我对你的逻辑做了一些修改。
1.如果网络更改侦听器订阅,则应仅在网络断开时发出状态。
1.不需要使用BlocListener,可以直接将AlertDialog作为Scaffold的主体。
下面是我想出来的代码

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();
  }
}
uqxowvwt

uqxowvwt2#

isDialogDisplayed,状态没有监听这个变量的值。所以当你更新它的值时什么也没有发生&你没有使用setState olso..有几种方法可以解决这个问题。
1.第一个

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

  await Firebase.initializeApp();

  final isDialogDisplayed = ValueNotifier<bool>(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.value = true;
          }
          if (state == ConnectivityState.connected &&
              isDialogDisplayed.value == true) {
            isDialogDisplayed.value = false;
          }
        }, builder: (context, state) {
          if (state == ConnectivityState.init) {
            return const Scaffold(body: ShimmerHome()); 
          }
          return  ValueListenableBuilder(
                valueListenable:  isDialogDisplayed,
                builder: (context, _isDialogDis, _) {
                  return  _isDialogDis
              ? Scaffold(
                  body: NoDataHelper(
                        ...
                        onTap: () {
                        if (state == ConnectivityState.connected) {
                          isDialogDisplayed.value = false;          // will work now
                        }
                      }),
                )
              : state == ConnectivityState.connected
                  ? MaterialApp.router(
                     ...
                    )
                  : const Scaffold(body: Center(child: ShimmerHome()));
        }));
                },
              ),
  ));
}

1.声明此(var isDialogDisplayed = false;)到您的ConnectivityCubit中,然后访问它
1.将您的BlocConsumer移动到StateFull小部件中,然后使用setState({})更新“isDialogDisplayed”;

相关问题