Hello flutter experts i am fetching data from Api and show in listview in my app when user click any item from listview its saved data in sqlite now i want if API data already exist in sqlite then my trailing star icon change into yellow color otherwise it will remain same please check my code let me know i can achieve this type functionality mobile app.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:testfproject/Model/Articlemodel.dart';
import 'package:testfproject/Model/Favourite/Favouritemodel.dart';
import 'package:testfproject/Services/services.dart';
import 'package:http/http.dart' as http;
import '../Db/Databasehelper.dart';
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
void initState() {
// TODO: implement initState
super.initState();
// article();
}
Services api=Services();
Databasehelper databasehelper=Databasehelper();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Articles'),
),
body: Column(
children: [
FutureBuilder(
future: api.Article(),
builder: (BuildContext context, AsyncSnapshot<List<Articlemodel>> snapshot) {
if(snapshot.hasData){
List<Articlemodel>?articles=snapshot.data;
return Expanded(
child: ListView.separated(
shrinkWrap: true,
itemCount:articles!.length,
itemBuilder: (conext,index){
//this list tile when user press on trailing icon it saved data in sqlite
return ListTile(
trailing: IconButton(
icon:Icon(Icons.star),
onPressed: () {
databasehelper.insert(Favouritemodel(author: articles[index].author.toString(), title:articles[index].title.toString()));
},
),
title: Text(articles[index].title.toString()),
//subtitle: Text(articles[index].author.toString()),
);
}, separatorBuilder: (BuildContext context, int index) {
return Divider();
},),
);
}else{
return Container(
child: Text('NO data'),
);
}
},
)
],
),
);
}
}
//my Api services class
import 'dart:convert';
import 'package:testfproject/Model/Articlemodel.dart';
import 'package:http/http.dart' as http;
class Services{
Future<List<Articlemodel>>Article() async {
final response = await http.get(Uri.parse('https://newsapi.org/v2/top-headlines?country=us&apiKey=0fb3a9662c3747fba42ffd3d66cc612d'));
if(response.statusCode==200){
var data=jsonDecode(response.body.toString());
final Iterable json = data["articles"];
return json.map((article) => Articlemodel.fromJson(article)).toList();
}else{
throw Exception('Error');
}
}
}
model class of api
class Articlemodel {
Source? source;
String? author;
String? title;
String? description;
String? url;
String? urlToImage;
String? publishedAt;
String? content;
bool? iSfavourite;
Articlemodel(
{this.source,
this.author,
this.title,
this.description,
this.url,
this.urlToImage,
this.publishedAt,
this.content,
});
Articlemodel.fromJson(Map<String, dynamic> json) {
source =
json['source'] != null ? new Source.fromJson(json['source']) : null;
author = json['author'];
title = json['title'];
description = json['description'];
url = json['url'];
urlToImage = json['urlToImage'];
publishedAt = json['publishedAt'];
content = json['content'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.source != null) {
data['source'] = this.source!.toJson();
}
data['author'] = this.author;
data['title'] = this.title;
data['description'] = this.description;
data['url'] = this.url;
data['urlToImage'] = this.urlToImage;
data['publishedAt'] = this.publishedAt;
data['content'] = this.content;
return data;
}
}
class Source {
String? id;
String? name;
Source({this.id, this.name});
Source.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}
//model class of sqlite for favouriting
class Favouritemodel {Favouritemodel(
{required this.author,required this.title,}
);
Favouritemodel.fromJson(dynamic json) {
author = json['author'];
title = json['title'];
}
String? author;
String? title;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['author'] = author;
map['title'] = title;
return map;
}
}
//database helper class
import 'dart:io' as io;
import 'package:flutter/cupertino.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import '../Model/Favourite/Favouritemodel.dart';
class Databasehelper{
static Database? _db;
bool check=false;
Future<Database?> get db async {
if(_db != null)
return _db;
_db = await initDb();
return _db;
}
//Creating a database with name test.dn in your directory
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "favourite.db");
var theDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return theDb;
}
// Creating a table
void _onCreate(Database db, int version) async {
// When creating the db, create the table
await db.execute(
"CREATE TABLE favourite(ID INTEGER PRIMARY KEY AUTOINCREMENT, author TEXT, title TEXT unique )");
print("Created tables");
}
//insert data
Future<Favouritemodel> insert(Favouritemodel favouritemodel) async {
Database? db = await this.db;
await db!.insert('favourite', favouritemodel.toJson()).catchError((e)=>(debugPrint(e)));
return favouritemodel;
}
first add this function to your database helper
Future<List<Favouritemodel>> favourites() async {
Database? db = await this.db;
final List<Map> data = await db!.query('favourite');
return data.map((e) => Favouritemodel.fromJson(e)).toList();
}
and override the equal operator in Favouritemodel
#override
bool operator ==(Object other) {
return identical(this, other) ||
(other is Favouritemodel &&
author == other.author &&
title == other.title);
receive the favourite list in the build method:
#override
Widget build(BuildContext context) {
final futureFavourites = databasehelper.favourites();
return Scaffold(
// ...
and finally change the itemBuilder to this:
itemBuilder: (conext, index) {
return FutureBuilder<List<Favouritemodel>>(
future: futureFavourites,
builder: (context, favouriteSnapshot) {
if(!favouriteSnapshot.hasData) {
return ListTile(title: Text('Loading...'));
}
final favourites = favouriteSnapshot.data!;
final favouriteModel = Favouritemodel(author: articles[index].author.toString(),
title:articles[index].title.toString());
final isFavourite = favourites.contains(favouriteModel);
return ListTile(
trailing: IconButton(
icon:Icon(Icons.star, color: isFavourite ? Colors.yellow : null),
onPressed: () {
databasehelper.insert(favouriteModel);
},
),
title: Text(articles[index].title.toString()),
//subtitle: Text(articles[index].author.toString()),
);
}
);
}
Related
This is my data model
class RoleModel {
int? id;
String? role;
RoleModel({this.id, this.role});
RoleModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
role = json['role'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['role'] = role;
return data;
}
}
This is my code to get api data
List<RoleModel> roles = [];
Future<List<RoleModel>> getRoles() async {
try {
final response = await http
.get(Uri.parse('https://localhost:8000/roles'));
var data = jsonDecode(response.body.toString());
if (response.statusCode == 200) {
for (Map<String, dynamic> i in data) {
roles.add(RoleModel.fromJson(i));
}
return roles;
} else {
throw Exception('Failed to load roles:$response');
}
} catch (e) {
throw Exception('Failed due to: $e');
}
}
How can I create a dropdown button which will have 'id' as value and 'role' will be displayed as text?
You can use the below the line of sample code for dropdown widget
DropdownButton<String>(
items: <String>['One', 'Two', 'Three', 'Four'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (v) {},
),
you can create it like this
DropdownButton<int>(
items: [
DropdownMenuItem(
child: Text("${roleModel.role}"),
value: roleModel.id,
),
],
onChanged: (value) {},
),
You can also create a dropdown button just using a custom package from pub.dev :
Add the latest version of dropdown_button2 to your pubspec.yaml file from
[1]: https://pub.dev/packages/dropdown_button2/install
Run 'flutter pub add dropdown_button2' this command from your terminal.
Add 'import 'package:dropdown_button2/dropdown_button2.dart'; this line to your code page.
import 'dart:convert';
import 'package:dropdown_button2/custom_dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyFlutterApp());
class MyFlutterApp extends StatelessWidget {
const MyFlutterApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
List<String> get getAllRoles {
List<String> allRoles = [];
for (int i = 0; i < roles.length; i++) {
allRoles.add('${roles[i].id} ${roles[i].role}');
}
return allRoles; // String format of json taken from the web.
}
int index = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dropdown with id and role'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: CustomDropdownButton2(
hint: 'Select Item',
dropdownItems: getAllRoles,
value: getAllRoles[index],
buttonWidth: double.infinity,
dropdownWidth: double.infinity,
buttonElevation: 7,
onChanged: (value) {
setState(() {
index = getAllRoles.indexOf(value.toString());
});
},
),
),
);
}
}
class RoleModel {
int? id;
String? role;
RoleModel({this.id, this.role});
RoleModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
role = json['role'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['role'] = role;
return data;
}
}
List<RoleModel> roles = [];
Future<List<RoleModel>> getRoles() async {
try {
final response = await http.get(Uri.parse('https://localhost:8000/roles'));
var data = jsonDecode(response.body.toString());
if (response.statusCode == 200) {
for (Map<String, dynamic> i in data) {
roles.add(RoleModel.fromJson(i));
}
return roles;
} else {
throw Exception('Failed to load roles:$response');
}
} catch (e) {
throw Exception('Failed due to: $e');
}
}
I've received an error, because the http URL isn't accessible now. If you try it with a new URL, i think this code will work correctly.
so I'm using flutter 2.2 and I'm tring to get data from an sqlite database but it's always coming as null
data_helper
class DataBaseHelper{
static final _dataBaseName = 'test.db';
static final _dataBaseVerison = 1;
static final _tabel = 'person';
DataBaseHelper._privateConstructor();
static final DataBaseHelper instance = DataBaseHelper._privateConstructor();
static Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await initDatabase();
return _database!;
}
#override
Future<Database> initDatabase() async {
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, _dataBaseName);
var exists = await databaseExists(path);
if (!exists) {
try {
await Directory(dirname(path)).create(recursive: true);
} catch (_) {}
ByteData data = await rootBundle.load(join("assets", _dataBaseName));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(path).writeAsBytes(bytes, flush: true);
}
Database newDatabase = await openDatabase(path, version: _dataBaseVerison);
return newDatabase;
}
getAllRows(String tabel) async {
Database db = await instance.database;
var result = await db.query(tabel) ;
print("All Data : $result");
return result.toList();
}
}
person_model
class Person {
Person({
int? id,
String? firstname,
String? lastName,}){
_id = id;
_firstname = firstname;
_lastName = lastName;
}
Person.fromJson(dynamic json) {
_id = json['id'];
_firstname = json['Firstname'];
_lastName = json['lastName'];
}
int? _id;
String? _firstname;
String? _lastName;
int? get id => _id;
String? get firstname => _firstname;
String? get lastName => _lastName;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = _id;
map['Firstname'] = _firstname;
map['lastName'] = _lastName;
return map;
}
}
main
class _MyHomePageState extends State<MyHomePage> {
DataBaseHelper dbHelper = DataBaseHelper.instance;
List<Person> person= List.empty(growable: true);
#override
void initState() {
super.initState();
dbHelper.getAllRows('person').then((rows){
setState(() {
rows.forEach((row) {
person.add(Person.fromJson(row));
});
});
});
}
#override
Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(title: Text('SQLite Example')),
body: Center(
child: ListView.builder(
itemCount:person.length,
itemBuilder: (context,index){
return ListTile(
title:Text('${person[index].name}}.'),
);
}),
),
);
}
}
data from database when I print it
All Data : [{id:1,Firstname:test,lastName:test}]
so i know that when i send data to fromjason it goes as null not a string and I tried JSON.decode(row) didn't work as type 'QueryRow' is not a subtype of type 'String'
Need to pass row data in fromJson and follow the below code
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Person> person = List.empty(growable: true);
List<Map> data = [
{"id": 1, "Firstname": "test", "lastName": "test"}
];
#override
void initState() {
super.initState();
data.forEach((row) {
person.add(Person.fromJson(row));
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text('SQLite Example')),
body: Center(
child: ListView.builder(
itemCount: person.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${person[index].firstname} ${person[index].lastName}'),
);
}),
),
),
);
}
}
class Person {
Person({
int? id,
String? firstname,
String? lastName,
}) {
_id = id;
_firstname = firstname;
_lastName = lastName;
}
Person.fromJson(dynamic json) {
_id = json['id'];
_firstname = json['Firstname'];
_lastName = json['lastName'];
}
int? _id;
String? _firstname;
String? _lastName;
int? get id => _id;
String? get firstname => _firstname;
String? get lastName => _lastName;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = _id;
map['Firstname'] = _firstname;
map['lastName'] = _lastName;
return map;
}
}
I am a beginner in flutter app development and I want to display thumb images into flutter grid view builder. My postman return response is 200. This is the response from postman
This is my flutter code. I donot know what i am doing wrong.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> fetchPhotos(http.Client client) async {
var headers = {
'Authorization': 'Bearer $bearer_token'
};
var request = http.Request('GET', Uri.parse('https://xxxxx.execute-api.us-east-2.amazonaws.com/stg/assets'));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
return compute(parsePhotos, response.body);
}
else {
print(response.reasonPhrase);
}
}
List<Photo> parsePhotos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
}
class Photo {
List<Assets> assets;
Photo({this.assets});
Photo.fromJson(Map<String, dynamic> json) {
if (json['assets'] != null) {
assets = new List<Assets>();
json['assets'].forEach((v) {
assets.add(new Assets.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.assets != null) {
data['assets'] = this.assets.map((v) => v.toJson()).toList();
}
return data;
}
}
class Assets {
String assetId;
String createdAt;
String description;
bool isPrivate;
bool isThumbnailGenerated;
Metadata metadata;
String name;
Null sharedBy;
int sizeInBytes;
List<String> tags;
String thumbnailUrl;
String title;
String type;
String uploadDate;
String uploadStatus;
Assets(
{this.assetId,
this.createdAt,
this.description,
this.isPrivate,
this.isThumbnailGenerated,
this.metadata,
this.name,
this.sharedBy,
this.sizeInBytes,
this.tags,
this.thumbnailUrl,
this.title,
this.type,
this.uploadDate,
this.uploadStatus});
Assets.fromJson(Map<String, dynamic> json) {
assetId = json['asset_id'];
createdAt = json['created_at'];
description = json['description'];
isPrivate = json['is_private'];
isThumbnailGenerated = json['is_thumbnail_generated'];
metadata = json['metadata'] != null
? new Metadata.fromJson(json['metadata'])
: null;
name = json['name'];
sharedBy = json['shared_by'];
sizeInBytes = json['size_in_bytes'];
tags = json['tags'].cast<String>();
thumbnailUrl = json['thumbnail_url'];
title = json['title'];
type = json['type'];
uploadDate = json['upload_date'];
uploadStatus = json['upload_status'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['asset_id'] = this.assetId;
data['created_at'] = this.createdAt;
data['description'] = this.description;
data['is_private'] = this.isPrivate;
data['is_thumbnail_generated'] = this.isThumbnailGenerated;
if (this.metadata != null) {
data['metadata'] = this.metadata.toJson();
}
data['name'] = this.name;
data['shared_by'] = this.sharedBy;
data['size_in_bytes'] = this.sizeInBytes;
data['tags'] = this.tags;
data['thumbnail_url'] = this.thumbnailUrl;
data['title'] = this.title;
data['type'] = this.type;
data['upload_date'] = this.uploadDate;
data['upload_status'] = this.uploadStatus;
return data;
}
}
class Metadata {
int exifOffset;
int imageLength;
int imageWidth;
int lightSource;
int orientation;
Metadata(
{this.exifOffset,
this.imageLength,
this.imageWidth,
this.lightSource,
this.orientation});
Metadata.fromJson(Map<String, dynamic> json) {
exifOffset = json['ExifOffset'];
imageLength = json['ImageLength'];
imageWidth = json['ImageWidth'];
lightSource = json['LightSource'];
orientation = json['Orientation'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ExifOffset'] = this.exifOffset;
data['ImageLength'] = this.imageLength;
data['ImageWidth'] = this.imageWidth;
data['LightSource'] = this.lightSource;
data['Orientation'] = this.orientation;
return data;
}
}
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
const appTitle = 'Get Assets';
return const MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Photo>>(
future: fetchPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('An error has occurred!'),
);
} else if (snapshot.hasData) {
return PhotosList(photos: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
class PhotosList extends StatelessWidget {
const PhotosList({Key? key, required this.photos}) : super(key: key);
final List<Photo> photos;
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return Image.network(photos[index].thumbnailUrl);
},
);
}
}
in Gridview Builder ... thumbnail images are not loading and it is throwing error.
[![enter image description here][2]][2]
I want the result like this
[2]: https://i.stack.imgur.com/Bnyaj.gif
I am using Firebase Database to store information regarding my flutter app.
I have manually updated my collections and documents.
But in one instance I want my users to setdata in my documents so it gets reflected in the app for that particular user. But, when the user does setdate it goes and creates new documents which I do not want, I want the user to setdata in the existing document. I did try but no luck.
Here are my codes:
class FirestoreService {
FirestoreService._();
static final instance = FirestoreService._();
Future<void> setData(
{#required String path, Map<String, dynamic> data}) async {
final reference = Firestore.instance.document(path);
await reference.setData(data);
}
abstract class Database {
Future<void> setRackBook(RackBookItems rackBookItems);
}
bool documentCheckBox() => true;
class FirestoreDatabase implements Database {
final String uid;
FirestoreDatabase({#required this.uid}) : assert(uid != null);
final _service = FirestoreService.instance;
#override
Future<void> setRackBook(RackBookItems rackBookItems) async =>
await _service.setData(
path: APIPath.rackBookItems(uid, rackBookItems.id),
data: rackBookItems.toMap());
}
class PageScreen extends StatefulWidget {
final RackBookItems rackBookItems;
final Database database;
const PageScreen(this.rackBookItems, {#required this.database});
static Future<void> show(
BuildContext context, {
Database database,
RackBookItems rackBookItems,
}) async {
final database = Provider.of<Database>(context);
await Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(
fullscreenDialog: false,
builder: (context) => PageScreen(
rackBookItems,
database: database,
),
),
);
}
#override
_PageScreenState createState() => _PageScreenState();
}
class _PageScreenState extends State<PageScreen> {
final _formKey = GlobalKey<FormState>();
bool _validateAndSaveForm() {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
Future<void> _completed() async {
if (_validateAndSaveForm()) {
try{
final checkBox = widget.rackBookItems?.checkBox ?? documentCheckBox();
final rackBookItems = RackBookItems(checkBox: checkBox);
await widget.database.setRackBook(rackBookItems);
Navigator.of(context).pop();
} on PlatformException catch (e) {
PlatformExceptionAlertDialog(
title: 'Operations failed',
exception: e,
).show(context);
}
}
}
#override
Widget build(BuildContext context) {
final auth = Provider.of<AuthBase>(context, listen: true);
return SafeArea(
child: Scaffold(
body: Column(
children: <Widget>[
StreamBuilder<User>(
stream: auth.onAuthStateChange,
builder: (context, snapshot) {
User user = snapshot.data;
if (snapshot.hasData) {
return Provider<Database>(
create: (_) => FirestoreDatabase(uid: user.uid),
child: Text('Data'),
);[![enter image description here][1]][1]
}
return Center(
child: CircularProgressIndicator(),
);
},
),
Form(
key: _formKey,
child: RaisedButton(
child: Text(
'Done',
style: TextStyle(color: Theme.of(context).accentColor),
),
onPressed: _completed,
),
)
],
),
),
);
}
}
class RackBookItems {
final String id;
final String rackId;
final String title;
final bool checkBox;
const RackBookItems({
this.id,
this.rackId,
this.title,
this.checkBox,
});
Map<String, dynamic> toMap() {
return {
'checkBox': checkBox,
};
}
factory RackBookItems.fromMap(Map<String, dynamic> data, String id) {
if (data == null) {
return null;
}
final String id = data['id'];
final String rackId = data['rackId'];
final String title = data['title'];
final bool checkBox = data['checkBox'];
return RackBookItems(
id: id,
rackId: rackId,
title: title,
checkBox: checkBox,
);
}
}
This is how my firebase looks like.
[1]: https://i.stack.imgur.com/Z07ai.png
Is there any error with the path I have given?
class APIPath {
static String rackBookItems( String uid, String id) =>
'rackBookItems/$id/';
}
You need to use updateData, this method required you to know the document's Document ID
Firestore.instance.collection('rackBookItems').document('book1').updateData({
'newData' : 14
});
If you need to update all of your documents, you can pull all of the documents and use a for loop to update them.
QuerySnapshot qs = await Firestore.instance.collection('rackBookItems').getDocuments();
List<DocumentSnapshot> books = qs.documents;
for (int i = 0; i < books.length; i++){
Firestore.instance.collection('rackBookItems').documents(books[i].documentID).updateData({
'title' : newData
});
}
updateData is good but in case the document does not exist you should use setData and set merge: true
class FirestoreService {
FirestoreService._();
static final instance = FirestoreService._();
Future<void> setData(
{#required String path, Map<String, dynamic> data}) async {
final reference = Firestore.instance.document(path);
await reference.setData(data, merge:true);
}
Hello friends,
I have been learning to use flutter for weeks, I am creating an app that I develop as I learn to program in flutter.
My idea is to be able to follow the Pattern (BLoC). What I want to do now is like being able to load the movie data list into the home.dart file in the body property
I appreciate your help!
home.dart
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'package:skyshowapp/styles/theme.dart' as Style;
class HomeScreen extends StatefulWidget{
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen>{
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Style.Colors.mainColor,
appBar: AppBar(
backgroundColor: Style.Colors.mainColor,
centerTitle: true,
leading: Icon(EvaIcons.menu2Outline , color: Colors.white),
title: Text("SKYSHOW APP"),
actions: <Widget>[
IconButton(icon: Icon(EvaIcons.searchOutline , color: Colors.white,), onPressed: null,)
],
),
body: ListView(
children: <Widget>[
],
),
);
}
}
movie_bloc.dart
import 'package:rxdart/subjects.dart';
import 'package:skyshowapp/model/movie.dart';
import 'package:skyshowapp/repository/repository.dart';
class MovieListBloc{
final MovieRepository _repository = new MovieRepository();
final BehaviorSubject<MovieRootClass> _subject = new BehaviorSubject<MovieRootClass>();
getMovies() async{
MovieRootClass response = await _repository.getMovies();
_subject.sink.add(response);
}
dispose(){
_subject.close();
}
BehaviorSubject<MovieRootClass> get subject => _subject;
}
final movieBloc = new MovieListBloc();
class MovieRootClass {
List<Movies> movies;
MovieRootClass({this.movies});
MovieRootClass.fromJson(Map<String, dynamic> json) {
if (json['movies'] != null) {
movies = new List<Movies>();
json['movies'].forEach((v) {
movies.add(new Movies.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.movies != null) {
data['movies'] = this.movies.map((v) => v.toJson()).toList();
}
return data;
}
}
class Movies {
String id;
String title;
String sinopsis;
String poster;
String rating;
String quality;
String year;
List<Extra> extra;
Movies(
{this.id,
this.title,
this.sinopsis,
this.poster,
this.rating,
this.quality,
this.year,
this.extra});
Movies.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
sinopsis = json['sinopsis'];
poster = json['poster'];
rating = json['rating'];
quality = json['quality'];
year = json['year'];
if (json['extra'] != null) {
extra = new List<Extra>();
json['extra'].forEach((v) {
extra.add(new Extra.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['title'] = this.title;
data['sinopsis'] = this.sinopsis;
data['poster'] = this.poster;
data['rating'] = this.rating;
data['quality'] = this.quality;
data['year'] = this.year;
if (this.extra != null) {
data['extra'] = this.extra.map((v) => v.toJson()).toList();
}
return data;
}
}
// Extra class .....
You can use StreamBuilder widget which takes in a stream, and rebuilds itself when ever new data is added to the stream.
StreamBuilder(
stream: subject.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.movies.length,
itemBuilder: (BuildContext context, int idnex) {
return ListTile(
title: Text(snapshot.data.someProperty),
);
},
);
}
return const CircularProgressIndicator();
},
);