i want to fetch data withour using future, can someone help me to convert it ? direct using listview.builder without using future builder. and how can i post it ? i already try it for a couple days and stuck here. please explain it too
thank you
import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:latihan_dio/src/features/home/domain/user.dart';
import '../../../../dio_client.dart';
class myHomepage extends StatefulWidget {
const myHomepage({Key? key}) : super(key: key);
#override
State<myHomepage> createState() => _myHomepageState();
}
class _myHomepageState extends State<myHomepage> {
// List<User> users = [];
var selectedIndex = 0;
#override
void initState() {
super.initState();
// fetchData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<User>>(
future: fetchData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading....');
default:
// if (snapshot.hasError) {
// return Text('Error: ${snapshot.error}');
// } else {
List<User>? data = snapshot.data;
return ListView.builder(
itemBuilder: (context, index) {
return Column(children: [
Text(data![index].firstName!),
]);
},
itemCount: data?.length,
);
}
}
// },
),
));
}
Future<List<User>> fetchData() async {
var Response = await DioClient().apiCall(
url: 'https://reqres.in/api/users?page=2',
requestType: RequestType.GET,
// queryParameters: {},
);
if (Response.statusCode == 200) {
List<dynamic> listUser = Response.data['data'];
List<User> users = listUser.map((e) => User.fromJson(e)).toList();
return users;
} else {
return [];
}
}
}
// Future<void> fetchData() async {
// var Response = await DioClient().apiCall(
// url: 'https://reqres.in/api/users?page=2',
// requestType: RequestType.GET,
// // queryParameters: {},
// );
// // List<dynamic> listUser = Response.data;
// // OR
// List<dynamic> listUser =
// Response.data['data']; // if you want to access data inside it
// List<User> users = listUser.map((e) => User.fromJson(e)).toList();
// }
as u can see here is my homepage. i make a freeze class and using dio client here.
Try this
class _myHomepageState extends State<myHomepage> {
List<User> user = [];
bool isLoading = false;
#override
void initState() {
initFunction();
super.initState();
}
void initFunction() async {
setState((){
isLoading= true;
})
user = await fetchData();
setState((){
isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: isLoading
? CircularProgressIndicator()
: ListView.builder(
itemBuilder: (context, index) {
return Column(children: [
Text(user[index].firstName!),
]);
},
itemCount: user.length,
);
),
));
}
Future<List<User>> fetchData() async {
var Response = await DioClient().apiCall(
url: 'https://reqres.in/api/users?page=2',
requestType: RequestType.GET,
// queryParameters: {},
);
if (Response.statusCode == 200) {
List<dynamic> listUser = Response.data['data'];
List<User> users = listUser.map((e) => User.fromJson(e)).toList();
return users;
} else {
return [];
}
}
}
Related
I am trying to show data from api and while loading data , there should be shown a circularprogressindicator,
but when I start app..it directly showing data instead of circularprogressindicator
class _HomeScreenState extends State<HomeScreen> {
bool isloading = false;
var maplist ;
Future<void> fetchdata() async {
setState(() {
isloading=true;
});
var resp =
await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
maplist = json.decode(resp.body);
setState(() {
isloading = false;
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
fetchdata();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: MyBody(),
));
}
MyBody() {
return isloading==true ? Center(child: CircularProgressIndicator()) : ListView.builder(
itemCount: maplist.length,
itemBuilder: (context,index){
return Container(
padding: EdgeInsets.all(8.0),
child: Text(maplist[index]['title']));
});
}
}
It's actually working perfectly fine, it shows too fast because it is receiving data quickly(+ could be cache case).
If you like to have more delay you can add, future.delay which is unnecessary
Future<void> fetchdata() async {
setState(() {
isloading = true;
});
var resp =
await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
maplist = json.decode(resp.body);
// get more delay
await Future.delayed(Duration(seconds: 2));
setState(() {
isloading = false;
});
}
A better of way of handling future method with FutureBuilder
Try the following code:
class _HomeScreenState extends State<HomeScreen> {
var maplist;
Future<void> fetchdata() async {
var resp =
await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
setState(() {
maplist = json.decode(resp.body);
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: MyBody(),
));
}
MyBody() {
return FutureBuilder(
future: fetchdata(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
return ListView.builder(
itemCount: maplist.length,
itemBuilder: (context,index){
return Container(
padding: EdgeInsets.all(8.0),
child: Text(maplist[index]['title']));
});
}
}
}
You need to use FutureBuilder, it is not good to use async function in initState, try this:
FutureBuilder<List<Map<String,dynamic>>>(
future: fetchdata(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List<Map<String,dynamic>> data = snapshot.data ?? [];
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Text(data[index]['title']));
});
}
}
},
),
also you need to change your fetchdata to this:
Future<List<Map<String,dynamic>>> fetchdata() async {
var resp =
await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
return json.decode(resp.body);
}
Try this one,set isloading default true
class _HomeScreenState extends State<HomeScreen> {
bool isloading = true;
var maplist ;
Future<void> fetchdata() async {
var resp =
await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
maplist = json.decode(resp.body);
setState(() {
isloading = false;
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
fetchdata();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: MyBody(),
));
}
MyBody() {
return isloading ? Center(child: CircularProgressIndicator()) : ListView.builder(
itemCount: maplist.length,
itemBuilder: (context,index){
return Container(
padding: EdgeInsets.all(8.0),
child: Text(maplist[index]['title']));
});
}
}
You can use like that
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
bool isloading = false;
var maplist;
Future<void> fetchdata() async {
setState(() {
isloading = true;
});
var resp = await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
maplist = json.decode(resp.body);
setState(() {
isloading = false;
});
}
#override
void initState() {
super.initState();
fetchdata();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: isloading ? const CircularProgressIndicator() : const MyBody(),
);
}
}
class MyBody extends StatelessWidget {
const MyBody({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
//Write your code here
);
}
}
I have a piece of code to scan and read device information. I have printed the elements in the list in onScan function, however I don't know how to get that information and put it in a listview.
Can someone help me?
List<Data> listDevice = [];
Future<void> getData() async {
var apiEndpoint = TTAPI.shared;
await apiEndpoint.devideScan(((data) => onScan(data)));
}
Future<void> onScan(dynamic data) async {
var dataResponse = DataResponse.fromJson(data);
print(dataResponse.toJson());
List<dynamic> dt = jsonDecode(jsonEncode(dataResponse.data).toString());
dt.forEach((element) {
var item = Data.fromJson(element);
print(item.modelName);
listDevice.add(item);
});
var connectRequest = {
'serialNumber': 'DEVICE_SERIAL',
'modelName': 'DEVICE_MODEL',
'ipAddr': 'DEVICE_IP'
};
var apiEndpoint = TTAPI.shared;
await apiEndpoint.connectDevice(connectRequest);
}
Future<List<Data>> getList() async {
return listDevice;
}
You can see more of my code here: https://docs.google.com/document/d/1ntxaDpyNCLD1MyzJOTmZsrh7-Jfim8cm0Va86IQZGww/edit?usp=sharing
As for the current code structure, listDevice is populated inside Future. So you can call setState to update the UI after getting the list at the end of onScan.
Future<void> getData() async {
var apiEndpoint = TTAPI.shared;
await apiEndpoint.devideScan(((data) => onScan(data)));
setState((){});
}
But it would be great to use FutureBuilder and return list from getData.
Current question pattern example
class TextFW extends StatefulWidget {
const TextFW({super.key});
#override
State<TextFW> createState() => _TextFWState();
}
class _TextFWState extends State<TextFW> {
//for current question way
List<int> listDevice = [];
Future<void> getData() async {
await Future.delayed(Duration(seconds: 2));
/// others async method
listDevice = List.generate(10, (index) => index);
setState(() {}); //here or `getData().then()`
}
#override
void initState() {
super.initState();
getData();
// or this getData().then((value) => setState((){}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: listDevice.length,
itemBuilder: (context, index) => ListTile(
title: Text("${listDevice[index]}"),
),
),
);
}
}
Using FutureBuilder
class TextFW extends StatefulWidget {
const TextFW({super.key});
#override
State<TextFW> createState() => _TextFWState();
}
class _TextFWState extends State<TextFW> {
/// method will provide data by scanning
Future<List<int>> getData() async {
await Future.delayed(Duration(seconds: 2));
return List.generate(10, (index) => index);
}
late final fututre = getData();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<int>>(
future: fututre,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("${snapshot.error}");
}
if (snapshot.hasData) {
final listDevice = snapshot.data;
return ListView.builder(
itemCount: listDevice?.length,
itemBuilder: (context, index) => ListTile(
title: Text("${listDevice![index]}"),
),
);
}
return CircularProgressIndicator();
},
),
);
}
}
class Organization_Api{
static Future<List<dynamic>> getData(
{required String target, String? limit}) async {
try {
var uri = Uri.https(
BASE_URL,
"api/$target",
target == "organizations"
? {
"offset": "0",
"limit": limit,
}
: {});
var response = await http.get(uri);
var data = jsonDecode(response.body);
List tempList = [];
if (response.statusCode != 200) {
throw data["message"];
}
for (var v in data) {
tempList.add(v);
}
return tempList;
} catch (error) {
log("An error occured $error");
throw error.toString();
}
}
static Future<List<Organization>> getAllOrganizations(
{required String limit}) async {
List temp = await getData(
target: "organizations",
limit: limit,
);
return Organization.organizationsToList(temp);
}
static Future<Organization> getOrganizationById({required String id}) async {
try {
var uri = Uri.https(
BASE_URL,
"api/organizations/$id",
);
var response = await http.get(uri);
var data = jsonDecode(response.body);
if (response.statusCode != 200) {
throw data["message"];
}
return Organization.fromJson(data);
} catch (error) {
log("an error occured while getting organization info $error");
throw error.toString();
}
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
static String routeName = "/home";
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Future<List<Organization>>? result ;
void initState(){
result = Organization_Api.getAllOrganizations(limit: '4');
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Organizations", style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
centerTitle: true,
),
body: Padding(
padding: EdgeInsets.all(10.0),
child: Column(
children:
<Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children:<Widget>[
ListView(
shrinkWrap: true,
children:<Widget> [result],
)
],
),
)
],
),
),
);
}
}
class Organization{
final int OrganizationId;
final String OrganizationName;
Organization({required this.OrganizationId,required this.OrganizationName});
factory Organization.fromJson(Map<String,dynamic> json){
return Organization(OrganizationId: json['OrganizationId'], OrganizationName: json['OrganizationName']);
}
Map toJson(){
return{
"OrganizationId": this.OrganizationId,
"OrganizationName": this.OrganizationName,
};
}
static List<Organization> organizationsToList(List organizationToList) {
return organizationToList.map((data) {
return Organization.fromJson(data);
}).toList();
}
}
Error = The element type >'Future<List>?' can't be assigned to the list type 'Widget'.
I just want to check the data coming from the service, but I couldn't find how to do it.
What did I do wrong or what did I miss to list the incoming data?
I shared the screen page and the codes on how I got the information from the service.
Your Organization_Api.getAllOrganizations provide a future. You can use FutureBuilder.
class _HomeScreenState extends State<HomeScreen> {
Future<List<Organization>>? myFuture;
#override
void initState() {
myFuture = Organization_Api.getAllOrganizations(limit: '4');
super.initState();
}
And on future builder
FutureBuilder<List<Organization>?>(
future: myFuture,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
return ListView(
shrinkWrap: true,
//children: snapshot.data!, // when `Organization` is a widget
children:// when `Organization` is a data model class
snapshot.data!.map((e) => Text(e.toString())).toList(),
);
}
return CircularProgressIndicator();
},
)
Also check Randal L. Schwartz video on using Future
When i refresh the data isnt fetching new data please help me
This is my method to fetch data from news org api
Future<List<Article>> getApi() async {
Response response = await get(Uri.parse(
"https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=apikey"));
if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body);
List<dynamic> body = json['articles'];
List<Article> article = body.map((e) => Article.fromJson(e)).toList();
return article;
} else {
throw ("cant get the articles");
}
}
this is my builder to show data
body: FutureBuilder<List<Article>>(
future: futureWords,
builder: (context, AsyncSnapshot<List<Article>> snap) {
if (snap.hasData) {
List<Article> articles = snap.data!;
return RefreshIndicator(
onRefresh: () {
setState(() {});
return _pullRefresh();
},
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return customListTile(articles[index]);
}),
);
} else {
return Center(child: CircularProgressIndicator());
}
}),
this is my pullrefresh method
Future<List<Article>> _pullRefresh() async {
List<Article> freshWords = await news.getApi();
setState(() {
futureWords = Future.value(freshWords);
});
return futureWords!;
}
May be it'll help you. If not - post your full code)
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
class Test2 extends StatefulWidget {
const Test2({Key? key}) : super(key: key);
#override
_Test2State createState() => _Test2State();
}
class Article {
String header='';
}
class _Test2State extends State<Test2> {
Future <List<Article>>? futureWords;
#override
void initState() {
super.initState();
_getNews();
}
_getNews() async {
var response = await http.get(Uri.parse(
"https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=aa20aef042a14de5b99a7f7d32952504"));
if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body);
List<dynamic> body = json['articles'];
//List<Article> articles = body.map((e) => Article.fromJson(e)).toList();
List<Article> articles = [];
for (var el in body) {
Article article = Article();
article.header = el['title'];
articles.add(article);
}
articles.shuffle();
setState(() {
futureWords = Future.value(articles);
});
} else {
throw ("cant get the articles. statusCode ${response.statusCode}");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Article>>(
future: futureWords,
builder: (context, AsyncSnapshot<List<Article>> snap) {
if (snap.hasData) {
List<Article> articles = snap.data!;
return
RefreshIndicator(
onRefresh: () {
_getNews();
return futureWords!;
},
child: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(title: Text(articles[index].header));
}),
);
} else {
return Center(child: CircularProgressIndicator());
}
}),
);
}
}
I wanna fetch data from PhpMyAdmin. But i am facing one issue. I can see in the body my data. I am sharing my source code. Thx for helping. And I am working with flutter desktop.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class WarehousePage extends StatefulWidget {
const WarehousePage({Key key}) : super(key: key);
#override
_WarehousePageState createState() => _WarehousePageState();
}
class _WarehousePageState extends State<WarehousePage> {
List data = [];
#override
void initState() {
fetchData();
super.initState();
}
void fetchData() async {
final response =
await http.get(Uri.parse('url/getdata.php'));
data = json.decode(response.body);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text(data[index]['productName']),
),
),
);
}
}
Update my code but still same. What is wrong? I have not any model class. I am see my data in the body and debug console. But i cant write it in the listview.
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class WarehousePage extends StatefulWidget {
const WarehousePage({Key key}) : super(key: key);
#override
_WarehousePageState createState() => _WarehousePageState();
}
class _WarehousePageState extends State<WarehousePage> {
List data = [];
#override
void initState() {
fetchData();
super.initState();
}
Future<List> fetchData() async {
var jsonResponse;
try {
var url = Uri.parse('https://rul/getdata.php');
var response = await http.get(url).timeout(const Duration(seconds: 20));
if (response.statusCode == 200) {
jsonResponse = json.decode(response.body);
if (jsonResponse != null) {
return (json.decode(response.body) as List)
.map((data) => (data))
.toList();
}
}
} on SocketException catch (e) {
print(e);
} catch (e) {
print(e);
}
return jsonResponse;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text(data[index]['productName']),
),
),
);
}
}
static Future<List<SomeModel>> fetchQuizTest() async {
var jsonResponse;
try {
var url = Uri.parse(url');
var response = await http.get(url).timeout(const Duration(seconds: 20));
if (response.statusCode == 200) {
jsonResponse = json.decode(response.body);
if (jsonResponse != null) {
return (json.decode(response.body) as List)
.map((data) => new SomeModel.fromJson(data))
.toList();
}
}
} on SocketException catch (e) {
print(e);
} catch (e) {
print(e);
}
return jsonResponse;
}