I have my model for json, service to get api
I just dont know how to get image like this like this
from this json from this
the Ipone Mega is the carousel slider(4 images in json link), below the other is just column
if you could show it in carousel Slider i will be very grateful to you
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_work/apiService/fetch_data.dart';
import 'package:my_work/apiService/phone.dart';
class CarouselSliderData extends StatefulWidget{
const CarouselSliderData({super.key});
#override
State<CarouselSliderData> createState() => CarouselSliderDataState();
}
class CarouselSliderDataState extends State<CarouselSliderData> {
Phone? info;
#override
void initState() {
DioService.getDataMocky(
url:'https://run.mocky.io/v3/654bd15e-b121-49ba-a588-960956b15175'
).then((value) async {
if(value != null){
setState((){
info = value!;
});
}
}).catchError(
(value) => (value),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image(image:)
],
);
}
}
Step 1: get the json from API. I call this variable is
Map<String, dynamic> json;
Step 2: As you can see, "home_store" of your json is a list of phones. Therefore, you create a model class called PhoneModel like this:
class PhoneModel {
int id;
bool isNew;
String title;
String subtitle;
String picture;
bool isBuy;
/// constructor
PhoneModel({this.id ...});
/// from json to class model
PhoneModel.fromJson(Map<String, dynamic> json) {
this.id = json["id"];
this.isNew = json["is_new"];
...
}
}
Then do like this to catch the list of items:
List<PhoneModel> listPhones = List<PhoneModel>.from(
(json['home_store'] as List).map((e) => PhoneModel.fromJson(e)),
);
Now your list of phone is variable listPhones. Url is field picture. Do Image.network or anythings else... Good luck!
Related
I just want to get a weather forecast data from the Internet. I wrote this code below but every time I got the error:
A non-null String must be provided to a Text widget
For some reason I could not take decoded json data
import 'package:flutter/material.dart';
import 'network.dart';
class HomePage extends StatefulWidget {
static String id;
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Map<String,dynamic> currentPositionWeatherData;
String temperature;
String weatherDescription;
String name;
void initState(){
super.initState();
getCurrentLocationWeather();
updateUI();
}
void getCurrentLocationWeather()async{
currentPositionWeatherData=await NetworkHelperForWeatherInfo().getCurrentPositionWeatherData();
}
void updateUI()async{
setState(() {
weatherDescription = currentPositionWeatherData["weather"][0]["description"];
temperature = currentPositionWeatherData["main"]["temp"];
name = currentPositionWeatherData["name"];
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.black,
child: Text(
temperature,
),
),
);
}
}
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart';
const openWeatherURL="http://api.openweathermap.org/data/2.5/weather";
const apikey="57aad03f4e48ca815bb1184e74624f46";
class NetworkHelperForWeatherInfo{
Future getCurrentPositionWeatherData()async{
Position position = await Geolocator.getCurrentPosition();
Response response = await get("$openWeatherURL?lat=${position.latitude}&lon=${position.latitude}&appid=$apikey");
if(response.statusCode ==200){
String currentPositionWeatherData = response.body;
return jsonDecode(currentPositionWeatherData);
}
else{
return response.statusCode;
}
}
}
import 'package:flutter/material.dart';
import 'homepage.dart';
import 'package:geolocator/geolocator.dart';
class LocationFinder{
bool serviceEnabled;
LocationPermission permission;
Future<Position> determineCurrentPosition()async{
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if(serviceEnabled != true){
return Future.error("Location services are disabled");
}
permission = await Geolocator.checkPermission();
if (permission==LocationPermission.deniedForever) {
return Future.error("Location permissions are permantly denied,we cannot request permissions.");
}
if (permission == LocationPermission.denied){
permission = await Geolocator.requestPermission();
if(permission != LocationPermission.whileInUse &&
permission != LocationPermission.whileInUse){
return Future.error("Location permission are denied/ actual value:$permission");
}
}
Position position =await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
return position;
}
}
child: Text(
temperature ?? 'waiting data...',
)
When _HomePageState State widget is first built, temperature variable will be null (until data is retrieved and the widget rebuilt through setState call). A null value isn't allowed by the Text widget which asserts the text value not be null.
The above change will supply the text waiting data... when temperature is null.
I am very new to programming and I am trying to pass a variable (jsonData) from a future to another future in a different class, so the data from the variable can be stored in a database. Dont be confused, I am using an API for getting the neccessary data, this works perfectly fine. Any tips how I can access the variable jsonData to insert the data?
//first class gets the json data
class getJSONData {
Future<void> makeRequest() async {
var url = "some url";
Map inputData = {
"Password": example,
"SQL": sql query,
"db_server": "server",
"db_table": "table",
};
var body = json.encode(inputData);
var putRequest = await http.put(
Uri.encodeFull(url), headers: {"Content-Type": "application/json"},
body: body);
//this variable has to be stored
var jsonData = json.decode(putRequest.body);
}
}
//data needs to be inserted here
class Database {
Future<void> insertJSON() async {
db = await openDatabase(
join(await getDatabasesPath(), tableName),
onCreate: (db, version) {
return db.execute('''
INSERT INTO $tableName(column1, column2, etc) VALUES (${jsonData["Records].data1}, ${jsonData["Records].data2}, etc)
''');
}
);
}
}
below i am showing you how to pass data between two screens :
Screen 1 :
class HomeScreenTopContainer extends StatefulWidget {
#override
_HomeScreenTopContainerState createState() => _HomeScreenTopContainerState();
}
class _HomeScreenTopContainerState extends State<HomeScreenTopContainer> {
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Inkwell(onTap:(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ParentLanding(parameter:"pass your value here")),
);
},child:Text("Tap Here and pass data")),
],
);
}
}
Screen 2 :
class ParentLanding extends StatefulWidget {
String parameter;
ParentLanding({Key key,String parameter}) : super(key: key,parameter:parameter);
#override
_ParentLandingState createState() => _ParentLandingState();
}
class _ParentLandingState extends State<ParentLanding> {
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Inkwell(onTap:(){
// you can use this parameter like this.
},child:Text(**Widget.parameter**)),
],
);
}
}
You have many options.
I'll suggest you one.
Change the signatures of both methods.
Example
Your HttpClient class
Future<Map<String, dynamic>> makeRequest() async {
// ... your code
var jsonData = json.decode(putRequest.body);
return jsonData;
}
Your DB Class
Future<void> insertJSON(Map<String, dynamic> jsonData) async {
db = await openDatabase(
join(await getDatabasesPath(), tableName),
onCreate: (db, version) {
return db.execute('''
INSERT INTO $tableName(column1, column2, etc) VALUES
(${jsonData["Records].data1}, ${jsonData["Records].data2}, etc)
''');
}
);
}
Use a third Class/object/method that make the call to the api, take the result and pass it to the db class:
main() async {
HttClient http = HttpClient();
Database db = Database();
final json = await http.makeRequest();
await db.insertJSON(json);
}
Easiest way to pass any value is using an argument.
Value can be send as:
Keys.navKey.currentState.pushNamed(
Routes.gameViewScreen, arguments: jsonData );
In another class it can be retrieved as :
var jsonData = ModalRoute.of(context).settings.arguments;
I am getting data as Future from my json API. And use my Flutter Mobile app.
Here is my code for getting data from API-
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
Future<List<Book>> fetchBooks(http.Client client) async {
final response =
await client.get('json URL');
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parseBooks, response.body);
}
// A function that converts a response body into a List<Photo>.
List<Book> parseBooks(String responseBody) {
final parsed = jsonDecode(responseBody).cast<String, dynamic>();
return parsed['data'].map<Book>((json) => Book.fromJson(json)).toList();
}
class Book {
final String name;
final String author;
final String genreClass;
final String pdf;
final int category;
Book({
this.name,
this.author,
this.genreClass,
this.pdf,
this.category,
});
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
name: json['name'] as String,
pdf: json['pdf'] as String,
author: json['author'] as String,
genreClass: json['genre_class'] as String,
category: json['category'] as int,
);
}
}
But I want to get it as Stream.Please someone help me, how can I convert my code from Future to Stream ?
Abir Ahsan try this, call(use) your function like this : fetchBooks(client).asStream()...
If you're intend to get steam with your builder function is called. You will need to declare a StreamController, it creates a simple stream that can be listened to and you basically push streams of events to the stream, using the sink. A simple snippet can help in terms of displaying a ticking crypto price every 3 seconds:
StreamController<DataModel> _streamController = StreamController();
#override
void dispose() {
// stop streaming when app close
_streamController.close();
}
#override
void initState() {
// TODO: implement initState
super.initState();
// A Timer method that run every 3 seconds
Timer.periodic(Duration(seconds: 3), (timer) {
getCryptoPrice();
});
}
// a future method that fetch data from API
Future<void> getCryptoPrice() async{
var url = Uri.parse('https://api.nomics.com/v1/currencies/ticker?key=your_api_key&ids=DOGE');
final response = await http.get(url);
final databody = json.decode(response.body).first;
DataModel dataModel = new DataModel.fromJson(databody);
// add API response to stream controller sink
_streamController.sink.add(dataModel);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder<DataModel>(
stream: _streamController.stream,
builder: (context,snapdata){
switch(snapdata.connectionState){
case ConnectionState.waiting: return Center(child: CircularProgressIndicator(),);
default: if(snapdata.hasError){
return Text('Please Wait....');
}else{
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${dataModel.name}',style: TextStyle(fontSize: 25),),
SizedBox(height: 20,),
SvgPicture.network('${dataModel.image}',width: 150,height: 150,),
SizedBox(height: 20,),
Text('\$${dataModel.price}',style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold),)
],
),
);
}
}
},
),
),
);
}
More about the code here: https://protocoderspoint.com/flutter-dart-stream-basic-example-fetch-crypto-currency-api-data/
You can Learn more: using these references
https://dart.dev/articles/libraries/creating-streams#creating-a-stream-from-scratch
https://api.dart.dev/stable/2.16.2/dart-async/StreamController-class.html
I am having the nested json where I want parse the worksheetData and display the list of worksheetdata in separate cards. I have tried used online tool parse but when I print the data it throws an error called "type 'List' is not a subtype of type 'Map"
#Update
Below is the home.dart file where I am getting the data error
Home.dart
class WorkSheet extends StatefulWidget {
const WorkSheet({Key key}) : super(key: key);
#override
_WorkSheetState createState() => new _WorkSheetState();
}
class _WorkSheetState extends State<WorkSheet> {
Future<String> loadSheetDataFromAssets() async {
return await DefaultAssetBundle.of(context)
.loadString('assets/example.json');
}
Future loadSheetData() async {
String jsonString = await loadSheetDataFromAssets();
final jsonResponse = json.decode(jsonString);
SheetData sheetData = new SheetData.fromJson(jsonResponse);
print('PName : ${sheetData.projectName}');
print('Worksheet : ${sheetData.worksheetData}');
print(sheetData);
}
#override
void initState() {
super.initState();
loadSheetData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Work sheet data'),
),
body: FutureBuilder(
future: loadSheetData(),
builder: (context, snapshot){
if(snapshot.data == null){
return Center(child: Text(snapshot.error));
}else{
return Card(child: Text(snapshot.data.toString()));
}
}
)
);
}
}
You could use some external tools to generate your models like quicktype
Or any of the approaches described in the official documentation doc
Make sure your class classes you want to convert fromJson are annotated with #JsonSerializable(). Please follow flutter documentation for this https://flutter.dev/docs/development/data-and-backend/json
This with Autoatically convert all your nested classes that are declared with #JsonSerializable() but if you have to convert a list from Json, you have to write some extra code like this below
Map jsonObject = json.decode(jsonString);
Iterable list = json.decode(jsonObject['worksheetData']);
List<WorksheetData> datasheet = list.map((f) => WorksheetData.fromJson(f)).toList();
What is the best way to serialize a list of data from Firebase? Firebase provides an object with a list of properties for the list which makes it more challenging to come up with a good conversion technique.
How would you serialize this data from Firebase:
{
"-KiRg_F-qC59xxlfZ6ej": {
"first":"Brandon",
"last":"Donnelson"
},
"-KiRgmsISBsJSWfXhrdD": {
"first":"Danny",
"last":"Kirk"
}
}
What I came up with — see _loadData()) —:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Text(
'click',
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _test,
tooltip: 'Increment',
child: new Icon(Icons.add),
),);
}
void _test() {
_loadData();
}
_loadData() async {
String url = 'https://dev-xxxxxxx.firebaseio.com/names.json';
var httpClient = createHttpClient();
var response = await httpClient.read(url);
print('response=' + response);
// response = {
// "-KiRg_F-qC59xxlfZ6ej":{"first":"Brandon","last":"Donnelson"},
// "-KiRgmsISBsJSWfXhrdD":{"first":"Danny","last":"Kirk"}
// }
NamesData namesData = new NamesData(JSON.decode(response));
print("names.len=" + namesData.names.length.toString());
}
}
class NamesData {
final List<NameData> names = new List();
NamesData(Map data) {
data.values.forEach((Map map) => names.add(new NameData.fromJson(map)));
}
}
class NameData {
String first;
String last;
NameData.fromJson(Map map) {
first = map['first'];
last = map['last'];
}
}
I found the JSON decoder has a better method for instantiating classes with the reviver function. This feels much better, but I think I can do better.
_loadData() async {
String url = 'https://dev-xxxxxxx.firebaseio.com/names.json';
var httpClient = createHttpClient();
var response = await httpClient.read(url);
print('response=' + response);
// response = {
// "-KiRg_F-qC59xxlfZ6ej":{"first":"Brandon","last":"Donnelson"},
// "-KiRgmsISBsJSWfXhrdD":{"first":"Danny","last":"Kirk"}
// }
var extendedJson = new JsonCodec(reviver: _reviver);
var o = extendedJson.decode(response);
print('end');
}
// https://github.com/dart-lang/sdk/blob/master/tests/lib/convert
// /json_toEncodable_reviver_test.dart
_reviver(key, value) {
if (value != null && value is Map && key.toString().contains("-")) {
return new NameData2(value);
}
return value;
}
}
class NameData2 {
String first;
String last;
NameData2(Map map) {
first = map['first'];
last = map['last'];
}
}
I personally like writing a tiny Codec sometimes:
DartPad example
import 'dart:convert';
void main() {
final decoder = const FirebaseNamesDecoder();
print(decoder.convert(exampleFirebaseData));
}
class NamedData {
final String id;
final String firstName;
final String lastName;
const NamedData(this.id, this.firstName, this.lastName);
#override
String toString() => '$NamedData {$id: $firstName $lastName}';
}
class FirebaseNamesDecoder extends Converter<Map, Iterable<NamedData>> {
const FirebaseNamesDecoder();
#override
Iterable<NamedData> convert(Map<String, Map> raw) {
return raw.keys.map((id) => new NamedData(id, raw[id]['first'], raw[id]['last']));
}
}
final exampleFirebaseData = {
"-KiRg_F-qC59xxlfZ6ej": {
"first":"Brandon",
"last":"Donnelson"
},
"-KiRgmsISBsJSWfXhrdD": {
"first":"Danny",
"last":"Kirk"
}
};
Results in:
(
NamedData {-KiRg_F-qC59xxlfZ6ej: Brandon Donnelson},
NamedData {-KiRgmsISBsJSWfXhrdD: Danny Kirk}
)
Dart 2 needs modification to the overridden method:
Iterable<NamedData> convert(Map<dynamic,dynamic> raw) {
return raw.keys
.map((id) => new NamedData(id, raw[id]['first'], raw[id]['last']));
}
Serializing JSON manually using dart:convert
Basic JSON serialization in Flutter is very simple. Flutter has a built-in dart:convert library which includes a straightforward JSON encoder and decoder.
The following sample JSON implements a simple user model.
{"name":"John Smith","email":"john#example.com"}
With dart:convert, you can serialize this JSON model in two ways.
1) Serializing JSON inline
Map<String, dynamic> user = jsonDecode(jsonString);
print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');
2) Serializing JSON inside model classes
class User
{
final Stringname;
final Stringemail;
User(this.name,this.email);
User.fromJson(Map<String,dynamic>json):name=json['name'],email=json['email'];
Map<String,dynamic>toJson()=>
{
'name':name,
'email':email,
};
}
The responsibility of the decoding logic is now moved inside the model itself. With this new approach, you can decode a user easily.
Map userMap = jsonDecode(jsonString);
var user = User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');
I would recommend using json_serializable it is developed by google developers and it can handle the boilerplate code easily.