I'm getting this error:
NosuchmethodError: Class 'List' has no instance setter 'state='.
Recevier: Instance(length:0) of ' _GrowableList' Tried calling: state=Instance(lenght:15) of'_GrowableList'
and I don't know where is the problem I can't see any problem in the code.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:quiz2/const/const.dart';
import 'package:sqflite/sqflite.dart';
class Category {
int ID;
String name, image;
Map<String, dynamic> toMap() {
var map = <String, dynamic> {
columnMainCategoryId: ID,
columnCategoryName: name,
columnCategoryImage: image
};
return map;
}
Category();
Category.fromMap(Map<String,dynamic> map) {
ID = map[columnMainCategoryId];
name = map[columnCategoryName];
image = map[columnCategoryImage];
}
}
class CategoryProvider {
Future<Category> getCategoryById(Database db, int id)async {
var maps = await db.query(tableCategoryName,
columns: [
columnMainCategoryId,
columnCategoryName,
columnCategoryImage
], where: "$columnMainCategoryId=?",
whereArgs: [id]);
if(maps.length > 0)
return Category.fromMap(maps.first);
return null;
}
Future<List<Category>> getCategories(Database db) async{
var maps = await db.query(tableCategoryName,
columns: [
columnMainCategoryId,
columnCategoryName,
columnCategoryImage
]);
if(maps.length > 0) return maps.map((category) => Category.fromMap(category)).toList();
return null;
}
}
class CategoryList extends StateNotifier<List<Category>>{
CategoryList(List<Category> state):super(state ?? []);
void addAll(List<Category> category)
{
state.addAll(category);
}
void add(Category category){
state = [
...state,
category,
];
}
}
file const.dart
final db_name = "quiz.db";
final columnMainCategoryId = "ID";
final columnCategoryName = "Name";
final columnCategoryImage = "Image";
final tableCategoryName = "Category";
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:quiz2/screens/home_page.dart';
void main() {
runApp(ProviderScope(child:MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
routes: {
"/homePage": (context) => MyCategoryPage(title: "My Quiz",)
},
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Topics'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pop();
Navigator.pushNamed(context, "/homePage");
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
screens/home_page.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:quiz2/const/state.dart';
import 'package:quiz2/database/category_provider.dart';
import 'package:quiz2/database/db_helper.dart';
class MyCategoryPage extends StatefulWidget {
MyCategoryPage({Key key, this.title}):super(key: key);
final String title;
#override
_MyCategoryPageState createState() => _MyCategoryPageState();
}
class _MyCategoryPageState extends State<MyCategoryPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Category>>(
future: getCategories(),
builder: (context, snapshot){
if(snapshot.hasError)
return Center(child: Text('${snapshot.error}'),);
else if(snapshot.hasData)
{
Category category = new Category();
category.ID = -1;
category.name = "Exam";
snapshot.data.add(category);
return GridView.count(
crossAxisCount: 2,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: snapshot.data.map((category){
return GestureDetector(child: Card(
elevation: 2,
color: category.ID == -1 ? Colors.green : Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: AutoSizeText(
"${category.name}",
style: TextStyle(
color: category.ID == -1 ? Colors.white : Colors.black,
fontWeight: FontWeight.bold
),
maxLines: 1,
textAlign: TextAlign.center,
)
,)
],
),
),);
}).toList(),
);
}
else return Center(child: CircularProgressIndicator(),);
},
)
);
}
Future<List<Category>> getCategories() async {
var db = await copyDB();
var result = await CategoryProvider().getCategories(db);
context.read(categoryListProvider).state = result;
return result;
}
}
db_helper.dart
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:quiz2/const/const.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
Future<Database> copyDB() async{
var dbPath = await getDatabasesPath();
var path = join(dbPath, db_name);
var exists = await databaseExists(path);
if(!exists){
try{
await Directory(dirname(path)).create(recursive:true);
} catch(_){
}
ByteData data = await rootBundle.load(join("assets/db",db_name));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes,data.lengthInBytes);
await File(path).writeAsBytes(bytes, flush:true);
}else{
print("DB already exists!");
}
return await openDatabase(path, readOnly: true);
}
state.dart
import 'package:flutter_riverpod/all.dart';
import 'package:quiz2/database/category_provider.dart';
final categoryListProvider = StateNotifierProvider((ref) => new CategoryList([]));
NosuchmethodError: Class 'List' has no instance setter 'state='.
Recevier: Instance(length:0) of ' _GrowableList'
Tried calling: state=Instance(lenght:15) of'_GrowableList'
In your code, you have
Future<List<Category>> getCategories() async {
var db = await copyDB();
var result = await CategoryProvider().getCategories(db);
context.read(categoryListProvider).state = result;
return result;
}
Here, your context.read(categoryListProvider) is actually of type List.
That's why, when you are calling it like that, it means that you are calling,
[/* some kind of list */].state = result
But, the List class doesn't have a property called state but you are trying to modify it. That's why the error is coming.
Comment out that line and check.
Related
import 'package:flutter/material.dart';
import 'package:sqlflite_demo/screens/product_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: ProductList(),
);
}
}
main.dart
class Product {
int? id;
String? name;
String? description;
double? unitPrice;
Product({this.name, this.description, this.unitPrice});
Product.withId({this.id, this.name, this.description, this.unitPrice});
Map<String,dynamic> toMap(){
var map = Map<String,dynamic>();
map["name"]=name;
map["description"]=description;
map["unitPrice"]=unitPrice;
if(id!=null){
map["id"]=id;
}
return map;
}
Product.fromObject(dynamic o){
this.id = int.tryParse(o["id"]);
this.name=o["name"];
this.description=o["description"];
this.unitPrice = double.tryParse(o["unitPrice"].toString());
}
}
product.dart
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import '../models/product.dart';
class DbHelper {
late Database _db;
Future<Database> get db async {
if (_db == null) {
_db = await initializeDb();
}
return _db;
}
Future<Database> initializeDb() async {
String dbPath = join(await getDatabasesPath(), "etrade.db");
var eTradeDb = await openDatabase(dbPath,version: 1, onCreate: createDb);
return eTradeDb;
}
void createDb(Database db, int version)async {
await db.execute("Create table products(id integer primary key, name text, description text, unitPrice integer)");
}
Future<List<Product>> getProducts() async{
Database db = await this.db;
var result = await db.query("products");
return List.generate(result.length, (i){
return Product.fromObject(result[i]);
});
}
Future<int> insert(Product product)async{
Database db = await this.db;
var result = await db.insert("products", product.toMap());
return result; ////////
}
Future<int> delete(int id)async{
Database db = await this.db;
var result = await db.rawDelete("delete from products where id=$id");
return result;
}
Future<int> update(Product product)async{
Database db = await this.db;
var result = await db.update("products", product.toMap(), where: "id=?",whereArgs: [product.id]);
return result;
}
}
db_Helper.dart
import 'package:flutter/material.dart';
import 'package:sqlflite_demo/data/dbHelper.dart';
import 'package:sqlflite_demo/models/product.dart';
import 'package:sqlflite_demo/screens/product_add.dart';
class ProductList extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return _ProductListState();
}
}
class _ProductListState extends State {
var dbHelper = DbHelper();
late List<Product> products;
int productCount =0;
#override
void initState() {
getProducts();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Ürün Listesi"),
),
body: buildProductList(),
floatingActionButton: FloatingActionButton(
onPressed: (){goToProductAdd();},
child: Icon(Icons.add),
tooltip: "Yeni Ürün Ekle",
),
);
}
ListView buildProductList() {
return ListView.builder(
itemCount: productCount,
itemBuilder: (BuildContext context, int position){
return Card(
color: Colors.pinkAccent,
elevation: 2.0,
child: ListTile(
leading: CircleAvatar(backgroundColor: Colors.black12, child: Text("P"),),
title: Text(products[position].name.toString()),
subtitle: Text(products[position].description.toString()),
onTap: (){},
),
);
});
}
void goToProductAdd() async{
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context)=>ProductAdd()));
if(result!=null){
if(result){
getProducts();
}
}
}
void getProducts() async{
var productsFuture = dbHelper.getProducts();
productsFuture.then((data){
this.products = data;
productCount=data.length;
});
}
}
product_list.dart
import 'package:flutter/material.dart';
import 'package:sqlflite_demo/data/dbHelper.dart';
import '../models/product.dart';
class ProductAdd extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return ProductAddState();
}
}
class ProductAddState extends State {
var dbHelper = DbHelper();
var txtName=TextEditingController();
var txtDescription=TextEditingController();
var txtUnitPrice=TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Yeni Ürün Ekle"),
),
body: Padding(
padding: EdgeInsets.all(30.0),
child: Column(
children: [
buildNameField(),buildDescriptionField(),buildUnitPriceField(),buildSaveButton()
],
),
),
);
}
buildNameField() {
return TextField(
decoration: InputDecoration(labelText: "Ürün Adı"),
controller: txtName,
);
}
buildDescriptionField() {
return TextField(
decoration: InputDecoration(labelText: "Ürün Açıklaması"),
controller: txtDescription,
);
}
buildUnitPriceField() {
return TextField(
decoration: InputDecoration(labelText: "Birim Fiyatı"),
controller: txtUnitPrice,
);
}
buildSaveButton() {
return FlatButton(
child: Text("Ekle"),
onPressed: (){
addProduct();
},
);
}
void addProduct() async{
var result = await dbHelper.insert(Product(name: txtName.text, description: txtDescription.text, unitPrice: double.tryParse(txtUnitPrice.text)));
Navigator.pop(context,true);
}
}
product_add.dart
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field '_db#19320762' has not been initialized.
This is my first project in flutter. and I have an error. can you explain that? Thanks. I dont know what happened
I have built a page which reads the json from recipeURL and I wish for it to display the product_name value in the json file. However for some reason my future fetchData () class isn't being read as none of the text in my if else statement is being displayed. Am I missing a simple oversight here?
EDIT: The main dart file is my main screen. This is where my navbar is created. Users are redirected to other pages when they click on the corresponding icon. Im having trouble passing BarcodePage(title:title); as parameters in my main file,26th line, can be found under Class MyAppState extends State<MyApp> {
My main dart file:
import 'package:flutter/material.dart';
import 'pages/BarcodePage.dart';
import 'pages/FoodPage.dart';
import 'pages/RecipePage.dart';
import 'pages/ShoppingPage.dart';
void main() {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()),);
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState(){
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
int _selectedPage =0;
final _pageOptions= [
FoodPage(),
RecipePage(),
BarcodePage(title: ,),
ShoppingPage(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
//title: 'Best B4',
theme: ThemeData(
primarySwatch: Colors.teal,),
debugShowCheckedModeBanner: false,
home: Scaffold (
appBar: AppBar(
title:Text(
'BestB4',
style: TextStyle(
fontFamily: 'PacificoRegular',
fontSize: 30,
),
),
backgroundColor: Colors.teal,
elevation: 20,
actions: [
IconButton(
icon: Icon(Icons.qr_code_2_rounded),
tooltip: 'Add item',
onPressed:(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BarcodePage()));
},
)
],
//ONPRESSED MENU OPEN
),
body:_pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.teal,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white70,
iconSize: 40,
selectedFontSize: 15,
unselectedFontSize: 15,
currentIndex:_selectedPage,
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
items: [
BottomNavigationBarItem(
icon:Icon(Icons.restaurant_rounded),
label: 'Food',
), //, title:Text('Food')
BottomNavigationBarItem(
icon:Icon(Icons.menu_book_rounded),
label:'Recipes',
),//, title:Text('Recipes')
BottomNavigationBarItem(
icon:Icon(Icons.add_outlined),
label:'Add',
),//, title:Text('Add')
BottomNavigationBarItem(
icon:Icon(Icons.shopping_cart_rounded),
label:'Shopping',
),//,title:Text('Shopping')
],
),
),
);
}
}
My BarcodePage dart file:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as p;
import 'package:flutter/services.dart';
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:http/http.dart';
class BarcodePage extends StatefulWidget{
const BarcodePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_BarcodePageState createState() => _BarcodePageState();
}
var futuredata = {};
class _BarcodePageState extends State<BarcodePage> {
int counter=0;
String result= "";
Future _scanBarcode() async{
try{
ScanResult scanResult = await BarcodeScanner.scan();
String barcodeResult = scanResult.rawContent;
setState(() {
result = barcodeResult;
});
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.cameraAccessDenied) {
setState((){
result = "CAMERA PERMISSION WAS DENIED. \n EDIT THIS IN YOUR SETTINGS";
});
}else {
setState(() {
result = "404 ERROR UNKNOWN $ex";
});
}
} on FormatException {
setState(() {
result = "SCAN AN ITEM";
});
} catch (ex){
setState(() {
result = "404 ERROR UNKNOWN $ex";
});
}
}
#override
void initState() {}
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.teal,
title:Text('Add an item',
style: TextStyle(
fontFamily: 'Fredoka',
fontSize: 25,
),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
),
);
else if (snapshot.connectionState == ConnectionState.done)
return ListTile(
title: Text(futuredata["product"]["product_name"].toString()),
subtitle: Text("France:" +
futuredata["product"]["product_name_en"].toString()),
);
else {
return Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
);
}
},
future: fetchmydata(),
)
],
),
floatingActionButton: FloatingActionButton.extended(
backgroundColor: Color.fromRGBO(51, 171, 160, 100),
icon: Icon(Icons.camera_alt),
label: Text("Scan"),
onPressed: _scanBarcode,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
The Json file looks like this:
JSON LINK: https://world.openfoodfacts.org/api/v0/product/5060391623139.json
You can read your json like this
var futuredata = {};
var productname= futuredata["product"]["product_name"]
Your fetch method like this
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
With model Class
SampleModel? Mymodel = null;
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
Mymodel = SampleModel.fromJson(futuredata);
} else {
print(response.reasonPhrase);
}
}
in the method we first read data from json as string or text
then we decode the string type or text from server to map type
SampleCode Dartpad live code check
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:http/http.dart' as p;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
var futuredata = {};
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
#override
void initState() {}
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
),
);
else if (snapshot.connectionState == ConnectionState.done)
return ListTile(
title: Text(futuredata["product"]["product_name"].toString()),
subtitle: Text("France:" +
futuredata["product"]["product_name_en"].toString()),
);
else {
return Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
);
}
},
future: fetchmydata(),
)
],
),
);
}
}
Sample ModelClass
///
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
///
class SampleModelProduct {
/*
{
"_id": "5060391623139",
"_keywords": [
"peanut"
],
"product_name": "Peanut butter",
"product_name_en": "Peanut butter",
"product_name_fr": "Peanut butter"
}
*/
String? Id;
List<String?>? Keywords;
String? productName;
String? productNameEn;
String? productNameFr;
SampleModelProduct({
this.Id,
this.Keywords,
this.productName,
this.productNameEn,
this.productNameFr,
});
SampleModelProduct.fromJson(Map<String, dynamic> json) {
Id = json['_id']?.toString();
if (json['_keywords'] != null) {
final v = json['_keywords'];
final arr0 = <String>[];
v.forEach((v) {
arr0.add(v.toString());
});
Keywords = arr0;
}
productName = json['product_name']?.toString();
productNameEn = json['product_name_en']?.toString();
productNameFr = json['product_name_fr']?.toString();
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['_id'] = Id;
if (Keywords != null) {
final v = Keywords;
final arr0 = [];
v!.forEach((v) {
arr0.add(v);
});
data['_keywords'] = arr0;
}
data['product_name'] = productName;
data['product_name_en'] = productNameEn;
data['product_name_fr'] = productNameFr;
return data;
}
}
class SampleModel {
/*
{
"code": "5060391623139",
"product": {
"_id": "5060391623139",
"_keywords": [
"peanut"
],
"product_name": "Peanut butter",
"product_name_en": "Peanut butter",
"product_name_fr": "Peanut butter"
},
"status": 1,
"status_verbose": "product found"
}
*/
String? code;
SampleModelProduct? product;
int? status;
String? statusVerbose;
SampleModel({
this.code,
this.product,
this.status,
this.statusVerbose,
});
SampleModel.fromJson(Map<String, dynamic> json) {
code = json['code']?.toString();
product = (json['product'] != null)
? SampleModelProduct.fromJson(json['product'])
: null;
status = json['status']?.toInt();
statusVerbose = json['status_verbose']?.toString();
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['code'] = code;
if (product != null) {
data['product'] = product!.toJson();
}
data['status'] = status;
data['status_verbose'] = statusVerbose;
return data;
}
}
try creating a .g.dart file using flutter packages pub run build_runner build. flutter automatically will create your binding class factory. once you have the binding classes created flutter will automatically code your binding class, including nested classes. I personally think automation is the way to handle all interactions with json from the server. The reason you want to use the future .g.dart code generator is to reduce the possibility of error and incorrect type casting.
file.dart
factory ProductView.fromJson(Map<String, dynamic> json) =>
_$ProductFromJson(json);
Map<String, dynamic> toJson() => _$ProductViewToJson(this);
file.g.dart
ProductView _$ProductViewFromJson(Map<String, dynamic> json) {
return
ProductView(
json['field1'] as int,
json['field2'] as String,
json['field3'] == null
? null
: DateTime.parse(json['field3'] as String),
);
}
Map<String, dynamic> _$ProjectViewToJson(ProductView instance) =>
<String, dynamic>{
'field1': instance.field1,
'field2': instance.field2,
'field3': instance.field3?.toIso8601String(),
};
decoding the json
var client = http.Client();
Map<String, String> headers = new HashMap();
headers['Accept'] = 'application/json';
headers['Content-Type'] = 'application/json';
headers['Authorization'] = 'Bearer $token';
var response = await client.get(url, headers: headers).timeout(_TIMEOUT);
var parsed = json.decode(response.body);
var view = ProductView.fromJson(parsed);
I want to render all of the pdfs' first page as images and pass them to Home Screen. I make Splash Screen's duration to 30second. But I think it is not right because there can be hundreds of pdfs in someone's phone storage and Splash Screen's duration can be longer than 30seconds. So is there any solution to my problem? Here is my code. Enlighten me pls.
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
import 'package:splash_screen_view/SplashScreenView.dart';
import 'constant.dart';
import 'package:permission_handler/permission_handler.dart';
import 'home_screen.dart';
class Splashscreens extends StatefulWidget {
_SplashscreensState createState() => _SplashscreensState();
}
class _SplashscreensState extends State<Splashscreens> {
List<FileSystemEntity>? filepdf;
List<Uint8List>? imagepdf = [];
void initState() {
super.initState();
getFile();
}
getFile() async {
await Permission.storage.request();
final myDir = Directory('/storage/emulated/0/documents/');
filepdf = myDir.listSync(recursive: true, followLinks: true);
for (int index = 0; index < filepdf!.length; index++) {
final document = await PdfDocument.openFile(filepdf![index].path);
final page = await document.getPage(1);
final pageImage = await page.render(width: page.width, height: page.height);
setState(() {
imagepdf!.add(pageImage!.bytes);
});
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SplashScreenView(
navigateRoute: HomeScreen(filepdf, imagepdf),
duration: 25000,
imageSize: 650,
imageSrc: "assets/image/jensenpdfviewerlogo.jpg",
colors: [
Colors.purple,
Colors.blue,
Colors.yellow,
Colors.red,
Colors.orange,
Color(0xFFECECEC)
],
pageRouteTransition: PageRouteTransition.SlideTransition,
text: "LOADING......",
textType: TextType.ColorizeAnimationText,
textStyle: fontStyle,
backgroundColor: Color(0xFF4E4AC2),
),
),
);
}
}
Here is my suggestion
class Splashscreens extends StatefulWidget {
_SplashscreensState createState() => _SplashscreensState();
}
class _SplashscreensState extends State<Splashscreens> {
List<FileSystemEntity>? filepdf;
List<Uint8List>? imagepdf = [];
Future<Map<String, dynamic>> getFile() async {
await Permission.storage.request();
final myDir = Directory('/storage/emulated/0/documents/');
filepdf = myDir.listSync(recursive: true, followLinks: true);
for (int index = 0; index < filepdf!.length; index++) {
final document = await PdfDocument.openFile(filepdf![index].path);
final page = await document.getPage(1);
final pageImage = await page.render(width: page.width, height: page.height);
setState(() {
imagepdf!.add(pageImage!.bytes);
});
}
var data = {
"file_pdf": filepdf,
"image_pdf": imagepdf
};
return data;
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getFile(),
builder: (BuildContext context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
Map<String, dynamic> data = snapshot.data!;
List<FileSystemEntity>? _filePdf = data["file_pdf"];
List<Uint8List>? _imagepdf = data["image_pdf"];
return YourResultScreen();
default:
return Container();
}
}
);
}
}
I am trying to show the JSON data from a URL to my Flutter application and haven't found any solution yet.
How to show this data in the ListView in Flutter?
Here is my complete Flutter project code:
Main.dart
import 'package:flutter/material.dart';
import 'package:jsontest/Json.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Cricket',
theme: new ThemeData(
primarySwatch: Colors.green,
),
home: new JsonParseDemo(),
);
}
}
Match.dart Where Json Data is in organized form
import 'dart: convert';
Match matchesFromJson(String str) => Match.fromJson(json.decode(str));
String matchesToJson(Match data) => json.encode(data.toJson());
class Match {
Match({
this.name,
this.status,
});
String name;
String status;
factory Match.fromJson(Map<String, dynamic> json) => Match(
name: json["name"],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"name": name,
"status": status,
};
}
Service.dart Here is the base URL to get JSON data
import 'package:http/http.dart' as http;
import 'Users.dart';
class Services {
//
static const String url = 'https://api.cricket.com.au/matches';
static Future<List<Match>> getMatches() async{
try{
final response = await http.get(url);
if (200 == response.statusCode){
final List<Match> match = matchesFromJson(response.body) as List<Match>;
return match;
}
else{
return List<Match>();
}
}
catch(e){
return List<Match>();
}
}
}
And here is the code of my main class where I want to show the data.
JsonParser.dart
import 'package:flutter/material.dart';
import 'Services.dart';
import 'Users.dart';
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Match> _match;
bool _loading;
#override
void initState() {
super.initState();
_loading = true;
Services.getMatches().then((matches) {
setState(() {
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Matches'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: null == _match ? 0 : _match.length,
itemBuilder: (context, index) {
Match match = _match[index];
return ListTile(
title: Text(match.name),
subtitle: Text(match.status),
);
},
),
),
);
}
}
How to get "Name and Status" of the match from this JSON?
Try my code below :
json_parse_demo_screen.dart
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Match> _match;
bool _loading = true;
#override
void initState() {
super.initState();
_loading = true;
Services.getMatches().then((matches) {
setState(() {
_match = matches;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Matches'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: null == _match ? 0 : _match.length,
itemBuilder: (context, index) {
Match match = _match[index];
return ListTile(
title: Text(match.name),
subtitle: Text(match.status),
);
},
),
),
);
}
}
match.dart
import 'dart:convert';
String matchesToJson(Match data) => json.encode(data.toJson());
class Match {
Match({
this.name,
this.status,
});
String name;
String status;
factory Match.fromJson(Map<String, dynamic> json) => Match(
name: json["name"],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"name": name,
"status": status,
};
}
service.dart
Here, you will have to check the hierarchy of the response you get.
The hierarchy of response is:
- meta
- matchList
- matches
Then you have to look for the result you expect (here matches)
class Services {
//
static const String url = 'https://api.cricket.com.au/matches';
static Future<List<Match>> getMatches() async{
try{
final response = await http.get(url);
final responseFormatted = json.decode(response.body);
final matches = responseFormatted["matchList"]["matches"];
if (200 == response.statusCode){
final List<Match> match = matches.map<Match>((item) => Match.fromJson(item)).toList();
return match;
}
else{
return List<Match>();
}
}
catch(e){
return List<Match>();
}
}
}
Output
You didn't initialize match
List<Match> _match;
You can do it like this
Services.getMatches().then((matches) {
setState(() {
_match=matches
_loading = false;
});
});
I'm learning flutter and dart language and trying to apply bloc pattern by rxdart and show data in the page.
Can't get length or display a data in page stream builder and listview.builder because I receive error:
class 'Future<List<User>>' has no instance getter 'length'.
Receiver: Instance of 'Future<List<User>>'
Tried calling: length
My class user.dart
class User {
int id;
String name;
String username;
String email;
User({this.id, this.name, this.username, this.email});
User.fromJson(Map<String, dynamic> parsedJson) {
User(
id: parsedJson['id'],
name: parsedJson['name'],
username: parsedJson['username'],
email: parsedJson['email'],
);
}
}
// user_repo.dart
import 'package:learn_flutter_bloc/bloc_rx_example/User.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'package:learn_flutter_bloc/url.dart';
class UserRepo {
static Future<List<User>> getUsers() async {
final res = await http.get("https://jsonplaceholder.typicode.com/users");
List<User> users = [];
if (res.statusCode == 200) {
var data = jsonDecode(res.body);
for (var user in data) {
users.add(User.fromJson(user));
}
return users;
} else {
throw Exception("Error In Calling APi");
}
}
}
// user_bloc
import 'package:learn_flutter_bloc/bloc_base.dart';
import 'package:learn_flutter_bloc/bloc_rx_example/user_repo.dart';
import 'package:rxdart/subjects.dart';
class UserBloc extends BlocBase {
Subject _usersSubject = BehaviorSubject();
Stream get users => _usersSubject.stream;
getUsers() async {
var usersData = UserRepo.getUsers();
_usersSubject.add(usersData);
}
#override
dispose() {
_usersSubject.close();
}
}
final bloc = UserBloc();
// user_list_app.dart
import 'package:flutter/material.dart';
import 'package:learn_flutter_bloc/bloc_rx_example/user_bloc.dart';
class UserListApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Bloc Rx Example',
theme: ThemeData(
primaryColor: Colors.teal,
),
home: Scaffold(
appBar: AppBar(
title: Text('Bloc Rx Example'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
}),
),
body: UserList(),
),
);
}
}
class UserList extends StatefulWidget {
#override
_UserListState createState() => _UserListState();
}
class _UserListState extends State<UserList> {
#override
void dispose() {
bloc.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
bloc.getUsers();
return Padding(
padding: EdgeInsets.all(10.0),
child: StreamBuilder(
stream: bloc.users,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.weekend),
title: Text('${snapshot.data[index].name}'),
);
});
} else if (!snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
While you are using StreamBuilder in the UI, Your getUsers() is returning Future<List<User>> . Return Stream<<List<User>> from getUsers() .
Fixed I problem was in bloc_user.dart misssing await
Future<List<User>> getUsers() async {
var usersData = UserRepo.getUsers();
print(usersData);
_usersSubject.sink.add(usersData);
}
to
Future<List<User>> getUsers() async {
var usersData = await UserRepo.getUsers();
print(usersData);
_usersSubject.sink.add(usersData);
}