No implementation found for method listen on channel for ConnectionStatus library - flutter

I'm trying to use FlutterCheckInternetConnectivity on our application, after run application i get this error:
plugins.flutter.io/connectivity_status:
MissingPluginException(No implementation found for method listen on channel
plugins.flutter.io/connectivity_status)
on this part of code:
void dispose() {
connectionChangeController.close();
}
ConnectionStatusSingleton class:
class ConnectionStatusSingleton {
static final ConnectionStatusSingleton _singleton = new ConnectionStatusSingleton._internal();
ConnectionStatusSingleton._internal();
static ConnectionStatusSingleton getInstance() => _singleton;
bool hasConnection = false;
StreamController connectionChangeController = new StreamController.broadcast();
final Connectivity _connectivity = Connectivity();
void initialize() {
_connectivity.onConnectivityChanged.listen(_connectionChange);
checkConnection();
}
Stream get connectionChange => connectionChangeController.stream;
void dispose() {
connectionChangeController.close();
}
void _connectionChange(ConnectivityResult result) {
checkConnection();
}
Future<bool> checkConnection() async {
bool previousConnection = hasConnection;
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
hasConnection = true;
} else {
hasConnection = false;
}
} on SocketException catch(_) {
hasConnection = false;
}
if (previousConnection != hasConnection) {
connectionChangeController.add(hasConnection);
}
return hasConnection;
}
}
my implemented this library:
main() {
ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
connectionStatus.initialize();
runApp(MaterialApp(
...
));
}
_FragmentPostsState widget class:
class _FragmentPostsState extends State<FragmentPosts> {
StreamSubscription _connectionChangeStream;
bool isOffline = false;
#override
void initState() {
super.initState();
ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
_connectionChangeStream = connectionStatus.connectionChange.listen(connectionChanged);
}
#override
Widget build(BuildContext context) {
return (isOffline)
? Center(...)
: PostPage();
}
void connectionChanged(dynamic hasConnection) {
setState(() {
print('connection changed ...');
isOffline = !hasConnection;
});
}
}

I had this same problem and eventually I restarted the app from command-line and this solved the problem.

Related

dart Isolate listen don't triggered (or work)

My class:
import 'dart:isolate';
import 'dart:ui';
import 'package:flutter_downloader/flutter_downloader.dart';
class SettingsPage extends StatefulWidget with WidgetsBindingObserver {
SettingsPage({Key? key}) : super(key: key);
#override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
final ReceivePort _port = ReceivePort();
int uploadProgress = 0;
// (-1)
DownloadTaskStatus uploadStatus = DownloadTaskStatus(-1);
String identifier = '';
get downloadsPath =>
storage.read('downloadsPath') ?? AndroidPathProvider.downloadsPath;
#override
void initState() {
super.initState();
_bindBackgroundIsolate();
FlutterDownloader.registerCallback(downloadCallback);
}
#override
void dispose() {
_unbindBackgroundIsolate();
super.dispose();
}
void _bindBackgroundIsolate() {
final isSuccess = IsolateNameServer.registerPortWithName(
_port.sendPort, 'downloader_send_port');
simplelog.i('regPort: $isSuccess');
if (!isSuccess) {
_unbindBackgroundIsolate();
_bindBackgroundIsolate();
return;
}
///Listening for the data is comming other isolataes
simplelog.i('before listen');
_port.listen((dynamic data) {
simplelog.i('in listen');
final String _id = data[0];
final DownloadTaskStatus _status = data[1];
final int _progress = data[2];
simplelog.i(
'Callback on UI isolate: '
'task ($_id) is in status ($_status) and process ($_progress)',
);
setState(() {
uploadProgress = _progress;
uploadStatus = _status;
simplelog.i('inside setState');
});
simplelog.i(
'uploadProgress = $uploadProgress \n uploadStatus = $uploadStatus \n uploadStatus.value = ${uploadStatus.value}');
if (uploadProgress == 100 &&
uploadStatus == DownloadTaskStatus.complete &&
uploadStatus.value == 3) {
try {
OpenFilex.open('$downloadsPath/${Consts.apkName}');
} catch (e) {
simplelog.e('Cannot open file ${Consts.apkName}! \n $e');
}
}
}, onError: (err) {
simplelog.e('ISOLATE LISTEN ERROR: $err');
},
onDone: () {
simplelog.i('onDone listen');
});
}
void _unbindBackgroundIsolate() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
}
#pragma('vm:entry-point')
static void downloadCallback(
String id,
DownloadTaskStatus status,
int progress,
) {
simplelog.i('Callback on background isolate: '
'task ($id) is in status ($status) and progress ($progress)');
IsolateNameServer.lookupPortByName('downloader_send_port')
?.send([id, status, progress]);
}
In case with dowloadCallback all work good,
but in case _port.listen(), I don't get any data (simplelog = print, it nothing to show me, work only case simplelog.i('before listen');
In init() method register callback, this prints works good, and file success downloaded
How I can solve this problem?
Tried to play around with opening and closing ports using Compiler

Unhandled Exception: Bad state: Tried to use PaginationNotifier after `dispose` was called

I have a StateNotifierProvider that calls an async function which loads some images from the internal storage and adds them to the AsyncValue data:
//Provider declaration
final paginationImagesProvider = StateNotifierProvider.autoDispose<PaginationNotifier, AsyncValue<List<Uint8List?>>>((ref) {
return PaginationNotifier(folderId: ref.watch(localStorageSelectedFolderProvider), itemsPerBatch: 100, ref: ref);
});
//Actual class with AsyncValue as State
class PaginationNotifier extends StateNotifier<AsyncValue<List<Uint8List?>>> {
final int itemsPerBatch;
final String folderId;
final Ref ref;
int _numberOfItemsInFolder = 0;
bool _alreadyFetching = false;
bool _hasMoreItems = true;
PaginationNotifier({required this.itemsPerBatch, required this.folderId, required this.ref}) : super(const AsyncValue.loading()) {
log("PaginationNotifier created with folderId: $folderId, itemsPerBatch: $itemsPerBatch");
init();
}
final List<Uint8List?> _items = [];
void init() {
if (_items.isEmpty) {
log("fetchingFirstBatch");
_fetchFirstBatch();
}
}
Future<List<Uint8List?>> _fetchNextItems() async {
List<AssetEntity> images = (await (await PhotoManager.getAssetPathList())
.firstWhere((element) => element.id == folderId)
.getAssetListRange(start: _items.length, end: _items.length + itemsPerBatch));
List<Uint8List?> newItems = [];
for (AssetEntity image in images) {
newItems.add(await image.thumbnailData);
}
return newItems;
}
void _updateData(List<Uint8List?> result) {
if (result.isEmpty) {
state = AsyncValue.data(_items);
} else {
state = AsyncValue.data(_items..addAll(result));
}
_hasMoreItems = _numberOfItemsInFolder > _items.length;
}
Future<void> _fetchFirstBatch() async {
try {
_numberOfItemsInFolder = await (await PhotoManager.getAssetPathList()).firstWhere((element) => element.id == folderId).assetCountAsync;
state = const AsyncValue.loading();
final List<Uint8List?> result = await _fetchNextItems();
_updateData(result);
} catch (e, stk) {
state = AsyncValue.error(e, stk);
}
}
Future<void> fetchNextBatch() async {
if (_alreadyFetching || !_hasMoreItems) return;
_alreadyFetching = true;
log("data updated");
state = AsyncValue.data(_items);
try {
final result = await _fetchNextItems();
_updateData(result);
} catch (e, stk) {
state = AsyncValue.error(e, stk);
log("error catched");
}
_alreadyFetching = false;
}
}
Then I use a scroll controller attached to a CustomScrollView in order to call fetchNextBatch() when the scroll position changes:
#override
void initState() {
if (!controller.hasListeners && !controller.hasClients) {
log("listener added");
controller.addListener(() {
double maxScroll = controller.position.maxScrollExtent;
double position = controller.position.pixels;
if ((position > maxScroll * 0.2 || position == 0) && ref.read(paginationImagesProvider.notifier).mounted) {
ref.read(paginationImagesProvider.notifier).fetchNextBatch();
}
});
}
super.initState();
}
The problem is that when the StateNotifierProvider is fetching more data in the async function fetchNextBatch() and I go back on the navigator (like navigator.pop()), Flutter gives me an error:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Tried to use PaginationNotifier after dispose was called.
Consider checking mounted.
I think that the async function responsible of loading data completes after I've popped the page from the Stack (which triggers a Provider dispose).
I'm probably missing something and I still haven't found a fix for this error, any help is appreciated.

Flutter how to check Internet connection is available or not

I am trying to use this plugin https://pub.dev/packages/connectivity/example Issue is its not showing or print internet is connected or not.
This is my code
class _HomePageState extends State<HomePage> {
String _connectionStatus = 'Unknown';
final Connectivity _connectivity = Connectivity();
StreamSubscription<ConnectivityResult> _connectivitySubscription;
#override
void initState() {
super.initState();
initConnectivity();
_connectivitySubscription =
_connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (mounted) {
if (userManager.getCurrentDriver() != null &&
userManager.getCurrentDriver().isNotEmpty) {
FirebaseFirestore.instance
.collection(FIREBASE_PATH_TRIP)
.doc(userManager.getCurrentDriver())
.get()
.then((event) {
if (event != null) {
var trip =
DriverModel.fromMap(Map<String, dynamic>.from(event.data()));
Provider.of<TripState>(context, listen: false).driver = trip;
Provider.of<BottomSheetSelector>(context, listen: false)
.changeSheet(SheetType.Profile);
} else {
userManager.saveCurrentDriver('');
}
});
}
if (Theme.of(context).platform == TargetPlatform.android) {
checkForAndroidUpdate(context);
}
}
});
}
#override
void dispose() {
_connectivitySubscription.cancel();
super.dispose();
}
Future<void> initConnectivity() async {
ConnectivityResult result;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await _connectivity.checkConnectivity();
} on PlatformException catch (e) {
print(e.toString());
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) {
return Future.value(null);
}
return _updateConnectionStatus(result);
}
#override
Widget build(BuildContext context) {
final _drawerKey = GlobalKey<ScaffoldState>();
ScreenUtil.init(context);
return SafeArea(
child: WillPopScope(
child: Scaffold(
key: _drawerKey,
backgroundColor: Colors.black,
resizeToAvoidBottomInset: false,
drawer: ViteDrawer(),
body: null,
),
));
}
Future<void> _updateConnectionStatus(ConnectivityResult result) async {
switch (result) {
case ConnectivityResult.wifi:
case ConnectivityResult.mobile:
case ConnectivityResult.none:
setState(() => _connectionStatus = result.toString());
break;
default:
setState(() => _connectionStatus = 'Failed to get connectivity.');
break;
}
}
}
What i need to do is simple print if internet is connected or not. I want to show alert but print is ok so ill manage it. But dont know why its not printing anything
You can try with this
Future<bool> check() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
print("Connected}");
return true;
} else if (connectivityResult == ConnectivityResult.wifi) {
print("Connected}");
return true;
}
print("not Connected}");
// return You can add your dialog for notify user to your connectivity is off
}
you can use below code to check the connectivity
Future<bool> checkInternetConnectivity() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
} else {
return false;
}
} on SocketException catch (_) {
return false;
}
}
simple
Future<bool> isConnected() async {
var result = await Connectivity().checkConnectivity();
return result != ConnectivityResult.none;
}

Correct way to call an api by provider in fflutter?

I have been trying to make a app in flutter where an api is called and data is updated in TextField
Used provider for state management, here is the code for it.
class ProfileProvider with ChangeNotifier {
var profileData;
String _url = "http://10.0.2.2:3000/api/v1/user/loggedin_user";
void getData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
var data = await http.get(
_url,
headers: {
"accept": "application/json",
"content-type": "application/json",
'Token': token,
},
);
var infoOfPerson = json.decode(data.body);
profileData = new ProfileObject(
name: infoOfPerson['name'],
mobile: infoOfPerson['mobile'],
email: infoOfPerson['email'],
role: infoOfPerson['role'],
);
notifyListeners();
}
ProfileObject get profileInfo {
return profileData;
}
}
I am getting the data fine, now i have to show it in the UI, but sometime data is populated, sometime its not. Can someone please point me the right direction why this is happening.
Here is the code for UI.
class Profile extends StatefulWidget {
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
final emailController = TextEditingController(text: '');
final nameController = TextEditingController(text: '');
final mobileController = TextEditingController(text: '');
var _isInit = true;
#override
void didChangeDependencies() {
if (_isInit) {
final profileData = Provider.of<ProfileProvider>(context);
profileData.getData();
if (profileData.profileInfo != null) {
emailController.text = profileData.profileInfo.name;
nameController.text = profileData.profileInfo.email;
mobileController.text = profileData.profileInfo.mobile;
}
_isInit = false;
super.didChangeDependencies();
}
}
#override
Widget build(BuildContext context) {
final profileData = Provider.of<ProfileProvider>(context);
return Scaffold(
drawer: NavigationDrawer(),
body: profileData.profileInfo == null
? Center(
child: CircularProgressIndicator(),
)
: Builder(
builder: (context) => SingleChildScrollView(
child: Padding(.....
Below the padding, there is normal TextField, can someone tell me why the data is being populated sometime and sometime its coming empty, even I wrapped it with CircularProgressIndicator() and a check the notifyListeners(); is not working there. The loader is not being shown and data is not being loaded.
Thanks
for StatelessWidget.
Inside the build method use:
Future.microtask(() async {
context.read<SomeProvider>().fetchSomething();
});
For StatefulWidgets if you want to call it once. Do this inside the initState() or didChangeDependencies (better if the latter). This will be called at the end of the frame which means after the build or rendering finishes..
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<SomeProvider>().fetchSomething();
});
}
EDIT: WidgetsBinding will also work on build. I forgot on why I used microtask lol
i've created a function which called nextTick, i call it in initState and it works for now, but want to see others method
void nextTick(Function callback, [int milliseconds = 0]) {
Future.delayed(Duration(milliseconds: 0)).then((_) {
callback();
});
}
then use it like below
#override
void initState() {
super.initState();
nextTick((){
ProfileProvider profileProvider = Provider.of<ProfileProvider>(context);
profileProvider.getProfile();
});
}
Edit: i store couple of variables to manage them on ui, like isLoading, hasError and errorMessage. Here is my provider class
class ProfileProvider extends ChangeNotifier {
bool _hasError = false;
bool _isLoading = true;
String _errorMsg = '';
Profile _profileResponse;
bool get hasError => _hasError;
bool get isLoading => _isLoading;
String get errorMsg => _errorMsg;
Profile get profileResponse => _profileResponse;
Future<void> getProfile() async {
this.setLoading = true;
this.setError = false;
this.setErrorMsg = '';
try {
await dio.post('$api/p/view', data: {}).then((res) {
print(res.data);
_profileResponse = Profile.fromJson(jsonDecode(res.data));
print(_profileResponse.data);
notifyListeners();
}).whenComplete(() {
this.setLoading = false;
});
} catch (e) {
this.setError = true;
this.setErrorMsg = '$e';
}
this.setLoading = false;
}
set setError(bool val) {
if (val != _hasError) {
_hasError = val;
notifyListeners();
}
}
set setErrorMsg(String val) {
if (val != null && val != '') {
_errorMsg = val;
notifyListeners();
}
}
set setLoading(bool val) {
_isLoading = val;
notifyListeners();
}
}

Flutter : I have NULL in my variable , How to use my function?

class _ProfilePageState extends State<ProfilePage> {
String tmpimage;
Uint8List TmpBytesImage;
File pimage;
void initState() {
super.initState();
Future.delayed(Duration.zero, () {
TmpBytesImage= profileimage();
});
}
profileimage() async {
var userimage1 = await DBHelper().getuserIMAGE1('roro');
print(userimage1);
if (userimage1 == Null) {
print('Empty');
} else {
setState(() {
userimage1.map((e) {
tmpimage = e['image0'];
}).toList();
print(tmpimage);
return Base64Decoder().convert(tmpimage);
});
}
}
The first error was:
Only static members can be accessed in initializers
I added :
void initState() {
super.initState();
Future.delayed(Duration.zero, () {
TmpBytesImage= profileimage();
});
}
Then it seemed to be working normally.
But there is a null value in the TmpBytesImage. How to fix it?
That's because you were not awaiting on your future method. Just replace your initState with this:
void initState() {
super.initState();
Future.delayed(Duration.zero, () async{
TmpBytesImage = await profileimage();
});
}