How to Pass parameters in url. in flutter - flutter

I want to pass some parameters in flutter url
here is example:
parameters are source , destination , type, fare.
url is http://localhost:9000/api/bmrc/fare/source/destination/fare/type
url need to send http://localhost:9000/api/bmrc/fare/1/17/2/SJT
(workinng in postman/thunderclient)
I tried after passing these parameters in body but its not worked for me

They are Path Parameters, not body JSON.
You can call your API like this:
callAPI(int source,int destination,int fare,String type){
String _url= "http://localhost:9000/api/bmrc/fare/${source}/${destination}/${fare}/${type}";
... //call your API with _url
}
You can change the param types as you like

its a POST Call:
To get data from from your url, try this.
Here is the sample Example:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<Post> post;
#override
void initState() {
super.initState();
post = fetchPost();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter REST API Example',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter REST API Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, abc) {
if (abc.hasData) {
return Text(abc.data.title);
} else if (abc.hasError) {
return Text("${abc.error}");
}
// By default, it show a loading spinner.
return CircularProgressIndicator();
},
),
),
),
);
}
}
Future<Post> fetchPost() async {
final response = await http.get('Give your JSON file web link.');
if (response.statusCode == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load post');
}
}
class Post {
final int userId;
final int id;
final String title;
final String description;
Post({this.userId, this.id, this.title, this. description});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
description: json[' description'],
);
}
}

Related

How to do HTTP GET on an API link that contains nested array in Dart/Flutter?

I am trying to create an app that shows the current data in my web server using the Flutter plugin. I want to access the details of my web server using HTTP GET.
I followed this guide (https://docs.flutter.dev/cookbook/networking/fetch-data) and used the code as well but I can't make it work on my HTTP GET link since it has nested parameters.
Here is the code from the guide:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
const Album({
required this.userId,
required this.id,
required this.title,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
Here is my link by the way: https://api.thingspeak.com/channels/1864145/fields/1.json?results=1
and this is the array it contains
{
"channel":{
"id":1864145,
"name":"channel name",
"description":"description",
"latitude":"0.0",
"longitude":"0.0",
"field1":"first field",
"field2":"second field",
"field3":"third field",
"field4":"fourth field",
"created_at":"2022-09-18T11:53:33Z",
"updated_at":"2022-09-18T12:26:54Z",
"last_entry_id":10742
},
"feeds":[
{"created_at":"2022-12-27T05:34:12Z",
"entry_id":10741,
"field1":"111",
"field2":"4",
"field3":"28",
"field4":"61"
}
]
}
///edit
For those confused, I don't have a code yet since I have no idea how to do it but I tried to replace the variables based on our own parameters and it did not work so I thought there is a different way/code for the nested array parameters.

Flutter http.get is not responding

I used exactly same code from Flutter Documentation to fetch data from internet.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
const Album({
required this.userId,
required this.id,
required this.title,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
It should display data with text widget after getting data, but http.get is not returning and it just keeps showing CircularProgressIndicator like:
I'm using Windows 10, Flutter 3.7.0 stable channel, Dart 2.19.0, http 0.13.5 version. How to fix this?
This could be because you haven't added the interne permissions in you android manifest
<manifest...
...
<uses-permission android:name="android.permission.INTERNET"/>
....
/manifest>

Expected a value of type 'int', but got one of type 'String' flutter

I'm trying to build a simple list in flutter, I based my code of a flutter cookbook https://docs.flutter.dev/cookbook/networking/background-parsing but I tried applying DDD so its separated in different classes.
import 'package:corsiapp/Domain/Course/course.dart';
import 'package:corsiapp/Infraestructure/remote_data_source.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 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.
//3232
// 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.red,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Course>>(
future: RemoteDataSourceImpl(client: http.Client()).getCoursefromAPI(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('An error has occurred!'),
);
} else if (snapshot.hasData) {
return CourseList(course: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
class CourseList extends StatelessWidget {
const CourseList({super.key, required this.course});
final List<Course> course;
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: course.length,
itemBuilder: (context, index) {
return Text(course[index].title);
},
);
}
}
import 'package:equatable/equatable.dart';
import 'package:corsiapp/Domain/Course/lesson.dart';
class Course extends Equatable {
const Course(
{required this.id,
required this.title,
required this.urlImage,
required this.description});
final int id;
final String title;
final String urlImage;
final String description;
factory Course.fromJson(Map<String, dynamic> json) {
return Course(
id: json['id'] as int,
title: json['title'] as String,
urlImage: json['urlimage'] as String,
description: json['description'] as String);
}
#override
List<Object?> get props => [id, title, urlImage, description];
}
import 'dart:convert';
import 'package:corsiapp/Domain/Course/course.dart';
import 'package:http/http.dart' as http;
abstract class RemoteDataSource {
Future<List<Course>> getCoursefromAPI();
}
class RemoteDataSourceImpl implements RemoteDataSource {
final http.Client client;
RemoteDataSourceImpl({required this.client});
#override
Future<List<Course>> getCoursefromAPI() async {
final response = await client
.get(Uri.parse('https://638c1e60eafd555746a0b852.mockapi.io/Course'));
if (response.statusCode == 200) {
return parseCourse(response.body);
} else {
print('Serch Local Repository');
throw Exception();
}
}
// A function that converts a response body into a List<Photo>.
List<Course> parseCourse(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Course>((json) => Course.fromJson(json)).toList();
}
}
Using a basic print I captured the error of the snapshot that error being Expected a value of type 'int', but got one of type 'String', in the tutorial they show a list of pictures I wanted to show a list of titles.
the JSON returned from https://638c1e60eafd555746a0b852.mockapi.io/Course indicates that the id is of type String not int
try this:
factory Course.fromJson(Map<String, dynamic> json) {
return Course(
id: int.parse(json['id']),
title: json['title'] as String,
urlImage: json['urlimage'] as String,
description: json['description'] as String,
);
}

Android Studio API response

I basically have everything functioning following this tutorial on how to implement a API in flutter: https://docs.flutter.dev/cookbook/networking/fetch-data. I followed the tutorial but i get an error message "Failed to load Album". My understanding of this is that the server didn't respond with a 200 ok repsonse, but im not sure. I don't know how what the problem is and how i can get it to display the information. The API im using is a car registry, where you can type in a numberplate and get all the details for a vehicle.
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('http://api.nrpla.de/Cz33849?api_token=JjCYzJA0B5FQPPjlWeyUqN3KSuaErwMyrryuQCmX7R6epHagtINaMjxfwaTGGyrl'),
headers: {
});
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final String registration;
final String type;
final String brand;
final String model;
final String version;
final String fuel_type;
final String registration_status;
final int engine_power;
final String doors;
final String leasing_period_start;
final String leasing_period_end;
final String color;
final String body_type;
Album({
required this.registration,
required this.type,
required this.brand,
required this.model,
required this.version,
required this.fuel_type,
required this.registration_status,
required this.engine_power,
required this.doors,
required this.leasing_period_start,
required this.leasing_period_end,
required this.color,
required this.body_type,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
registration: json['registration'],
type: json['type'],
brand: json['brand'],
model: json['model'],
version: json['version'],
fuel_type: json['fuel_type'],
registration_status: json['registration_status'],
engine_power: json['engine_power'],
doors: json['doors'],
leasing_period_start: json['leasing_period_start'],
leasing_period_end: json['leasing_period_end'],
color: json['color'],
body_type: json['body_type'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.registration);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
You have consumed your monthly limit that's why you are not getting data from the API status code is 429

Does stream builder build my widgets again and again without any change in stream?

Stream builder in Flutter is getting recalled. I am not sure why. I believe the problem might be that i have a bloc provider in stream builder. My stream dataBloc.dataStream is not changing, to cause the streambuilder to build again. Not sure, what i am doing wrong. Does stream builder build my widgets again and again without any change in stream. Obviously that's not true! Right?
Widget build(context) {
final DataBloc dataBloc = DataBlocProvider.of(context);
print("dropdown build called again");
// this doesn't print recursively so this is perfect.
// So my build is not getting called again.
return StreamBuilder(
stream: dataBloc.dataStream,
builder: (context, snapshot) {
//ToDo remove prints
print("dropdown ${snapshot.data}");
// there is no change in snapshot.data, however print is getting called recursively. This is bad and wrong
// so my stream builder is getting called again, and this is wrong
String key = dataElement.conditionalField;
String _valueArray = dataElement.conditionalValues.toString();
String conditionalValue =
_valueArray.substring(1, _valueArray.length - 1);
Map<String, String> dataMap = snapshot.hasData ? snapshot.data : {};
bool isVisible = true;
if (key != "" &&
dataMap.containsKey(key) &&
dataMap[key] == conditionalValue.toString()) {
isVisible = true;
} else if (key != "") {
isVisible = false;
}
return Visibility(
child: BlocDropDownProvider(
fieldName: dataElement.key,
dataBloc: dataBloc,
child: Card(
color: Colors.grey[100],
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
label,
new Container(
height: 8.0,
),
dropDown,
],
),
),
),
visible: isVisible? true:false,
);
output on console is :
I/flutter (14422): dropdown {idnumber: 10}
I/flutter (14422): dropdown {idnumber: 10}
I can't really replicate this issue with 1:1 accuracy base from the given details. What I encountered similarly is that build within StreamBuilder is being called again on ConnectionState changes.
Here's a minimal repro using StreamBuilder sending a HTTP request. The HTTP request sample here is based from this Flutter Networking guide.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final streamController = StreamController();
#override
void initState() {
super.initState();
fetchAlbum().then((response) => streamController.add(response));
}
#override
void dispose() {
super.dispose();
streamController.close();
}
#override
Widget build(BuildContext context) {
debugPrint('build');
return StreamBuilder(
stream: streamController.stream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
debugPrint('Stream $snapshot');
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: snapshot.hasData
? Text('Album ${snapshot.data.title}')
: Text('Waiting...'),
),
);
},
);
}
Future<Album> fetchAlbum() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/albums/1');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
class Album {
final int userId;
final int id;
final String title;
Album({this.userId, this.id, this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
Then again, I suggest not being too concerned with build costs as long as the Widgets inside the build is manageable. More details about Flutter best practices are discussed in this doc.