Error: A value of type 'List<String>' can't be assigned to a variable of type 'List<ChartData>', trying to create a Chart with a list of Strings, - list

I'm trying to create a graph and i don't know how to set values on this graph (I know how to set the values manually but i created a field in firestore that receives the value of x and y of the graph when you click on a button ), i'm using SyncFusion Flutter Chart (if you have any another idea to solve my problem feel free to say) and i'm trying to add the values ( String ) to the list and for that i Created in firestore when you click on the button (ChartData(x,y)) so all i need is add this string to the list of type ChartData, and for that i'm trying to use decode and split but now returned this error and i don't know how to solve. i'm sorry for the long text.
List<ChartData> convert(String input) {
List<ChartData> output;
try {
output = json.decode(input);
return output;
} catch (err) {
print('The input is not a string representation of a list');
return [ChartData(0, 0)];
}
}
List<ChartData> testim = testefinal.split(',');
final List<ChartData> list1 = convert(testefinal);
final List<ChartData> chartData = list1;
Error: A value of type 'List<String>' can't be assigned to a variable of type 'List<ChartData>'.
Full Code:
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:mood3/telas/animacao.dart';
import 'package:ntp/ntp.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import '../model/GraphMood.dart';
class Graph extends StatefulWidget {
#override
State<Graph> createState() => _GraphState();
}
class _GraphState extends State<Graph> {
TooltipBehavior? _tooltipBehavior;
DateTime ntpTime = DateTime.now();
String testefinal = '';
_loadNTPTime() async {
FirebaseAuth auth = FirebaseAuth.instance;
FirebaseFirestore db = FirebaseFirestore.instance;
setState(() async {
ntpTime = await NTP.now();
});
}
Future _recuperarNome() async {
FirebaseAuth auth2 = FirebaseAuth.instance;
User? user = auth2.currentUser;
DocumentSnapshot ds = await db.collection('usuarios')
.doc(user!.uid)
.get();
Map<String, dynamic> dss = ds.data() as Map<String, dynamic>;
setState((){
testefinal = dss["moodGraph"];
});
print(testefinal);
}
FirebaseFirestore db = FirebaseFirestore.instance;
#override
initState(){
_recuperarNome();
_tooltipBehavior = TooltipBehavior(enable: true);
super.initState();
_loadNTPTime();
}
#override
Widget build(BuildContext context) {
List<ChartData> convert(String input) {
List<ChartData> output;
try {
output = json.decode(input);
return output;
} catch (err) {
print('The input is not a string representation of a list');
return [ChartData(0, 0)];
}
}
List<ChartData> testim = testefinal.split(',');
final List<ChartData> list1 = convert(testefinal);
final List<ChartData> chartData = list1;
return Scaffold(
body: Center(
child: Container(
child: SfCartesianChart(
primaryXAxis: CategoryAxis(),
// Chart title
title: ChartTitle(text: 'Mood Chart'),
// Enable legend
legend: Legend(isVisible: true),
// Enable tooltip
tooltipBehavior: _tooltipBehavior,
series: <ChartSeries>[
// Renders line chart
LineSeries<ChartData, int>(
dataSource: chartData,
xValueMapper: (ChartData data, _) => data.x.toInt(),
yValueMapper: (ChartData data, _) => data.y
)
]
)
)
)
);
}
}
class ChartData {
ChartData(this.x, this.y);
final double x;
final double y;
}

I think, output = json.decode(input) as List();

Related

item not removed in list when use list.remove(element) in flutter

I am having trouble removing an item in a list after adding the element.
List<CartItem> _items = [];
FirebaseFirestore? _instance;
void add(BuildContext context, CartItem item) {
_items.add(item);
AuthService authService = Provider.of<AuthService>(context, listen: false);
Map<String, dynamic> cartMap = Map();
_items.forEach((CartItem item) {
cartMap['title'] = (item.product as Product).title;
cartMap['name'] = (item.product as Product).name;
});
_instance = FirebaseFirestore.instance;
_instance!
.collection('cart')
.doc(authService.getCurrentUser()) //need to get logged in account's id
.update({
'cartProduct': FieldValue.arrayUnion([cartMap])
}).then((value) {
print(_items.length);
notifyListeners();
});
}
void remove(BuildContext context, CartItem item) {
_items.remove(item);
AuthService authService = Provider.of<AuthService>(context, listen: false);
Map<String, dynamic> cartMap = Map();
cartMap['title'] = (item.product as Product).title;
cartMap['name'] = (item.product as Product).name;
_instance = FirebaseFirestore.instance;
_instance!.collection('cart').doc(authService.getCurrentUser()).update({
'cartProduct': FieldValue.arrayRemove([cartMap]),
}).then((value) {
print(_items.length);
notifyListeners();
});
}
After I do add(context, widget.product) and print _items.length, the result is 1
However, after I do remove(context, widget.product) and print _items.length, the result is still 1.
Consumer<CartService>(
builder: (context, cart, child) {
Widget renderedButton;
if (cart.isProductAddedToCart(widget.product) == false) {
renderedButton = DefaultButton(
text: "Participate",
press: () {
print(cart.isProductAddedToCart(widget.product));
cartService.add(context, CartItem(product: widget.product));
print(cart.isProductAddedToCart(widget.product));
},
);
} else {
renderedButton = DefaultButton(
text: "Delete",
press: () {
print(cart.isProductAddedToCart(widget.product));
cartService.remove(
context, CartItem(product: widget.product));
print(cart.isProductAddedToCart(widget.product));
},
);
}
return renderedButton;
As in the code above, the remove() method is supposed to remove the same item that was added to the list using the add() method.
Just update the remove() to: (only change _items.remove(item); position)
void remove(BuildContext context, CartItem item) {
AuthService authService = Provider.of<AuthService>(context, listen: false);
Map<String, dynamic> cartMap = Map();
cartMap['title'] = (item.product as Product).title;
cartMap['name'] = (item.product as Product).name;
_instance = FirebaseFirestore.instance;
_instance!.collection('cart').doc(authService.getCurrentUser()).update({
'cartProduct': FieldValue.arrayRemove([cartMap]),
}).then((value) {
/// todo check firebase collection's deletion success first
_items.remove(item);
print(_items.length);
notifyListeners();
});
}
The item you're adding to the list may not be the same instance of the item you're removing. Make sure the item object/class have equality and hashcode implementation to compare the two items properly.
If you don't have control over the object, the following approach can be an easier alternative:
_items.removeWhere((_item) => _item.property == item.property);
^ where property can be the id of the product.

How to save a bool favorite from list of object to Shared Preferences in Flutter

I have a list of items i want if i clicked on any of them his bool favorite equal true using shared pref..
in more details I Have a list of objects with a bool favorite attribute. I Want to store this boolean value to shared pref..
Model Class:
class ZekrModel {
final String zekrTitle;
final String zekrImage;
final String zekrCat;
final Widget screenWidget;
bool isFav;
bool toggleDone() {
isFav = !isFav;
}
}
Provider Class:
class ZekrProvider with ChangeNotifier{
List<ZekrModel> _zekrList = [
ZekrModel(
zekrTitle: 'أذكار المساء',
zekrImage: 'assets/images/sunset.png',
zekrCat: 'Azkar',
screenWidget: AlmasaaScreen(),
),
ZekrModel(
zekrTitle: 'أذكار الصباح',
zekrImage: 'assets/images/sunrise.png',
zekrCat: 'Azkar',
screenWidget: AlsabahScreen(),
)
];
void updateFav(ZekrModel zekrModel) {
zekrModel.toggleDone();
notifyListeners();
}
List<ZekrModel> get favZekr {
return _zekrList.where((element) => element.isFav).toList();
}
}
Usage in UI:
onTap: (){
value.updateFav(zekrIndex);
},
Import the package:
import 'package:shared_preferences/shared_preferences.dart';
Your widget:
class _LoginState extends State<Login> {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Then, just call like that inside any method to set a bool:
final SharedPreferences prefs = await _prefs;
prefs.setBool('logado', true);
prefs.setString('logado_email', people.email);
If you want to retrieve it later:
bool status = prefs.getBool('logado') ?? false;

Flutter - Fill future list from json

I want to fill a list from json.
Future<List<Titles>> fetchTitle() async {
String url = "https://jsonplaceholder.typicode.com/posts";
final response = await http.get(url,headers: {'Content-Type': 'application/json'});
return titlesFromJson(utf8.decode(response.bodyBytes));
How to fill below list using fetchTitle method. I want to add "title" item from json.
final List myLists = [];
Expanded(
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1,
padding: EdgeInsets.only(left: 20, top: 20, right: 20),
children:List.generate(myLists.length, (index) {
return InkWell(
From the official documentation this is the way on how to fetch data from json and convert the response to list of model:
1- create a model for the post
class Post {
int userId;
int id;
String title;
String body;
Post({this.userId, this.id, this.title, this.body});
Post.fromJson(Map<String, dynamic> json) {
userId = json['userId'];
id = json['id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['userId'] = this.userId;
data['id'] = this.id;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
2 - import http package and fetch post from the link https://jsonplaceholder.typicode.com/posts
import 'package:http/http.dart' as http;
Future<List<Post>> fetchPosts(http.Client client) async {
final response = await client
.get('https://jsonplaceholder.typicode.com/posts');
return parsePosts(response.body);
}
3 - Use the method that you define on your model to create a list that contain posts
import 'dart:convert';
List<Post> parsePosts(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}
4 - to make a test that your code work, create a simple async main method that call fetchPosts with the await prefix because fetchPosts return a Future so if you don't use await you will get a future and not the List
void main() async {
List posts = await fetchPosts(http.Client());
// this will print the id and the title of posts
posts.forEach((post) => print('Post id: ${post.id} | Post title: ${post.title}'));
}
I hope this help!
To add the JSON result to a list, you may need to wait for the response and add it to the List. Since fetchTitle() method returns Future<List<Titles>>, when you await for it, you will get a List<Titles> which can be assigned to your myList.
myList = await fetchTitle();
Since we are using await, we may need to mark the method using async keyword.
void main() async {
List myList = [];
myList = await fetchTitle();
print(myList);
}

Flutter: Selected value doesn't display in the dropdown

I'm populating cities name from SQLite database and trying to display as a drop down list. I make it work by following a tutorial, but having a small issue. The selected value is not displayed in dropdown, it keep displaying default hint value. However, I was able to assign and retrieve correct selected value.
Here is my code:
cities.dart
class Cities {
int id;
String name;
Cities(this.id, this.name);
Cities.fromMap(Map<String, dynamic> json) {
this.id = json["id"];
this.name = json["name"];
}
Map<String, dynamic> toMap() => {
'id': null,
'name': name,
};
}
Function that retrieve and returns value from db:
Future<List<Cities>> getCitiesList() async {
Database db = await instance.database;
final citiesData = await db.query('cities');
if (citiesData.length == 0) return null;
List<Cities> citiesList = citiesData.map((item) {
return Cities.fromMap(item);
}).toList();
return citiesList;
}
The code which builds drop down, inside Widget build:
//these are defined above in the code
Cities _city;
final databaseHelper = DatabaseHelper.instance;
FutureBuilder<List<Cities>>(
future: databaseHelper.getCitiesList(),
builder: (BuildContext context, AsyncSnapshot<List<Cities>> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<Cities>(
items: snapshot.data
.map((city) => DropdownMenuItem<Cities>(
child: Text(city.name),
value: city,
))
.toList(),
onChanged: (Cities value) {
setState(() {
_city = value;
});
},
isExpanded: true,
// value: _city, //uncommenting this line breaks the layout
hint: Text('Select City'),
);
},
),
Error in the console:
'package:flutter/src/material/dropdown.dart': Failed assertion: line 620 pos 15: 'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not true.
Un-commenting this value: _city, add same error in display (displays error 8 times, instead of dropdown list).
Questions:
How can I fix this issue?
How can I set default value from the list? (which will be selected by default)
You can do it in simple way, just create a simple list of strings and pass that list to dropdown menu.
Here's how:
Update your getCitiesList() function:
Future<List<String>> getCitiesList() async {
Database db = await instance.database;
final citiesData = await db.query(tblCities);
if (citiesData.length == 0) return null;
return citiesData.map((Map<String, dynamic> row) {
return row["name"] as String;
}).toList();
}
Add this inside your form page:
//initialize these at top
List<String> _citiesList = <String>[];
String _city;
void _getCitiesList() async {
final List<String> _list = await databaseHelper.getCitiesList();
setState(() {
_citiesList = _list;
});
}
Call _getCitiesList(); inside initState().
Add this inside your build method:
DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: _city,
items: _citiesList.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (String newValue) {
setState(() {
_city = newValue;
});
},
)),

Flutter + AWS: It always gives broken pipe error

I'm trying to compare faces with AWS rekognition API. but somehow I'm getting "broken pipe" error all the time. There is no problem on aws keys and photos. I'm trying to get more info from http.post but It just says "broken pipe", it doesn't give any detail, unfortunately.
Scenario;
User takes 2 photos (working)
on second taken, I will parse images to bytes (working)
send bytes with standard request to aws API (doesn't work)
I changed the image quality to the lowest as well, but It didn't help.
Main.dart code
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'testa.dart';
import 'package:path_provider/path_provider.dart';
List<CameraDescription> cameras;
Future<void> main() async {
cameras = await availableCameras();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
CameraController controller;
#override
void initState() {
super.initState();
controller = CameraController(cameras[0], ResolutionPreset.low);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
Future<String> _checkImage(String filePath, String secondPath) async {
File sourceImagefile, targetImagefile; //load source and target images in those File objects
String accessKey, secretKey, region ; //load your aws account info in those variables
print(filePath);
print(secondPath);
targetImagefile = File(filePath);
sourceImagefile = File(secondPath);
print(targetImagefile.existsSync());
print(sourceImagefile.existsSync());
accessKey = '';
secretKey = '';
region = 'eu-west-1';
RekognitionHandler rekognition = new RekognitionHandler(accessKey, secretKey, region);
String labelsArray = await rekognition.compareFaces(sourceImagefile, targetImagefile);
return labelsArray;
}
Widget cameraPart() {
if (!controller.value.isInitialized) {
return Container();
}
return AspectRatio(
aspectRatio:
controller.value.aspectRatio,
child: CameraPreview(controller));
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: cameraPart(),
floatingActionButton: FloatingActionButton(
onPressed: takePhoto,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Future<String> get360PhotoFolder() async {
final Directory appFolder = await getAppFolder();
final String dirPath = '${appFolder.path}/photos360';
await Directory(dirPath).create(recursive: true);
return dirPath;
}
String firstPath = '';
String secondPath = '';
Future<bool> takePhoto() async {
final String dirPath = await get360PhotoFolder();
final String filePath = '$dirPath/${timestamp()}_test.jpg';
try {
debugPrint('photo taken - $filePath');
await controller.takePicture(filePath);
setState(() {
if (firstPath == '') {
print('a');
firstPath = filePath;
}else if (secondPath == '') {
print('b');
secondPath = filePath;
_checkImage(firstPath, secondPath).then((value) {
print(value);
}).catchError((error) {
print(error);
});
firstPath = '';
secondPath = '';
}
});
} on CameraException catch (e) {
print([e.code, e.description]);
return true;
}
return false;
}
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
Future<Directory> getAppFolder() async =>
await getApplicationDocumentsDirectory();
}
AWS rekognition code
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:intl/intl.dart';
import 'testb.dart';
class RekognitionHandler {
final String _accessKey, _secretKey, _region;
RekognitionHandler(this._accessKey, this._secretKey, this._region);
Future<String> _rekognitionHttp(String amzTarget, String body) async {
String endpoint = "https://rekognition.$_region.amazonaws.com/";
String host = "rekognition.$_region.amazonaws.com";
String httpMethod = "POST";
String service = "rekognition";
var now = new DateTime.now().toUtc();
var amzFormatter = new DateFormat("yyyyMMdd'T'HHmmss'Z'");
String amzDate =
amzFormatter.format(now); // format should be '20170104T233405Z"
var dateFormatter = new DateFormat('yyyyMMdd');
String dateStamp = dateFormatter.format(
now); // Date w/o time, used in credential scope. format should be "20170104"
int bodyLength = body.length;
String queryStringParamters = "";
Map<String, String> headerParamters = {
"content-length": bodyLength.toString(),
"content-type": "application/x-amz-json-1.1",
"host": host,
"x-amz-date": amzDate,
"x-amz-target": amzTarget
};
String signature = Signature.generateSignature(
endpoint,
service,
_region,
_secretKey,
httpMethod,
now,
queryStringParamters,
headerParamters,
body);
String authorization =
"AWS4-HMAC-SHA256 Credential=$_accessKey/$dateStamp/$_region/$service/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-target, Signature=$signature";
headerParamters.putIfAbsent('Authorization', () => authorization);
//String labelsArray = "";
StringBuffer builder = new StringBuffer();
try {
HttpClient httpClient = new HttpClient();
httpClient.connectionTimeout = Duration(minutes: 10);
HttpClientRequest request = await httpClient.postUrl(Uri.parse(endpoint));
request.headers.set('content-length', headerParamters['content-length']);
request.headers.set('content-type', headerParamters['content-type']);
request.headers.set('host', headerParamters['host']);
request.headers.set('x-amz-date', headerParamters['x-amz-date']);
request.headers.set('x-amz-target', headerParamters['x-amz-target']);
request.headers.set('Authorization', headerParamters['Authorization']);
request.write(body);
HttpClientResponse response = await request.close();
await for (String a in response.transform(utf8.decoder)) {
builder.write(a);
}
} catch (e) {
print(e);
}
return Future.value(builder.toString());
}
Future<String> compareFaces(
File sourceImagefile, File targetImagefile) async {
try {
List<int> sourceImageBytes = sourceImagefile.readAsBytesSync();
String base64SourceImage = base64Encode(sourceImageBytes);
List<int> targetImageBytes = targetImagefile.readAsBytesSync();
String base64TargetImage = base64Encode(targetImageBytes);
String body =
'{"SourceImage":{"Bytes": "$base64SourceImage"},"TargetImage":{"Bytes": "$base64TargetImage"}}';
String amzTarget = "RekognitionService.CompareFaces";
String response = await _rekognitionHttp(amzTarget, body);
return response;
} catch (e) {
print(e);
return "{}";
}
}
}