Flutter ObjectBox watch - flutter

I'm using the objectbox with watch feature.
But if I use watch feature I cant close the store, Can I have any problem about this? with battery low or slow app? is there a better way to do it?
My code
Stream<List<Room>>> listenRoomUnreadMessage(){
try {
return objectBox.store
.box<RoomUnread>()
.query()
.watch(triggerImmediately: true)
.transform(
StreamTransformer.fromHandlers(
handleData: (query, sink) =>
sink.add(query.find().map((e) => e.toDomain()).toList()),
),
);
} catch (ex) {
rethrow;
}
}
and create store class
class ObjectBox {
late final Store store;
ObjectBox._create(this.store);
static Future<ObjectBox> create() async {
final store = await openStore();
return ObjectBox._create(store);
}
}
and I call create in main function
late ObjectBox objectBox;
void main() async {
objectBox = await ObjectBox.create();
runApp(const MaterialAppMain());
}
Thanks

Related

dart asyncronous code - should i choose static or non static parameter?

i was building an app with Flutter and Firebase and I encountered the following problem:
I have a firebase helper class with within all the methods I need to use firebase realtime database and I will call these from the main function.
this is the firebase helper class:
class FBHelper {
FBHelper._internal();
static final DatabaseReference database = FirebaseDatabase.instance.ref('/');
factory FBHelper() {
return FBHelper._internal();
}
Future<void> initializeFirebase() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
print('firebase app initialized');
}
Future<void> callPost(dynamic o) async {
await database.set(o);
}
}
and this is my main
void main() async {
final _ = FBHelper();
WidgetsFlutterBinding.ensureInitialized();
await _.initializeFirebase();
await _.callPost({"master": "1"});
runApp(const MyApp());
}
if I mark as static the DatabaseReference database property there are no problems at all.
instead, if I avoid the static modifier I get this
FirebaseException ([core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp())
can someone explain me what I’m missing? do I have a wrong idea of how to use static?

how to mock the state of a StateNotifierProvider flutter

my test is throwing an exception because there is a StateNotifierProvider inside which is not overridden. for a regular Provider, i can override it using providerContainer, but for the state of a stateNotifierProvider, I don't know how to do it. I tried my best but I reached the limit of my best. I already saw this and this but it didn't help.
Appreciate much if someone could help me out of this. Thanks
My service File
class ReportService {
final Ref ref;
ReportService({
required this.ref,
});
Future<void> testReport() async {
//* How can i override this provider ?
final connection = ref.read(connectivityServiceProvider);
if (connection) {
try {
await ref.read(reportRepositoryProvider).testFunction();
} on FirebaseException catch (e, st) {
ref.read(errorLoggerProvider).logError(e, st);
throw Exception(e.message);
}
} else {
throw Exception('Check internet connection...');
}
}
}
final reportServiceProvider = Provider<ReportService>((ref) => ReportService(
ref: ref,
));
My test file
void main() {
WidgetsFlutterBinding.ensureInitialized();
final reportRepository = MockReportRepository();
ReportService makeReportService() {
final container = ProviderContainer(overrides: [
reportRepositoryProvider.overrideWithValue(reportRepository),
]);
addTearDown(container.dispose);
return container.read(reportServiceProvider);
}
test('test test', () async {
//How to stub the connectivityServiceProvider here ?
when(reportRepository.testFunction)
.thenAnswer((invocation) => Future.value());
final service = makeReportService();
await service.testReport();
verify(reportRepository.testFunction).called(1);
});
My StateNotifierProvider
class ConnectivityService extends StateNotifier<bool> {
ConnectivityService() : super(false);
}
final connectivityServiceProvider =
StateNotifierProvider<ConnectivityService, bool>(
(ref) => ConnectivityService());

Use StreamSubscription as Future in Dart/Flutter

I want to connect my Flutter app to bluetooth device with flutter_blue library, and return a result (anything) when the connection is ON. But I don't understand how to do.
Here my code :
Future connect(BluetoothDevice device) async {
_btDevice = device;
StreamSubscription<BluetoothDeviceState> subscription;
subscription = device.state.listen((event) async {
if (event != BluetoothDeviceState.connected) {
await device.connect();
} else {
await device.discoverServices().then((value) => _initFeatures(value));
}
})
..onDone(() {
// Cascade
print("onDone");
});
subscription.asFuture();
//subscription.cancel();
}
And when I call this function with
await newDevice.connect(bluetoothDevice).then((value) => print('OK'));
OK is written before the real connection. _initFeatures if well call when the device is connected.
I try to use asFuture from StreamSubscription with onDone, but that change nothing.
Could you help me please ?
UPDATE 12/10
I've worked on another project for few monthes, and when I come back, I can't solve the problem, so I add the full code.
The concept is a class widget calls the connect future in other class and need to receipt the end of work.
Widget
Future<void> _connectDevice() async {
try {
widget.device.connect(widget.btDevice!).then((value) => _initValue());
} catch (e) {
print(e);
}
}
_initValue() is a method to create the rest of the screen
and the Future connect()
Future connect(BluetoothDevice device) async {
_btDevice = device;
StreamSubscription<BluetoothDeviceState> subscription;
subscription = device.state.listen((event) async {
if (event != BluetoothDeviceState.connected) {
await device.connect();
} else {
await device
.discoverServices()
.then((value) => _initFeatures(value))
.then((value) => print("OK"));
}
});
await subscription.asFuture();
await subscription.cancel();
}
What I'd like is the Future finishes when print("OK") is called, in order .then((value) => _initValue()); is called.
The problem is only this end. Maybe it's not the good way to implement this kind of solution.

Flutter Unhandled exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized

I am trying to create an Isolate un Flutter and then use this isolate to fetch some data from Firebase Realtime Database.
I am creating de Isolate in a file called home.dart (not main) and here is my code for that file. I have a class to create the Isolate and the function for the Isolate to execute. Inside this function I am trying to fetch the data.
void elIsolate(SendPort sPort) async {
print("Fetching data");
final databaseReference = FirebaseDatabase.instance.reference().child("categories");
DataSnapshot info;
/*databaseReference.once().then((DataSnapshot snapshot) {
info = snapshot;
print(info.value);
});*/
print("new isolate created");
IsolateChannel channel = IsolateChannel.connectSend(sPort);
channel.stream.listen((data) {
print('newIsolate received : $data');
});
channel.sink.add("hi");
}
class _MyHomePageState extends State<MyHomePage> {
List list = [];
void initState(){
WidgetsFlutterBinding.ensureInitialized();
super.initState();
print("Init state");
loadIsolate();
}
Future loadIsolate() async {
await Firebase.initializeApp();
print("Load isolate");
ReceivePort rPort = ReceivePort();
IsolateChannel channel = IsolateChannel.connectReceive(rPort);
channel.stream.listen((data) {
print('rootIsolate received : $data');
channel.sink.add('How are you');
});
await Isolate.spawn(elIsolate, rPort.sendPort);
/*await Isolate.spawn(getAllWorkers, receivePort.sendPort);
receivePort.listen((message) {
print(message);
});*/
}
}
Then I have my main.dart. I added this line inside the main function: WidgetsFlutterBinding.ensureInitialized();
Here is my code
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
bool resp;
await SharedPreferences.getInstance().then((prefs) {
resp = prefs.getBool('isUser');
if (resp == null) {
FirebaseAuth _auth = FirebaseAuth.instance;
resp = (_auth.currentUser != null);
prefs.setBool('isUser', resp);
}
});
runApp(MyApp(user: resp));
}
flutter_isolate: ^2.0.2
onPressed: () {
FlutterIsolate.spawn(_isolateEntrypoint, "");
}
// A "top level" function (i.e. not inside a class or make it static)
_isolateEntrypoint(String foo) {
WidgetsFlutterBinding.ensureInitialized();
...
}
Make sure that authorization and initialization were made on the same main thread (top level or static).
Now this FlutterEngine will be able to communicate with Firebase Realtime Database but the main FlutterEngine won't. In practice, depending on the app, an app may want to communicate with Realtime Database from either engine (or both). In background apps, more likely from here rather than the main isolate, but again that depends on the app.

Print and save data of list of installed apps in flutter

I am trying to get list of appName for all Apps installed and using package: https://pub.dev/packages/device_apps . How to run this in initstate so I can run it in background and save data in backend.
Below code prints all information while I am only looking for specific fields as list.
void initState() {
super.initState();
getinstalledAppList();
}
Future<void> getinstalledAppList() async{
List<Application> apps = await DeviceApps.getInstalledApplications();
print(apps);
}
chetan suri you can map your apps list to new one or use foreach statement. Here is example:
void initState() {
super.initState();
getinstalledAppList();
}
Future<void> getinstalledAppList() async{
List<Application> apps = await DeviceApps.getInstalledApplications();
print(apps);
// Using foreach statement
apps.forEach((app) {
print(app.appName);
// TODO Backend operation
});
}
Map apps list to new:
Class model:
class AppInfo {
String appName, packageName, versionName;
AppInfo({
this.appName,
this.packageName,
this.versionName,
});
static List<AppInfo> retrieveSomeFields(List<Application> data) {
return data
.map(
(app) => AppInfo(
appName: app.appName,
packageName: app.packageName,
versionName: app.versionName,
),
)
.toList();
}
}
Call:
Future<void> getinstalledAppList() async{
List<Application> apps = await DeviceApps.getInstalledApplications();
print(apps);
var data = AppInfo.retrieveSomeFields(apps);
// TODO Backend operation
}
You can write a work manager and callbackDispatcher for background processes. Here is a good explanation. It will look like this:
const myTask = "syncWithTheBackEnd";
void main() {
Workmanager.initialize(callbackDispatcher);
Workmanager.registerOneOffTask(
"1",
myTask, //This is the value that will be returned in the callbackDispatcher
// Set Your Delay!
initialDelay: Duration(minutes: 5),
constraints: WorkManagerConstraintConfig(
requiresCharging: true,
networkType: NetworkType.connected,
),
);
runApp(MyApp());
}
void callbackDispatcher() {
Workmanager.executeTask((task) {
switch (task) {
case myTask:
print("this method was called from native!");
// Call your own method for Android.
getinstalledAppList();
break;
case Workmanager.iOSBackgroundTask:
print("iOS background fetch delegate ran");
// Call your own method for iOS.
getinstalledAppList();
break;
}
//Return true when the task executed successfully or not
return Future.value(true);
});
}