How to access variable availableList below from one dart to another
class Excerciselist extends StatefulWidget {
final String value;
Excerciselist( this.value );
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyExc(); }
}
ImageSequenceAnimatorState imageSequenceAnimator;
void onReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator) {
imageSequenceAnimator = _imageSequenceAnimator;
}
final List<Exercise> availableList = [
Exercise(
name: "Pushups",
imageUrl: "imagesfirst",
duration: "20"),
Exercise(
name: "Chinups",
imageUrl: "second",
duration: "20"),
Exercise(
how can i access availableList variable in another dart file?
class Excerciselist {
String name;
String imageUrl;
String duration;
Excerciselist({
this.name,
this.imageUrl,
this.duration,
});
static List<Excerciselist> availableList = [
Excerciselist(name: "Pushups", imageUrl: "imagesfirst", duration: "20"),
Excerciselist(name: "Chinups", imageUrl: "second", duration: "20"),
];
}
then import it to you file and you can list the items, for example:
import 'package:flutter/material.dart';
import 'Excerciselist.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
List _list = Excerciselist.availableList;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView(
children: [
..._list.map((data) {
return Column(
children: [Text('${data.name}'), Text('${data.imageUrl}')],
);
})
].toList()),
));
}
}
================
you can also create an instance and methods for manipulating you data, for example to find the total duration.
class Excerciselist {
// adding these two lines
static Excerciselist instance = Excerciselist._();
Excerciselist._();
// ==
String name;
String imageUrl;
String duration;
Excerciselist({
this.name,
this.imageUrl,
this.duration,
});
static List<Excerciselist> availableList = [
Excerciselist(name: "Pushups", imageUrl: "imagesfirst", duration: "20"),
Excerciselist(name: "Chinups", imageUrl: "second", duration: "20"),
];
// Create the method
durationOf() {
int totalDur = 0;
availableList.forEach((element) {
totalDur = totalDur + int.parse(element.duration);
});
return totalDur;
}
//
}
and you can call it in your main file:
Excerciselist <name> = Excerciselist.instance;
then use it in your widget: <name>.durationOf()
import this file like mak said.
Making use of State management solutions like riverpod and provider will be more cleaner.
Related
I have a Complex map on Dart with the following structure
{
"India":["Mumbai","Delhi"],
"Australia":["Sydney","Perth" ,"Queensland" ],
"USA":["LA","New York"]
}
I am implementing a search using search delegate in flutter. But not able to query the data using Edit Text.
I am trying to search via City in-country in the above example. how can I do this?
For Example if user type "M" then city with M letter should be shown with country name
Thank you so much.
You just need to iterate over Map, then the value of List like this :
Map<String, List<String>> dataMap = {}; // your data map above
String query; // your search query
List<String> list = []; // list to store the results
if (query.isNotEmpty) {
dataMap.forEach((country, cities) {
cities.forEach((city) {
if (city.toLowerCase().startsWith(query.toLowerCase())) {
list.add('$city, $country');
}
});
});
}
Here the working example :
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return OutlinedButton.icon(
icon: Icon(Icons.search),
label: Text('Search'),
onPressed: () async {
final result = await showSearch(
context: context,
delegate: CustomSearchDelegate(),
);
print(result);
},
);
}
}
class CustomSearchDelegate<String> extends SearchDelegate<String> {
final dataMap = {
"India": [
"Mumbai",
"Delhi",
],
"Australia": [
"Sydney",
"Perth",
"Queensland",
],
"USA": [
"LA",
"New York",
]
};
#override
List<Widget> buildActions(BuildContext context) {
return [
if (query.isNotEmpty)
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return BackButton(
onPressed: () {
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
return buildSuggestions(context);
}
#override
Widget buildSuggestions(BuildContext context) {
List<String> list = [];
if (query.isNotEmpty) {
dataMap.forEach((country, cities) {
cities.forEach((city) {
if (city.toLowerCase().startsWith(query.toLowerCase())) {
list.add('$city, $country');
}
});
});
}
return ListView(
children: ListTile.divideTiles(
context: context,
tiles: list.map((data) {
return ListTile(
title: Text(data),
onTap: () {
close(context, data);
},
);
}),
).toList(),
);
}
}
My small app, is getting list of users from JSON link then store it in the List, I wanna this list into usersCollection collection ref of firestore
my code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:yat_flutter_app/main.dart';
import 'usersList.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
CollectionReference usersCollection =
FirebaseFirestore.instance.collection('users');
Future<List<User>> getUsers() async {
var data = await http
.get("https://www.json-generator.com/api/json/get/bYKKPeXRcO?indent=2");
var jasonData = json.decode(data.body);
List<User> users = [];
for (var i in jasonData) {
User user = User(i["index"], i["about"], i["name"], i["picture"],
i["company"], i["email"]);
users.add(user);
}
return users;
}
#override
Widget build(BuildContext context) {
List<User> usersList = getUsers() as List<User>;
return Container(
child: Column(
children: [
FutureBuilder(
future: getUsers(),
builder: (BuildContext context, AsyncSnapshot asyncSnapshop) {
if (asyncSnapshop.hasData) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: asyncSnapshop.data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 5,
color: Colors.cyan[50],
child: ListTile(
trailing: Icon(Icons.share),
title: Text(asyncSnapshop.data[index].name, style: TextStyle(fontFamily: 'Tahoma',fontSize: 20,fontWeight: FontWeight.bold),),
leading: CircleAvatar(
backgroundImage: NetworkImage(
asyncSnapshop.data[index].picture +
asyncSnapshop.data[index].index.toString() +
".jpg"),
),
subtitle: Text(asyncSnapshop.data[index].email,style: TextStyle(fontFamily: 'Tahmoma',fontSize: 18),),
onTap: (){
Navigator.push(context, new MaterialPageRoute(builder: (context)=>
detailsPage(asyncSnapshop.data[index])
));
},
onLongPress: ()=>
Fluttertoast.showToast(
msg: asyncSnapshop.data[index].name,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green[900],
textColor: Colors.white,
fontSize: 16.0
),
),
);
}),
);
} else {
return Text("Loading, please wait...");
}
},
),
ElevatedButton(
child: Text('Save data'),
onPressed: () => {
usersCollection.add(getUsers()); // here's I am trying to add the result of getUsers into usersCollection
}),
],
),
);
}
}
To push an object to Firestore you need to convert your object to map.
You can just add this function to your class:
Map<String, dynamic> toMap() {
return {
'field1': value1,
'field2': value1,
};
}
To push a List , you need to convert all objects to map, you can do it with following method:
static List<Map> ConvertToMap({List myList }) {
List<Map> steps = [];
myList.forEach((var value) {
Map step = value.toMap();
steps.add(step);
});
return steps;
}
Or simply , see how to convert List to Map
I hope it will be useful
To push this list to Firestore you need to fromJson and toJson methods in your model class
factory User.fromJson(Map<String, dynamic> data){
return User(
index: data['index'] as int,
about: data['about'] as String,
name: data['name'] as String,
picture: data['picture'] as String,
company: data['company'] as String,
email: data['email'] as String );
}
Map<String, dynamic> toJson(){
return {
"index": index,
"about" : about,
"name" : name,
"picture" : picture,
"company" : company,
"email" : email,
};
}
instead that I would like to suggest using json_serializable library
then you need to do some changes in your future method like this
getUsers().then((users) {
// add users to map
});
and then you can use fromJson method to push it to firestore database
Firebase realtime database and firestore are no SQL databases where data will be stored in Parent child relation or Tree structure.
For you to store list of data you can convert your list into Map
Map can be initialised as follows
Map<String, String> toMap() {
return {
'Fruit': "Mango",
'Flower': "Lotus",
'Vegetable': "Potato",
};
}
After you have Map you can set value to the firestore. You can use the below code to set value
Map<String, Object> city = new Map<>();
//Loop through your list and load Map (City) values
db.collection("cities").document("LA").set(city)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully written!");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error writing document", e);
}
});
You can convert List of items to map using this
Java: How to convert List to Map
I want to upload a List of a custom class to the cloud firebase, but I get the error that my custom class is not a subtype of type <dynamic>. Does this happen because it is not possible to upload List of custom classes to firebase? Do I need to create e new collection which than works as the List or is there a other way to work around this problem?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
//Class for the custom list
class CustomClass {
int id;
String content;
CustomClass({this.id, this.content});
CustomClass.fromMap(Map<String, dynamic> data) {
id = data['id'];
content = data['content'];
}
Map<String, dynamic> toMap() {
return {
'id': id,
'content': content,
};
}
}
//Model which I want to upload with the custom list
class CustomModel {
String name;
List<CustomClass> customList;
CustomModel();
CustomModel.fromMap(Map<String, dynamic> data) {
name = data['name'];
customList = data['customList'];
}
Map<String, dynamic> toMap() {
return {
'name': name,
'customList': customList,
};
}
}
//Page to upload the customModel with the customList
class UploadPage extends StatelessWidget {
CustomModel _customModel = CustomModel();
List<CustomClass> _customList = [CustomClass(id: 1, content: 'UserContent')];
#override
Widget build(BuildContext context) {
return Scaffold(
body: FlatButton(
child: Text('Upload'),
onPressed: () async {
_customModel.name = 'UserName';
_customModel.customList = _customList;
await Firestore.instance
.collection('CustomClass')
.add(_customModel.toMap());
}),
);
}
}
You can use dart: convert to convert your model object into json format i.e Map which you can upload to Firebase.
For this, I have renamed your toMap method to toJson & fromMap methods to fromJson. Also, I have added factory keyword before fromJson methods.
You should also override the toString method to print your objects for testing/debugging.
Your code should look something like this:
//Class for the custom list
class CustomClass {
int id;
String content;
CustomClass({this.id, this.content});
factory CustomClass.fromJson(Map<String, dynamic> data) {
return CustomClass(
id: data['id'],
content: data['content'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'content': content,
};
}
#override
String toString() {
return '${const JsonEncoder.withIndent(' ').convert(this)}';
}
}
//Model wich I want to upload with the custom list
class CustomModel {
String name;
List<CustomClass> customList;
CustomModel({
this.name,
this.customList,
});
factory CustomModel.fromJson(Map<String, dynamic> data) {
List<dynamic> list = data['customList'] ?? [];
final customList = list.map((e) => CustomClass.fromJson(e)).toList();
return CustomModel(
name: data['name'],
customList: customList,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'customList': customList?.map((e) => e.toJson())?.toList(),
};
}
#override
String toString() {
return '${const JsonEncoder.withIndent(' ').convert(this)}';
}
}
// Your build method:
CustomModel _customModel = CustomModel();
List<CustomClass> _customList = [CustomClass(id: 1, content: 'UserContent')];
#override
Widget build(BuilContext context) {
return Scaffold(
body: FlatButton(
child: Text('Upload'),
onPressed: () async {
_customModel.name = 'UserName';
_customModel.customList = _customList;
await Firestore.instance
.collection('CustomClass')
.add(_customModel.toJson());
}),
);
}
so i'm working on a Map that has this structure :
Map<String, List<Video>> mapName;
Where Video is just an object that has 3 attributes : String title,String videoURL, bool isDone.
I'm planing on creating a listView that will display all Video titles so i'm just trying to figure out how to get the length of the list that exists into the Map.
I tryed some test and it displayed this :
print(videoList.values.map((list) => list.length));
I/flutter (23887): (9)
Now its true that i have 9 videos in the list, but I cannot use this in my listview itemcount because it requires an int type data.
If your Map have more than one list of videos by the key String of the Map, you can get all lengths using this code:
Map<String, List<Video>> mapName = {
'video1': [Video(),Video()],
'video2': [Video()],
'video3': [Video(),Video(),Video()],
}; //Init
int total = 0;
mapName.keys.forEach((key){
List<Video> video = mapName[key];
int length = video.length;
print('$key: $length');
total += length;
});
print('total: $total');
Flutter Example:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class Video {
final String name;
final String url;
final bool isDone;
Video(this.name, this.url, this.isDone);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Map<String, List<Video>> mapName = {
'video1': [
Video('Bunny', 'http://????', false),
Video('Bunny10', 'http://????', true),
],
'video2': [
Video('Bunny2', 'http://????', false),
],
'video3': [
Video('BunnyX', 'http://????', false),
Video('Bunny12', 'http://????', true),
Video('BunnyZZ', 'http://????', false),
],
}; //Init
List<Video> mVideos = [];
mapName.values.forEach((videos) {
videos.forEach((video) {
mVideos.add(video);
});
});
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: ListView.builder(
itemCount: mVideos.length,
itemBuilder: (context, index) {
Video video = mVideos[index];
String name = video.name;
String url = video.url;
bool isDone = video.isDone;
return ListTile(
tileColor: isDone ? Colors.green : null,
title: Text(name),
subtitle: Text(url),
);
},
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4);
}
}
I want to cache two lists that got from Firebase to use to later when the user is offline
This is the full code for my list display screen -
import 'package:flutter/material.dart';
import 'package:naamaa/calculations/name-list-calc.dart';
List namesList = List();
List meaningsList = List();
class NameList extends StatefulWidget {
#override
_NameListState createState() => _NameListState();
}
class _NameListState extends State<NameList> {
Future<String> getPosts() async {
var names = await NameListCalc().nameListCalc();
namesList.addAll(names[0]);
meaningsList.addAll(names[1]);
String s = 'test';
return s;
}
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: ListView.builder(
padding: EdgeInsets.zero,
itemBuilder: (context, position) {
return Row(
children: <Widget>[
Container(
width: 100,
child: Text(namesList[position]),
),
Container(
child: Text(meaningsList[position]),
)
],
);
},
itemCount: namesList.length,
),
);
} else {
return Text(':(');
}
},
);
}
}
I want to cache namesList and meaningsList for later use.
If someone can help it would be great :)
I didn't get complete requirement by your question description but you can use shared_preferences library to store the data list as following
Add following line pubspec.yaml
dependencies:
flutter:
sdk: flutter
shared_preferences:
You can use this example and add more utility methods as per you requirement.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
AppConfig.init(() {
runApp(MyApp());
});
}
class CustomModel {
int id;
String name;
CustomModel({this.id, this.name});
factory CustomModel.fromJson(Map<String, dynamic> json) {
return CustomModel(id: json["id"], name: json["name"]);
}
Map<String, dynamic> toJson() => {"id": id, "name": name};
#override
String toString() {
return "id: $id, name: $name";
}
}
class AppConfig {
static Future init(VoidCallback callback) async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferenceUtils.init();
callback();
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class SharedPreferenceUtils {
static SharedPreferences prefs;
static init() async {
prefs = await SharedPreferences.getInstance();
// storing lists
await putStringList("m_list", ["abc", "def"]);
await putObjectList("data",
[CustomModel(id: 1, name: "Bob"), CustomModel(id: 2, name: "Alice")]);
}
static Future<bool> putStringList(String key, List<String> list) async {
return prefs.setStringList(key, list);
}
static List<String> getStringList(String key) {
return prefs.getStringList(key);
}
static Future<bool> putObjectList(String key, List<Object> list) async {
if (prefs == null) return null;
List<String> _dataList = list?.map((value) {
return json.encode(value);
})?.toList();
return prefs.setStringList(key, _dataList);
}
static List<T> getObjList<T>(String key, T f(Map v),
{List<T> defValue = const []}) {
if (prefs == null) return null;
List<Map> dataList = getObjectList(key);
List<T> list = dataList?.map((value) {
return f(value);
})?.toList();
return list ?? defValue;
}
static List<Map> getObjectList(String key) {
if (prefs == null) return null;
List<String> dataList = prefs.getStringList(key);
return dataList?.map((value) {
Map _dataMap = json.decode(value);
return _dataMap;
})?.toList();
}
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(SharedPreferenceUtils.getStringList("m_list").toString()),
Text(SharedPreferenceUtils.getObjList<CustomModel>(
"data", (v) => CustomModel.fromJson(v)).toString()),
],
),
),
),
);
}
}
You don't need to store the lists in init() as it's done for this example. You can also pass data from one widget to others in multiple ways and if you are looking for state management then you can use BLOC or providers.