I wrote this code recently but it doesn't get me the result!
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'package:pics/src/widgets/image_list.dart';
import 'models/image_model.dart';
import 'dart:convert';
class App extends StatefulWidget {
createState() {
return AppState();
}
}
class AppState extends State<App> {
int counter = 0;
List<ImageModel> images = [];
void fetchImage() async {
counter++;
final Uri rep =
Uri.parse('https://jsonplaceholder.typicode.com/photos/$counter');
var response = await get(rep);
var imageModel = ImageModel.fromJson(json.decode(response.body));
setState(() {
images.add(imageModel);
});
}
Widget build(context) {
return MaterialApp(
home: Scaffold(
body: ImageList(images),
appBar: AppBar(
title: const Text('Lets see some images'),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: fetchImage,
),
),
);
}
}
The terminal say this:
The following NetworkImageLoadException was thrown resolving an image
codec: HTTP request failed, statusCode: 403,
https://via.placeholder.com/600/92c952
When the exception was thrown, this was the stack:
#0 NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:117:9)
Image provider: NetworkImage("https://via.placeholder.com/600/92c952",
scale: 1.0) Image key:
NetworkImage("https://via.placeholder.com/600/92c952", scale: 1.0)
and this is image list class if you need to read it:
import 'package:flutter/material.dart';
import '../models/image_model.dart';
class ImageList extends StatelessWidget {
final List<ImageModel> images;
ImageList(this.images);
Widget build(context) {
return ListView.builder(
itemCount: images.length,
itemBuilder: (context, int index) {
return Image.network(images[index].url);
},
);
}
}
and this is Image Model:
class ImageModel {
late int id;
late String title;
late String url;
ImageModel(this.id, this.title, this.url);
ImageModel.fromJson(Map<String, dynamic> parsedJson) {
id = parsedJson['id'];
title = parsedJson['title'];
url = parsedJson['url'];
}
}
You can use web render, run with --web-renderer html
flutter run -d c --web-renderer html
-d to select device, where c is chrome
Related
I am developing a mobile application with Flutter. And I have a code like this:
PaginationController.dart:
import 'package:get/get.dart';
import 'package:keycehennemi/functions/SecureStorage.dart';
class PaginationController extends GetxController {
RxString ProductImage = RxString("");
}
ListView.dart:
onTap: () {
setState(() {
paginationController.ProductImage.value = snapshot.data.docs[index].data()["Image"];
});
Get.to(const ProductDetailsPage());
},
The page I'm trying to show the image:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:keycehennemi/controllers/PaginationController.dart';
class ProductDetailsPage extends StatefulWidget {
const ProductDetailsPage({Key key}) : super(key: key);
#override
State<ProductDetailsPage> createState() => _ProductDetailsPageState();
}
PaginationController paginationController = PaginationController();
String ImageURL = "";
class _ProductDetailsPageState extends State<ProductDetailsPage> {
#override
void initState() {
super.initState();
setState(() {
ImageURL = paginationController.ProductImage.value;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
Image.network(ImageURL, fit: BoxFit.cover),
],
),
),
);
}
}
When I run these codes, I get an error like this:
How can I solve this problem? I haven't been able to figure it out for days, it bothers me.
When I print the ProductImage in the PaginatonController I see the value is given. So the value is assigned to ProductImage. But I can't display the image on the page I'm trying to display and I'm getting an error.
I know this may not be conventional but this is how i use GetX (It can help you):
First I make a GlobalBindings.dart file:
class GlobalBindings implements Bindings {
#override
void dependencies() {
Get.lazyPut<PaginationController>(() => PaginationController(),
fenix: true);
}
Then I do this in my void main:
void main async {
GlobalBindings().dependencies();
runApp(MyApp());
}
Then in my PaginationController.dart:
class PaginationController extends GetxController {
String _productImage = "";
String get productImage => _productImage;
setProductImage(String value){
_productImage = value;
update();
}
}
Then inside productImage:
class ProductDetailsPage extends StatelessWidget {
ProductDetailsPage({Key? key})
: super(key: key);
#override
Widget build(BuildContext context) {
//Call GetBuilder anywhere in the app
return GetBuilder<PaginationController>(builder:(controller)=> Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
if(controller.productImage.isNotEmpty)
Image.network(controller.productImage, fit: BoxFit.cover),
TextButton(child:Text("Button"),onPressed:(){
controller.setProductImage("You can set image url here");
})
],
),
),
));
}
}
Note: You can use the GetBuilder any where.
I am trying to retrieve data from a Realtime database in Firebase to Flutter. The data should be parsed to be used in the building of a listview inside a future builder. However, after I execute the code I got an error that displayed on the Emulator screen. My understanding is that there is a type mismatch inside the code of firebaseCalls method. Below is my code Main.dart, data model, Firebase data, and Error Message. Any help to figure out the issue is appreciated. Thanks in advance!
Main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'datamodel.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final ref = FirebaseDatabase.instance.ref();
Future<List<Menu>> firebaseCalls(DatabaseReference ref) async {
DataSnapshot dataSnapshot = await ref.child('Task').get();
String? jsondata =dataSnapshot.value as String?; // just in case String is not working
//String jsondata = dataSnapshot.children;// value;//[0]['Task'];// should be dataSnapshot.value
// Decode Json as a list
final list = json.decode(jsondata!);// as List<dynamic>;
return list.map((e) => Menu.fromJson(e)).toList();
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
//drawer: _drawer(data),
appBar: AppBar(
title: const Text('الصف السادس العلمي'),
),
body: FutureBuilder(
future: firebaseCalls(ref), // async work
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return new Text('Press button to start');
case ConnectionState.waiting:
return new Text('Loading....');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) =>
_buildTiles(snapshot.data[index]),
);
}
} // builder
)
)
);
}
////////////////////////////////////////////
Widget _buildTiles(Menu list) {
if (list.subMenu?.length == 0)
return new ListTile(
leading: Icon(list.icon),
title: Text(
list.name!,
style: TextStyle(
fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
),
onTap: () => debugPrint("I was clicked"),
);
return new ExpansionTile(
leading: Icon(list.icon),
title: Text(
list.name!,
style: TextStyle(
fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
),
children: list.subMenu!.map(_buildTiles).toList(),
);
}//_buildTiles
}
datamodel.dart
import 'package:flutter/material.dart';
class Menu {
String? name; // I added ?
IconData? icon;// I added ?
int? font;// I added ?
List<Menu>? subMenu= [];// I added ?
Menu({this.name, this.subMenu, this.icon,this.font});
Menu.fromJson(Map<String, dynamic> json) {
name = json['name'];
font = json['font'];
icon = json['icon'];
if (json['subMenu'] != null) {
//subMenu?.clear(); // I added ? it also recomand using !
json['subMenu'].forEach((v) {
//subMenu?.add(new Menu.fromJson(v));
subMenu?.add(Menu.fromJson(v));
});
}
}
}
Database:
Error message:
The problem is here:
DataSnapshot dataSnapshot = await ref.child('Task').get();
String? jsondata =dataSnapshot.value as String?;
If we look at the screenshot of the database you shared, it's clear that the value under the /Task path is not a string. It is in fact an entire object structure, which means you get back a Map<String, Object> from dataSnapshot.value. And since that's not a String, you get the error that you get.
The proper way to get the value of the entire Task node is with something like:
Map values = dataSnapshot.value;
And then you can get for example the name with:
print(values["name"]);
Alternatively you get get the child snapshot, and only then get the string value from it, with something like:
String? name = dataSnapshot.child("name")?.value as String?;
This keeps happening although there is data in the database. I'm new to flutter and I've been trying to fix this problem for almost three days now. snapshot.data is returning null and I don't know why because I have enough data in the database.
Below is the db_helper.dart file.
import 'dart:async';
import 'dart:io' as io;
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:com.example.simple_app/models/person.dart';
import 'package:path/path.dart';
class DBHelper {
static Database db_instance;
Future<Database> get db async {
if (db_instance == null) {
db_instance = await initDB();
}
return db_instance;
}
initDB() async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'simpleapp.db');
var db = await openDatabase(path, version: 1, onCreate: onCreateFunc);
return db;
}
void onCreateFunc(Database db, int version) async {
// create table
await db.execute(
'CREATE TABLE persons(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, created DATETIME, updated DATETIME);');
}
/// crud functions
Future<List<Person>> getAllPersons() async {
final db_connection = await db;
var response = await db_connection.query("Person");
List<Person> list = response.map((c) => Person.fromMap(c)).toList();
return list;
}
// add new person
void addNewPerson(Person person) async {
var db_connection = await db;
String query = """
INSERT INTO persons(name,created,updated) VALUES('${person.name}','${person.created}', '${person.updated}')
""";
await db_connection.transaction((transaction) async {
print(query);
return await transaction.rawInsert(query);
});
}
}
Below is home.dart file where I'm trying to display the data from the database in FutereBuilder but snapshot is always returning null, which is resulting in the loader circle circling all time.
import 'package:com.example.simple_app/models/person.dart';
import 'package:com.example.simple_app/utils/db_helper.dart';
import 'package:flutter/material.dart';
import 'package:com.example.simple_app/common_widgets/appbar.dart';
import 'dart:async';
import 'package:sqflite/sqflite.dart';
var dbHelper = DBHelper();
class HomePage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _HomePageState();
}
}
class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
final List<Widget> _children = [];
static const TextStyle moneyLendingAction =
TextStyle(color: Colors.white, fontSize: 20);
#override
Widget build(BuildContext context) {
final controller_name = new TextEditingController();
return new Scaffold(
appBar: appbar(context, 'Simple App', 'other data'),
body: new Container(
padding: EdgeInsets.all(16.0),
child: FutureBuilder<List<Person>>(
future: dbHelper.getAllPersons(),
builder:
(BuildContext context, AsyncSnapshot<List<Person>> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Person item = snapshot.data[index];
return Dismissible(
background: Container(color: Colors.red),
onDismissed: (direction) {},
child: ListTile(
title: Text(item.name),
subtitle: Text(item.name),
leading: CircleAvatar(child: Text(item.id.toString())),
),
);
},
);
} else {
// because snapshot.data is returning null, this is showing all time.
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
#override
void initState() {
super.initState();
}
}
Below is the person.dart model file.
class Person {
int id;
String name;
DateTime created, updated;
Person({this.id, this.name, this.created, this.updated});
factory Person.fromMap(Map<String, dynamic> json) => new Person(
id: json["id"],
name: json["name"],
created: json["created"],
updated: json["updated"],
);
Map<String, dynamic> toMap() => {
"id": id,
"name": name,
"created": created,
"updated": updated,
};
}
What I want is to show the data from the database in the FutureBuilder. And please don't tell me this is duplicate because I have checked similar questions and I don't see any question that relates to what is happening in my code.
Thank you, posted with love.
You need to cast date strings from JSON response
created: DateTime.parse(data['created_at'].toString()),
updated: DateTime.parse(data['date'].toString()),
I would like to make an endlessFeed in Fluter but the app terminates without giving me any information why. Basically it happens after I scrolled down about 60 images then it starts to lag a bit and it crashes.
I tested another API but the same there. It uses images with lower resolution so it takes longer to scroll down until it stops working.
So I don't know what happens here. My guess is that there are to many images in the ListView so that the phone can't handle it and crashes.
I've put the whole code below because I don't even know wehere the problem could be. Is there maybe another way to achieve an endlessImageFeed?
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:cached_network_image/cached_network_image.dart';
// my base url
String imageUrl = "http://192.168.2.107:8000";
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'EndlessFeed',
theme: ThemeData(
primaryColor: Colors.white,
),
home: PhotoList(),
);
}
}
class PhotoList extends StatefulWidget {
#override
PhotoListState createState() => PhotoListState();
}
class PhotoListState extends State<PhotoList> {
StreamController<Photo> streamController;
List<Photo> list = [];
#override
void initState() {
super.initState();
streamController = StreamController.broadcast();
streamController.stream.listen((p) => setState(() => list.add(p)));
load(streamController);
}
load(StreamController<Photo> sc) async {
// URL for API
String url = "http://192.168.2.107:8000/api/";
/* ______________________________________________
I also tried another API but it chrashes also (but it takes longer until crash):
String url = "https://jsonplaceholder.typicode.com/photos/";
______________________________________________ */
var client = new http.Client();
var req = new http.Request('get', Uri.parse(url));
var streamedRes = await client.send(req);
streamedRes.stream
.transform(UTF8.decoder)
.transform(json.decoder)
.expand((e) => e)
.map((map) => Photo.fromJsonMap(map))
.pipe(sc);
}
#override
void dispose() {
super.dispose();
streamController?.close();
streamController = null;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EndlessFeed"),
),
body: Center(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) => _makeElement(index),
),
),
);
}
Widget _makeElement(int index) {
if (index >= list.length) {
return null;
}
return Container(
child: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Column(
children: <Widget>[
child: new Container(
// my base URL + one image
child: new Image(image: new CachedNetworkImageProvider(imageUrl + list[index].mImage))
),
),
],
),
));
}
}
class Photo {
final String mImage;
Photo.fromJsonMap(Map map)
: mImage= map['mImage'];
}
I'm designing an app with a List-List-Detail view (an overview of lists, each list, details of the selected item from each list) that pulls all of its data from static JSON files.
I'm wondering what's the best structure for reading, parsing, and displaying the JSON files. Should I design models for each view: the overview of all lists, each list, and each item and have those as separate files? Should all of the asset loading and JSON parsing take place in those model files? Should the each view only accept parsed data in the form of a PODO?
I've been following the instructions here for the overall design, but I'm stuck on the best way to work with the JSON files, since they add an async element to Widget design.
Yes you need to create the Model class to handle the JSON response,
Either you can use the same model class to list-list, but dont forget to add child list items to same model
here is the sample example
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response =
await client.get('https://jsonplaceholder.typicode.com/photos');
// Use the compute function to run parsePhotos in a separate isolate
return compute(parsePhotos, response.body);
}
// A function that will convert a response body into a List<Photo>
List<Photo> parsePhotos(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => new Photo.fromJson(json)).toList();
}
class Photo {
final int albumId;
final int id;
final String title;
final String url;
final String thumbnailUrl;
Photo({this.albumId, this.id, this.title, this.url, this.thumbnailUrl});
factory Photo.fromJson(Map<String, dynamic> json) {
return new Photo(
albumId: json['albumId'] as int,
id: json['id'] as int,
title: json['title'] as String,
url: json['url'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
);
}
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final appTitle = 'Isolate Demo';
return new MaterialApp(
title: appTitle,
home: new MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new FutureBuilder<List<Photo>>(
future: fetchPhotos(new http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? new PhotosList(photos: snapshot.data)
: new Center(child: new CircularProgressIndicator());
},
),
);
}
}
class PhotosList extends StatelessWidget {
final List<Photo> photos;
PhotosList({Key key, this.photos}) : super(key: key);
#override
Widget build(BuildContext context) {
return new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return new Image.network(photos[index].thumbnailUrl);
},
);
}
}