Pass Widgets in Connectivity check in flutter - flutter

I want to implement internet connectivity check into my app and I used official connectivity plugin and it is working great for displaying String Value but instead of showing string value in screen I want to display different widgets for connected and disconnected.
Here What I am Using
//
Widget result;
//
body: Container(
alignment: Alignment.center,
child: result != null ?
result : Text("unknown", style :
TextStyle(fontSize: 30,fontWeight: FontWeight.bold),
),
void checkStatus(){
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if(
result == ConnectivityResult.mobile ||
result == ConnectivityResult.wifi){
Text("Connected", style:TextStyle(color:Colors.red));
} else {
Text("No InterNet", style:TextStyle(color:Colors.red));
}
});
}
#override
void initState() {
super.initState();
checkStatus();
}
And I am Getting 'unknown' value

try this
class Sample extends StatefulWidget {
#override
_SampleState createState() => _SampleState();
}
class _SampleState extends State<Sample> {
Widget result;
#override
void initState() {
super.initState();
checkStatus();
}
void checkStatus() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
result = Text("Connected to Mobile Network");
setState(() {});
} else if (connectivityResult == ConnectivityResult.wifi) {
result = Text("Connected to WiFi");
print("Connected to WiFi");
setState(() {});
} else {
result = Text("Unable to connect. Please Check Internet Connection");
setState(() {});
print("Unable to connect. Please Check Internet Connection");
}
}
#override
Widget build(BuildContext context) {
return Center(child: result);
}
}

Try this:
Use this package for checking Internet:
data_connection_checker:
And, Inside your stateful class create stream listener i.e and a boolean value.
StreamSubscription<DataConnectionStatus> listener; bool isConnected = true;
and Inside initState:
#override
void initState() {
super.initState();
listener = DataConnectionChecker().onStatusChange.listen((status) {
switch (status) {
case DataConnectionStatus.connected:
print('Data connection is available. $status');
setState(() {
isConnected = true;
});
break;
case DataConnectionStatus.disconnected:
print('You are disconnected from the internet. $status');
setState(() {
isConnected = false;
});
break;
}
});
}
Done, This will keep listening to changes in your internet status, Thus you can prompt user as you like. Cheers, Feel free to ask if confusion and if it helps upvote :D

Related

how to await for network connectivity status in flutter

I have used connectivity_plus and internet_connection_checker packages to check the internet connectivity.
The problem occured is , the app works perfectly fine as expected when the app start's with internet on state. But when the app is opened with internet off, the dialog isn't shown !!
I assume this is happening because the build method is called before the stream of internet is listened.
Code :
class _HomePageState extends State<HomePage> {
late StreamSubscription subscription;
bool isDeviceConnected = false;
bool isAlertSet = false;
#override
void initState() {
getConnectivity();
super.initState();
}
getConnectivity() {
subscription = Connectivity().onConnectivityChanged.listen(
(ConnectivityResult result) async {
isDeviceConnected = await InternetConnectionChecker().hasConnection;
if (!isDeviceConnected && isAlertSet == false) {
showDialogBox();
setState(() {
isAlertSet = true;
});
}
},
);
}
#override
void dispose() {
subscription.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
...
);
}
showDialogBox() => showDialog(/* no internet dialog */)
Extending the question: Is it assured that this works for all the pages ?
if yes, how ?
if not , how to overcome this?
First of all you need to listen for internet connectivity in your app first screen which is probably app.dart
GlobalKey<NavigatorState> navigatorKey = GlobalKey();
final noInternet = NoInternetDialog();
class TestApp extends StatefulWidget {
#override
State<TestApp> createState() => _TestAppState();
}
class _TestAppState extends State<TestApp> {
#override
void initState() {
super.initState();
checkInternetConnectivity();
}
#override
Widget build(BuildContext context) {
return MaterialApp(...);
}
Future<void> checkInternetConnectivity() async {
Connectivity().onConnectivityChanged.getInternetStatus().listen((event)
{
if (event == InternetConnectionStatus.disconnected) {
if (!noInternet.isShowing) {
noInternet.showNoInternet();
}
}
});
}
}
Make the screen stateful in which you are calling MaterialApp and in initState of that class check for your internet connection, like above
You are saying how can I show dialog when internet connection changes for that you have to create a Generic class or extension which you can on connectivity change. You have to pass context to that dialogue using NavigatorKey
class NoInternetDialog {
bool _isShowing = false;
NoInternetDialog();
void dismiss() {
navigatorKey.currentState?.pop();
}
bool get isShowing => _isShowing;
set setIsShowing(bool value) {
_isShowing = value;
}
Future showNoInternet() {
return showDialog(
context: navigatorKey.currentState!.overlay!.context,
barrierDismissible: true,
barrierColor: Colors.white.withOpacity(0),
builder: (ctx) {
setIsShowing = true;
return AlertDialog(
elevation: 0,
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(3.0.h),
content: Container(...),
);
},
);
}
}
Use checkConnectivity to check current status. Only changes are exposed to the stream.
final connectivityResult = await Connectivity().checkConnectivity();

setState is not calling when Navigating to another page

I am checking the connectivity using Connectivity().checkConnectivity() it is working but the setState() is not calling when I navigate to this page.
To navigate to main page to another page I am using Navigator.push(context, MaterialPageRoute(builder: (context) => search()));
and here is my next page
class search extends StatefulWidget {
#override
_searchState createState() => _searchState();
}
class _searchState extends State<search> {
List<filter> _list = [];
List<filter> to_display = [];
bool isoffline;
Future<void> connectivity() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
// I am connected to a mobile network.
setState(() {
isoffline = true;
});
print("connected");
} else if (connectivityResult == ConnectivityResult.wifi) {
setState(() {
isoffline = true;
});
// I am connected to a wifi network.
print("connected");
} else {
setState(() {
isoffline = false;
});
print(
"dissconneteddsfffffffffffffffffffffffffffffffffffffffffffffffffffffffdsfsd");
}
}
Future _future;
#override
void initState() {
mylist().then((value) {
setState(() {
_list = to_display = value;
});
});
connectivity();
print("value${isoffline}"); // this value is on null
_future = data();
super.initState();
}
print("value${isoffline}"); // this value is on null
The function connectivity is an asynchronous function. You are calling the function and immediately checking the boolean value, that's why you are getting null. You have to wait till the execution, either by using await or then syntax.
connectivity().then((value) {
print("value ${isoffline}");
});
In your code connectivity(); method is async which mean it will require some time to complete.
Now when init method is called it executes connectivity(); and then immediately executes print("value${isoffline}"); now the value for isoffline initially is null, hence null printed
solution is either you put print("value${isoffline}"); in connectivity(); method or try to add it after build method.
#override
Widget build(BuildContext context) {
connectivity();
print("value${isoffline}");
return YourWidget();
}

How to Navigate one of the two screens to users correctly in Flutter?

Recently I am developing first ever app in Flutter and I know the basics only.
So here's the problem which I am facing currently.
I have to Navigate One of the two screens, either Register or Home page according to old/new user, So what I did is here.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Register.dart';
import 'HomePage.dart';
class Authenticate extends StatefulWidget {
#override
_AuthenticateState createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
String _userName = "";
#override
void initState() {
super.initState();
_getUserName();
}
_getUserName() async {
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
_userName = pref.getString('userName') ?? "";
});
}
Widget build(BuildContext context) {
if (_userName == "") {
print('name : $_userName , NEW user'); // ERROR - why it's printing on console for old User ?
return Register();
} else {
return HomePage(_userName);
}
}
}
So the problem is, even if I am opening app through old user, it is printing the debug code written for new user and there's around 0.3 sec screen visibility of Register screen.
So what should I do to fix this?
The print is happening because this line of code:
SharedPreferences pref = await SharedPreferences.getInstance();
is asynchronous, which means that it might invoke in some later point in time. Because of that the build method is called first, then your _getUserName method finished, which causes a setState and invokes a build method again.
You might want to show some kind of loader screen until sharedPrefernces is initialized and then decide wheter to show Register or Home page.
Example code:
class _AuthenticateState extends State<Authenticate> {
String _userName = "";
bool _isLoading = true;
#override
void initState() {
super.initState();
_getUserName();
}
_getUserName() async {
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
_userName = pref.getString('userName') ?? "";
_isLoading = false;
});
}
Widget build(BuildContext context) {
if (_isLoading) {
return Center(child: CupertinoActivityIndicator());
} else if (_userName == "") {
print('name : $_userName , NEW user'); // ERROR - why it's printing on console for old User ?
return Register();
} else {
return HomePage(_userName);
}
}
}
Try this:
class _AuthenticateState extends State<Authenticate> {
String _userName;
#override
void initState() {
super.initState();
_getUserName();
}
_getUserName() async {
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
_userName = pref.getString('userName') ?? '';
});
}
Widget build(BuildContext context) {
if (_userName == null) {
return Center(child: CircularProgressIndicator());
} else if (_userName == '') {
print('name : $_userName , NEW user');
return Register();
} else {
return HomePage(_userName);
}
}
}
In this case, _userName is null initially and will only be assigned a value after the _getUserName() returns either an empty String or an old userName. When null, the widget will build a progress indicator instead. If you don't want that, just return a Container().

How to show message to the snackBar when user does not have internet in flutter app?

if internet connection is off i want to show "No internet connection" message in SnackBar.
if internet connection is on it will show UI.
This is my code:
import 'dart:io';
import 'package:flutter/material.dart';
import 'main.dart';
class InternetCheck extends StatefulWidget {
#override
_InternetState createState() => _InternetState();
}
class _InternetState extends State<InternetCheck> {
bool _isInternet = true;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
checkInternet() async {
try {
final response = await InternetAddress.lookup('example.com'); // google
if (response.isNotEmpty && response[0].rawAddress.isNotEmpty) {
_isInternet = true; // internet
setState(() {});
}
} on SocketException catch (_) {
_isInternet = false; // no internet
setState(() {
_showSnackBar();
});
}
return _isInternet;
}
#override
void initState() {
checkInternet();
super.initState();
}
void _showSnackBar() {
SnackBar snackBar = SnackBar(content: Text('No Connection'));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
// checkInternet();
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
body: _isInternet == true ? Text('internet') : Text('no Internet'),
),
);
}
}
using my code when app run first time with internet off it show SnackBar but when i switch internet on and again switch internet off then it will not showing snakbar.
Check out the connectivity package. It allows you to listen for network state changes :
#override
initState() {
super.initState();
subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if(connectivityResult == ConnectivityResult.none)
_showSnackbar();
})
}
// Be sure to cancel subscription after you are done
#override
dispose() {
super.dispose();
subscription.cancel();
}

check internet connection in flutter

I am trying to use the following code to check an internet connection in flutter, we want to make our application usable offline but this code just seems to loop. Is there a better way to do this? Im calling this on a button press before calling an http api.
package is = connectivity: ^0.4.6+1
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile || connectivityResult == ConnectivityResult.wifi) {
//Connection Exists
} else {
//No connection
}
You should listen to network connection event instead of calling it directly.
Take a try with this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:connectivity/connectivity.dart';
class CheckNetworkPage extends StatefulWidget {
#override
_CheckNetworkPageState createState() => _CheckNetworkPageState();
}
class _CheckNetworkPageState extends State<CheckNetworkPage> {
StreamSubscription<ConnectivityResult> _networkSubscription;
#override
initState() {
super.initState();
_networkSubscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if (result == ConnectivityResult.mobile) {
// I am connected to a mobile network.
} else if (result == ConnectivityResult.wifi) {
// I am connected to a wifi network.
} else if (result == ConnectivityResult.none) {
// I am not connected any network.
}
});
}
#override
Widget build(BuildContext context) {
return Container();
}
// Be sure to cancel subscription after you are done
#override
dispose() {
super.dispose();
_networkSubscription.cancel();
}
}