Creating a share class Flutter - flutter

I am not sure if this is possible, but with SwiftUI I have a mediaplayer class which has all my media player controls in it.
I am wondering if it is possible to have a flutter class file that hold flutter_radio_player and 1 media player that can change audio source?
The issue I have ran into with our old android app is we can't change the track without it creating a whole new media player.
I can't find any sample code on how to do this.
My code currently:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_radio_player/flutter_radio_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
var playerState = FlutterRadioPlayer.flutter_radio_paused;
var volume = 0.8;
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _currentIndex = 0;
final List<Widget> _children = [
new MyApp(),
];
FlutterRadioPlayer _flutterRadioPlayer = new FlutterRadioPlayer();
#override
void initState() {
super.initState();
initRadioService();
}
Future<void> initRadioService() async {
try {
await _flutterRadioPlayer.init(
"DRN1", "Live", "http://stream.radiomedia.com.au:8003/stream", "false");
} on PlatformException {
print("Exception occurred while trying to register the services.");
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Radio Player Example'),
),
body: Center(
child: Column(
children: <Widget>[
StreamBuilder(
stream: _flutterRadioPlayer.isPlayingStream,
initialData: widget.playerState,
builder:
(BuildContext context, AsyncSnapshot<String> snapshot) {
String returnData = snapshot.data;
print("object data: " + returnData);
switch (returnData) {
case FlutterRadioPlayer.flutter_radio_stopped:
return RaisedButton(
child: Text("Start listening now"),
onPressed: () async {
await initRadioService();
});
break;
case FlutterRadioPlayer.flutter_radio_loading:
return Text("Loading stream...");
case FlutterRadioPlayer.flutter_radio_error:
return RaisedButton(
child: Text("Retry ?"),
onPressed: () async {
await initRadioService();
});
break;
default:
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
onPressed: () async {
print("button press data: " +
snapshot.data.toString());
await _flutterRadioPlayer.playOrPause();
},
icon: snapshot.data ==
FlutterRadioPlayer
.flutter_radio_playing
? Icon(Icons.pause)
: Icon(Icons.play_arrow)),
IconButton(
onPressed: () async {
await _flutterRadioPlayer.stop();
},
icon: Icon(Icons.stop))
]);
break;
}
}),
Slider(
value: widget.volume,
min: 0,
max: 1.0,
onChanged: (value) => setState(() {
widget.volume = value;
_flutterRadioPlayer.setVolume(widget.volume);
})),
Text("Volume: " + (widget.volume * 100).toStringAsFixed(0))
],
),
),
),
);
}
}

FlutterRadioPlayer Author here. With the new release of the player, you can do this.
You just have to call
_flutterRadioPlayer.setUrl('URL_HERE')
The player will automatically set the old stream to a halt and start the new stream. Yes, you can set it to autoplay when ready as well. Just refer to the docs in new release.

Related

play audio through earpiece in flutter ( getting only through speaker )

Play audio through earpiece in flutter , is it possible now, is there any plugin available for this use Case
import 'dart:math';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart' as ja;
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _player = ja.AudioPlayer(
// Handle audio_session events ourselves for the purpose of this demo.
handleInterruptions: false,
androidApplyAudioAttributes: false,
handleAudioSessionActivation: false,
);
#override
void initState() {
super.initState();
AudioSession.instance.then((audioSession) async {
// This line configures the app's audio session, indicating to the OS the
// type of audio we intend to play. Using the "speech" recipe rather than
// "music" since we are playing a podcast.
await audioSession.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playback,
avAudioSessionCategoryOptions:
AVAudioSessionCategoryOptions.allowBluetooth,
avAudioSessionMode: AVAudioSessionMode.defaultMode,
avAudioSessionRouteSharingPolicy:
AVAudioSessionRouteSharingPolicy.independent,
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.unknown,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.media,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: false,
));
// Listen to audio interruptions and pause or duck as appropriate.
_handleInterruptions(audioSession);
// Use another plugin to load audio to play.
await _player.setUrl(
"https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3");
});
}
void _handleInterruptions(AudioSession audioSession) {
// just_audio can handle interruptions for us, but we have disabled that in
// order to demonstrate manual configuration.
bool playInterrupted = false;
audioSession.becomingNoisyEventStream.listen((_) {
print('PAUSE');
_player.pause();
});
_player.playingStream.listen((playing) {
playInterrupted = false;
if (playing) {
audioSession.setActive(true);
}
});
audioSession.interruptionEventStream.listen((event) {
print('interruption begin: ${event.begin}');
print('interruption type: ${event.type}');
if (event.begin) {
switch (event.type) {
case AudioInterruptionType.duck:
if (audioSession.androidAudioAttributes!.usage ==
AndroidAudioUsage.game) {
_player.setVolume(_player.volume / 2);
}
playInterrupted = false;
break;
case AudioInterruptionType.pause:
case AudioInterruptionType.unknown:
if (_player.playing) {
_player.pause();
playInterrupted = true;
}
break;
}
} else {
switch (event.type) {
case AudioInterruptionType.duck:
_player.setVolume(min(1.0, _player.volume * 2));
playInterrupted = false;
break;
case AudioInterruptionType.pause:
if (playInterrupted) _player.play();
playInterrupted = false;
break;
case AudioInterruptionType.unknown:
playInterrupted = false;
break;
}
}
});
audioSession.devicesChangedEventStream.listen((event) {
print('Devices added: ${event.devicesAdded}');
print('Devices removed: ${event.devicesRemoved}');
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('audio_session example'),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Center(
child: StreamBuilder<ja.PlayerState>(
stream: _player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
if (playerState?.processingState !=
ja.ProcessingState.ready) {
return Container(
margin: EdgeInsets.all(8.0),
width: 64.0,
height: 64.0,
child: CircularProgressIndicator(),
);
} else if (playerState?.playing == true) {
return IconButton(
icon: Icon(Icons.pause),
iconSize: 64.0,
onPressed: _player.pause,
);
} else {
return IconButton(
icon: Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: _player.play,
);
}
},
),
),
),
Expanded(
child: FutureBuilder<AudioSession>(
future: AudioSession.instance,
builder: (context, snapshot) {
final session = snapshot.data;
if (session == null) return SizedBox();
return StreamBuilder<Set<AudioDevice>>(
stream: session.devicesStream,
builder: (context, snapshot) {
final devices = snapshot.data ?? {};
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Input devices",
style: Theme.of(context).textTheme.headline6),
for (var device
in devices.where((device) => device.isInput))
Text(
'${device.name} (${describeEnum(device.type)})'),
SizedBox(height: 16),
Text("Output devices",
style: Theme.of(context).textTheme.headline6),
for (var device
in devices.where((device) => device.isOutput))
Text(
'${device.name} (${describeEnum(device.type)})'),
],
);
},
);
},
),
),
],
),
),
),
);
}
}
if you implement the above functionality already , Please mention a solution
used plugins
just_audio: ^0.9.24
audio_session: ^0.1.7
Flutter 3.0.1 • channel stable Tools • Dart 2.17.1 • DevTools 2.12.2

The search bar does not return any results

I am trying to add a search function in my flutter app, the search bar is showing and there's not errors but its not working and it doesn't return any results.
the data list is from an API that I already called using the rest API
// ignore_for_file: use_key_in_widget_constructors, avoid_print, avoid_unnecessary_containers, curly_braces_in_flow_control_structures, prefer_const_constructors, non_constant_identifier_names, unnecessary_new, avoid_function_literals_in_foreach_calls, unused_import, avoid_types_as_parameter_names, unused_label
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:myapp2/Service_Request/SR.dart';
import 'package:myapp2/main.dart';
import 'package:myapp2/Service_Request/second.dart';
import '../Classes/demandes.dart';
import 'SR_details.dart';
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DataFromAPI(),
);
}
}
class DataFromAPI extends StatefulWidget {
#override
_DataFromAPIState createState() => _DataFromAPIState();
}
List<Attributes> _MyAllData = [];
var _srAttributes = [];
class _DataFromAPIState extends State<DataFromAPI> {
#override
void initState() {
loadData().then((value) {
setState(() {
_srAttributes.addAll(value);
});
});
super.initState();
}
Future<List<Sr>> loadData() async {
try {
var response = await http.get(Uri.parse(
'http://192.168.1.30:9080/maxrest/rest/mbo/sr/?_lid=azizl&_lpwd=max12345m&_format=json'));
if (response.statusCode == 200) {
final jsonBody = json.decode(response.body);
Demandes data = Demandes.fromJson(jsonBody);
final srAttributes = data.srMboSet.sr;
return srAttributes;
}
} catch (e) {
throw Exception(e.toString());
}
throw Exception("");
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: Text('Liste des Demandes'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => SR()))),
),
body: FutureBuilder<List<Sr>?>(
future: loadData(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
} else {
return new ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: ((_, index) {
return index == 0
? _searchbar()
: new ListTile(
title: new Card(
margin: new EdgeInsets.symmetric(
vertical: 2.0, horizontal: 8.0),
elevation: 10,
child: new ListTile(
title: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(padding: new EdgeInsets.all(2.0)),
new Text(
'Ticket ID : ${snapshot.data![index].attributes.ticketid.content}'),
new Text(
'status : ${snapshot.data![index].attributes.status.content}'),
new Text(
'description : ${snapshot.data![index].attributes.description?.content}'),
new Text(
'Reported by : ${snapshot.data![index].attributes.reportedby.content}'),
new Text(
'Reoprt date : ${snapshot.data![index].attributes.statusdate.content}'),
],
),
trailing: Icon(Icons.arrow_forward_ios_rounded),
),
),
onTap: () {
Navigator.of(context)
.push(
new MaterialPageRoute(
builder: (BuildContext context) =>
new SrDetailsScreen(
sr: snapshot.data![index]),
),
)
.then((data) {});
});
}),
);
}
},
),
),
);
}
_searchbar() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Search ..."),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_srAttributes = _MyAllData.where((srAttributes) {
var idticket = srAttributes.description!.content.toLowerCase();
return idticket.contains(text);
}).toList();
});
},
),
);
}
}
FutureBuilder loads values of current future. You are assigning a function result to FutureBuilder so its value always changes dynamically.
Create variable to keep Future's value.
Future<List<Sr>>? dataToLoad;
Whenever you want to load data from server ( for example, on text changed ):
setState((){
dataToLoad = loadData();
});
And use it in FutureBuilder:
FutureBuilder<List<Sr>?>(
future: dataToLoad,

Flutter Unable to display info from asynchronous call on first page of app

UPDATE
I was able to solve my problem using the FutureBuilder widget. All the changes were in the file_listing.dart file. Here's the updated file:
start of file_listing.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path/path.dart' as pathpkg;
import 'package:pythonga_expense_estimator/components/bottom_button.dart';
import 'package:pythonga_expense_estimator/services/directory_services.dart';
class FileListing extends StatefulWidget {
FileListing();
#override
State<FileListing> createState() => _FileListingState();
}
class _FileListingState extends State<FileListing> {
Map fileMap = {};
Future<Map> getSavedEstimates() async {
try {
var savedEstimates = await DirectoryHelper.listOfFiles().then((resp) {
return resp;
});
savedEstimates.forEach((key, value) => print(key));
return savedEstimates;
} catch (e) {
throw Exception("Could Not Retrieve list of saved files");
}
}
Future<List<Widget>> fileListMappedAsWidget() async {
var fileHits =
await getSavedEstimates(); //returns Future<Map<dynamic,dynamic>>
List<Widget> newList = [];
fileHits.forEach((k, v) {
newList.add(Row(
children: [
Text(pathpkg.basename(v)),
BottomButton(
buttonTitle: 'Delete',
onPressed: () => () {
setState(() {
k.deleteSync();
fileMap.remove(k);
});
})
],
));
});
// () => newList;
return newList;
// throw ("f");
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: fileListMappedAsWidget(),
// future: testRetrieve,
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
List<Widget> children;
print(snapshot.connectionState);
if (snapshot.hasData) {
List<Widget> childStuff = [];
for (int i = 0; i < snapshot.data!.length; i++) {
childStuff.add(snapshot.data![i]);
}
children = childStuff;
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(Icons.error_outline, color: Colors.red, size: 60),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'))
];
} else {
children = const <Widget>[
SizedBox(
width: 60, height: 60, child: CircularProgressIndicator()),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting Result'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
}),
);
}
}
end of file_listing.dart
ORIGINAL QUESTION
I'm trying to create a page for a Flutter app. It will be the first page that the user sees when they launch the app.
The page will display a list of files, cost estimates that the user has saved previously and a button for them to create a new "estimate" which can then also be saved to a file.
The files are being saved on the device, and I'm using the path_provider and path packages to access them. Reading from and writing to the device file system are asynchronous operations.
I cannot get the list of files to appear automatically when the page loads and would like to get advice on how to do this. The results of the async function are futures of data types and I cannot get them to be just data types.
Here's what I have in terms of code:
(1) main.dart
It specifies the home page of the material app to be StartPage().
start of main.dart
import 'package:flutter/material.dart';
import 'constants/text_constants.dart';
import 'pages/start_page.dart';
void main() => runApp(PythongaVisitCostCalculator());
class PythongaVisitCostCalculator extends StatelessWidget {
const PythongaVisitCostCalculator({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: kAppTitle1,
theme: ThemeData(
primarySwatch: Colors.lightBlue,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
shape: MaterialStateProperty.all<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
),
),
),
),
home: StartPage(title: kYourTripsDescr));
}
}
end of main.dart
(2) start_page.dart
This is the home page (stateful class) for the application, as specified in main.dart. One of the items that appears is a list of files saved by the user using the FileListing() widget, which is created in the file_listing.dart file, which follows.
start of start_page.dart
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pythonga_expense_estimator/components/round_icon_button.dart';
import 'package:pythonga_expense_estimator/components/file_listing.dart';
import 'package:pythonga_expense_estimator/pages/input_page.dart';
import '../constants/text_constants.dart';
class StartPage extends StatefulWidget {
const StartPage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<StartPage> createState() => _StartPageState();
}
class _StartPageState extends State<StartPage> {
Map fileList = {};
#override
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(kAppTitle2),
centerTitle: true,
automaticallyImplyLeading: false,
),
body: SafeArea(
child: Column(children: [
Text(kYourEstimatesDescr),
FileListing(),
Row(
children: [
Text(kEstimateTripDescr),
RoundIconButton(
icon: FontAwesomeIcons.plus,
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return InputPage(title: 'New Estimate');
}));
})
],
),
]),
),
);
}
}
end of start_page.dart
(3) file_listing.dart
This stateful class returns a widget ,FileListing(), that is used in the StartPage() widget.
start of file_listing.dart
import 'package:flutter/material.dart';
import 'package:path/path.dart' as pathpkg;
import 'package:pythonga_expense_estimator/components/bottom_button.dart';
import 'package:pythonga_expense_estimator/services/directory_services.dart';
class FileListing extends StatefulWidget {
FileListing();
#override
State<FileListing> createState() => _FileListingState();
}
class _FileListingState extends State<FileListing> {
Map fileMap = {};
Future<Map> getSavedEstimates() async {
try {
var savedEstimates = await DirectoryHelper.listOfFiles().then((resp) {
return resp;
});
savedEstimates.forEach((key, value) => print(key));
return savedEstimates;
} catch (e) {
throw Exception("Could Not Retrieve list of saved files");
}
}
Future<List<Widget>> fileListMappedAsWidget() async {
var fileHits = await getSavedEstimates(); //returns Future<Map<dynamic,dynamic>>
List<Widget> newList = [];
fileHits.forEach((k, v) {
newList.add(Row(
children: [
Text(pathpkg.basename(v)),
BottomButton(
buttonTitle: 'Delete',
onPressed: () => () {
setState(() {
k.deleteSync();
fileMap.remove(k);
});
})],
));
});
}
#override
Widget build(BuildContext context) {
// if (fileList.isEmpty) {
if (fileListMappedAsWidget().isEmpty) {
return Container(
child: Row(children: const [
Center(child: Text("No Estimates on File")),
]));
}
return Column(
//children: fileList,
children: fileListMappedAsWidget(),
);
}
}
end of file_listing.dart
Dart Analysis gives me an error on the line:
children: fileListMappedAsWidget(). The error is:
The argument type 'Future<List>' can't be assigned to the parameter type 'List'.
and an error on the line if (fileListMappedAsWidget().isEmpty) {
The error is:
The getter 'isEmpty' isn't defined for the type 'Future<List>
I was expecting to that the return of fileListMappedAsWidget would be a List rather than a Future<List> once the asynchronous method completed and returned its response.
My question is "How can I transform that Future<List> to List so that my page will list the files saved by the user?
(4) directory_services.dart
Here's the code in directory_services.dart that reads the contents of the application data folder and returns a map of {File, filename text}. This code appears to be working correctly.
start of directory_services.dart
import 'dart:io' as io;
import 'package:path_provider/path_provider.dart' as pathprvdrpkg;
import 'package:path/path.dart' as pathpkg;
import '../constants/text_constants.dart';
class DirectoryHelper {
static Future<Map<io.FileSystemEntity, String>> listOfFiles() async {
List<io.FileSystemEntity> fileSystemEntityList =
io.Directory(await localPath()).listSync();
Map<io.FileSystemEntity, String> fileMap = {};
for (int i = 0; i < fileSystemEntityList.length; i++) {
if (pathpkg.extension(fileSystemEntityList[i].path) ==
kEstimateFileExtension) {
fileMap[fileSystemEntityList[i]] = fileSystemEntityList[i].path;
}
}
return fileMap;
}
static localPath() async {
// finds the correct local path using path_provider package
try {
final directory = await pathprvdrpkg.getApplicationDocumentsDirectory();
// print("directory.path in DirectoryPath.localPath");
return directory.path;
} catch (e) {
return Exception('Error: $e');
}
}
}
end of directory_services.dart
Thanks for your help and advice!
I was able to solve my problem using the FutureBuilder widget. All the changes were in the file_listing.dart file. Here's the updated file:
start of file_listing.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path/path.dart' as pathpkg;
import 'package:pythonga_expense_estimator/components/bottom_button.dart';
import 'package:pythonga_expense_estimator/services/directory_services.dart';
class FileListing extends StatefulWidget {
FileListing();
#override
State<FileListing> createState() => _FileListingState();
}
class _FileListingState extends State<FileListing> {
Map fileMap = {};
Future<Map> getSavedEstimates() async {
try {
var savedEstimates = await DirectoryHelper.listOfFiles().then((resp) {
return resp;
});
savedEstimates.forEach((key, value) => print(key));
return savedEstimates;
} catch (e) {
throw Exception("Could Not Retrieve list of saved files");
}
}
Future<List<Widget>> fileListMappedAsWidget() async {
var fileHits =
await getSavedEstimates(); //returns Future<Map<dynamic,dynamic>>
List<Widget> newList = [];
fileHits.forEach((k, v) {
newList.add(Row(
children: [
Text(pathpkg.basename(v)),
BottomButton(
buttonTitle: 'Delete',
onPressed: () => () {
setState(() {
k.deleteSync();
fileMap.remove(k);
});
})
],
));
});
// () => newList;
return newList;
// throw ("f");
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: fileListMappedAsWidget(),
// future: testRetrieve,
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
List<Widget> children;
print(snapshot.connectionState);
if (snapshot.hasData) {
List<Widget> childStuff = [];
for (int i = 0; i < snapshot.data!.length; i++) {
childStuff.add(snapshot.data![i]);
}
children = childStuff;
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(Icons.error_outline, color: Colors.red, size: 60),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'))
];
} else {
children = const <Widget>[
SizedBox(
width: 60, height: 60, child: CircularProgressIndicator()),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting Result'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
}),
);
}
}
end of file_listing.dart

Hive Flutter Usage

I am a newbee at Flutter and Hive, just learning. Here are some questions:
I am using Value Listenable Builder, when I press the "Person age Up" person1 age is not updated, but if I press the setstate then is updated.
How to auto update?
Hive is a database; if I press the "Add person", it adds, and I see when I press "Print person lenght" but when reloaded the app person length is changed to 1 again, all adds removed:
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'departmentClass.dart';
import 'person.dart';
void main() async {
await Hive.initFlutter('test');
Hive.registerAdapter(DepartmentAdapter());
Hive.registerAdapter(PersonAdapter());
await Hive.openBox<Department>('testBox');
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final Box testBox = Hive.box<Department>('testBox');
#override
Widget build(BuildContext context) {
if (testBox.isEmpty) {
final List<Person> personsAll = [];
final person1 = new Person(23, "Maria");
personsAll.add(person1);
var mydepartment = new Department(34, "newD", personsAll);
Hive.box<Department>('testBox').put("01", mydepartment);
}
return ValueListenableBuilder(
valueListenable: testBox.listenable(),
builder: (context, box, widget) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Hive Test"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Hive Sample"),
RaisedButton(
child: Text("Clear Box"),
onPressed: () {
Hive.box<Department>('testBox').clear();
},
),
Text("Person1 Age Now: " + box.get("01").persons[0].age.toString()),
RaisedButton(
child: Text("Person age UP"),
onPressed: () {
box.get("01").persons[0].age++;
print(box.get("01").persons[0].age);
},
),
RaisedButton(
child: Text("Set State"),
onPressed: () {
setState(() {});
},
),
RaisedButton(
child: Text("Add person "),
onPressed: () {
final person2 = new Person(23, "Maria");
box.get("01").persons.add(person2);
},
),
RaisedButton(
child: Text("Print person lenght "),
onPressed: () {
print("Persons: " + Hive.box<Department>('testBox').get("01").persons.length.toString());
},
)
],
)),
),
),
);
},
);
}
}
First of all when you open a box it is better to declare it's type in generic;
final Box<Department> testBox = Hive.box<Department>('testBox');
Secondly if you want to notify the box that you're listening via ValueListenableBuilder, you need to put the value inside the box every time you changed the value;
box.get("01").persons[0].age++;
// this will notify the valuelistenablebuilder
box.put("01", box.get("01"));
print(box.get("01").persons[0].age);
I have written an app where I used both Hive and cubits and it worked really well.
Below is AppDatabase class, where I have only one box ('book') and I open it up in the initialize() method, like below:
The whole application and tutorial is here.
const String _bookBox = 'book';
#Singleton()
class AppDatabase {
AppDatabase._constructor();
static final AppDatabase _instance = AppDatabase._constructor();
factory AppDatabase() => _instance;
late Box<BookDb> _booksBox;
Future<void> initialize() async {
await Hive.initFlutter();
Hive.registerAdapter<BookDb>(BookDbAdapter());
_booksBox = await Hive.openBox<BookDb>(_bookBox);
}
Future<void> saveBook(Book book) async {
await _booksBox.put(
book.id,
BookDb(
book.id,
book.title,
book.author,
book.publicationDate,
book.about,
book.readAlready,
));
}
Future<void> deleteBook(int id) async {
await _booksBox.delete(id);
}
Future<void> deleteAllBooks() async {
await _booksBox.clear();
}
}

How can I implement AlertDialog box inside ListView in Flutter Android app automatically without pressing any button?

I am working on a project where I have created a RestApi where I have data of cars and which I keep updating every 3 sec. The cars are at a junction of 4 roads, now when a car is approaching towards a particular road denoted by id the "is_green" will become true and in the ListView -> the CircleAvtar will become green which will indicate that car is comming or not Now My Question is
how can I implement a AlertDialog box which will popup automically whithout pressing any button when bool isGreen = userData[index]["is_green"] will contain value true . I am new to flutter so I don't know how to do that... Please help me out
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: Home(),
));
}
class Home extends StatefulWidget {
Home({Key key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Map data;
List userData;
Future getData() async {
print("updating data...");
http.Response response = await http.get("http://10.100.101.154:3000/xd");
data = jsonDecode(response.body);
setState(() {
userData = data["data"];
});
}
#override
void initState() {
super.initState();
Timer.periodic(new Duration(seconds: 3), (timer) {
getData();
});
}
Color getColor(bool isGreen) {
if (isGreen == true) {
return Colors.green;
} else {
return Colors.red;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SGH'),
centerTitle: true,
),
body: ListView.builder(
itemCount: userData == null ? 0 : userData.length,
itemBuilder: (BuildContext context, int index) {
bool isGreen = userData[index]["is_green"];
return Card(
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10),
child: CircleAvatar(
backgroundColor: getColor(isGreen),
minRadius: 6,
),
),
Padding(
padding: EdgeInsets.all(10),
child: Wrap(
direction: Axis.horizontal,
children: <Widget>[
Text(
"Road Id = ${userData[index]["id"]} \CarInQueue = ${userData[index]["car_que"]} \nIsGreen ? --> ${userData[index]["is_green"]} ",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
],
),
);
}),
);
}
}
Just check any time you update list of cars... Then show a Dialog with informations about which car is crossing
Future getData() async {
print("updating data...");
http.Response response = await http.get("http://10.100.101.154:3000/xd");
data = jsonDecode(response.body);
setState(() {
userData = data["data"];
});
checkDialog();
}
checkDialog(){
var item = userData.where((car)=>car["is_green"]).first;//this is the first car where is_green is true
if(item!=null){
showDialog(context:context,
builder:(BuildContext context)=>AlertDialog(
//.... content here
));
}
}