Hi how i can Load this list in a ListView or ListViebuilder?
Future<List<bool>> getBoolList() async{
List<bool> prefList = [];
var sharedPreferences = await SharedPreferences.getInstance();
Set<String> keys = sharedPreferences.getKeys();
for(int i=0; i<keys.length ; i++){
bool value = sharedPreferences.getBool(keys.elementAt(i));
prefList.add(value);
}
return prefList;
}
List<bool> list = await getBoolList();
how I got there
Flutter SharedPreferences how to load all saved?
Edit: my favorite.dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
// ignore: must_be_immutable
class Favoriten extends StatefulWidget {
#override
_FavoritenState createState() => _FavoritenState();
}
class _FavoritenState extends State<Favoriten> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Favorites'),
),
body: // MyList
);
}
}
You have to use stream builder. It observes the stream. (Best way to implement is using bloc pattern)
class Favoriten extends StatefulWidget {
#override
_FavoritenState createState() => _FavoritenState();
}
class _FavoritenState extends State<Favoriten> {
final _boolList = PublishSubject<List<bool>>();
Observable<List<bool>> get boolList => _boolList.stream;
loadList() async{
List<bool> prefList = [];
var sharedPreferences = await SharedPreferences.getInstance();
Set<String> keys = sharedPreferences.getKeys();
for(int i=0; i<keys.length ; i++){
bool value = sharedPreferences.getBool(keys.elementAt(i));
prefList.add(value);
}
_boolList.sink.add(prefList);
}
#override
Widget build(BuildContext context) {
loadList();
return StreamBuilder(
stream: boolList,
builder: (context, snapshot) {
if (snapshot.hasData) {
return root(snapshot.data);
} else {
return Container(
child: YourLoader(),// display loader
);
}
}
);
}
Widget root(List<bool> list){
return ListView.builder(
itemBuilder: (context, index) {
return Container(); // your design here
}
itemCount: list.length,
);
}
}
Note :- You have to add rxdart: ^0.22.0 plugin in your pubspec.yaml
and then import 'package:rxdart/rxdart.dart';
Related
Flutter
import 'package:country_house/pages/Country.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
class AllCountries extends StatefulWidget {
const AllCountries({Key? key}) : super(key: key);
#override
State<AllCountries> createState() => _AllCountriesState();
}
class _AllCountriesState extends State<AllCountries> {
Future<List> countries=[];
Future<List> getCountries() async {
var response = await Dio().get('https://restcountries.com/v3.1/all');
return response.data.length;
}
#override
void initState() {
countries = getCountries();
super.initState();
}
#override
Widget build(BuildContext context) {
getCountries();
return Scaffold(
appBar: AppBar(
title: Text('All Countries'),
centerTitle: true,
),
body: Container(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: FutureBuilder<List>(
future: countries,
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (snapshot.hasData) {
return Text('hello');
}
return null;
}),
),
),
);
}
}
I get the following error:
A value of type 'List' can't be assigned to a variable of type 'Future<List>'.
'List' is from 'dart:core'.
'Future' is from 'dart:async'.
Future countries=[];
How can I resolve this issue?
You have to declare countries in this form:
Future<List> countries = Future.value([]);
class _AllCountriesState extends State<AllCountries> {
Future<List> countries = Future.value([]);
Future<List> getCountries() async {
var response = await Dio().get('https://restcountries.com/v2/all');
return response.data;
}
#override
void initState() {
countries = getCountries();
super.initState();
}
You have to declare countries as a late Future:
late Future<List> countries;
then, the initState() will work.
Note that you are requesting the length of the response and not the data.
In order to populate the list you should also parse the jSon data.
You can read an example of networking in flutter using Dio at the following link: Networking in Flutter using Dio
I have a simple question. I have a list of three integers. In my app, I have a floating action button. Each time when button is pressed the 'next' element of list is displayed. I have to reset to the first element once the looping is completed. I achieved this in a hard way;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
List nums = [1, 2, 3];
void _incrementCounter() {
if (_counter <= 1) {
setState(() {
_counter++;
});
} else {
setState(() {
_counter = 0;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('${nums[_counter]}'),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
}
I wish to know if there are some easier ways to achieve this. Thanks in advance for any help.
You can use remainder (%) to get back to the first index after a loop:
void _incrementCounter() {
setState(() {
_counter = (_counter + 1) % nums.length;
});
}
I am trying to get lazy loading output with flutter. I could do lazy loading only with a generated array given by flutter as an example. But I couldn't get the same output when integrating with Rest API. How to perform lazy loading with an API in a flutter?
I call an api with pagination ,
here is my code :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class TestLazyLoading extends StatefulWidget {
#override
_TestLazyLoadingState createState() => new _TestLazyLoadingState();
}
class _TestLazyLoadingState extends State<TestLazyLoading> {
static const String _url = 'https://api.coinranking.com/v1/public/coins';
ScrollController controller;
int _totalCount = 0;
int _limit = 20;
int _offset = 0;
List<String> items = [];
bool _isLoading = true;
#override
void initState() {
super.initState();
controller = new ScrollController()..addListener(_scrollListener);
_getData(limit: _limit, offset: _offset);
}
#override
void dispose() {
controller.removeListener(_scrollListener);
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Scrollbar(
child: ListView.builder(
controller: controller,
itemBuilder: (context, index) {
if (items.length-1 == index && _isLoading ) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return Container(
child: Text(items[index]),
height: 38,
alignment: Alignment.centerLeft,
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(10),
color: Colors.grey[200],
);
}
},
itemCount: items.length,
),
),
),
);
}
void _scrollListener() {
if (controller.position.extentAfter < 50) {
if (!_isLoading && _totalCount > items.length) {
_offset += _limit;
_getData(limit: _limit, offset: _offset);
}
}
}
void _getData({#required int limit, #required int offset}) async {
setState(() {
_isLoading = true;
});
http.Response response =
await http.get('$_url?limit=$limit&offset=$offset');
if (response.statusCode == 200) {
var jsonResponse = jsonDecode(response.body);
_totalCount = jsonResponse['data']['stats']['total'];
List<dynamic> coinList = jsonResponse['data']['coins'];
for (dynamic coin in coinList) {
items.add(coin['symbol']);
}
setState(() {
_isLoading = false;
});
}
}
}
also add dependncy for http in you pubspec.yaml :
dev_dependencies:
flutter_test:
sdk: flutter
http: ^0.12.1
finally call TestLazyLoading widget in the main for testing
I want to cache two lists that got from Firebase to use to later when the user is offline
This is the full code for my list display screen -
import 'package:flutter/material.dart';
import 'package:naamaa/calculations/name-list-calc.dart';
List namesList = List();
List meaningsList = List();
class NameList extends StatefulWidget {
#override
_NameListState createState() => _NameListState();
}
class _NameListState extends State<NameList> {
Future<String> getPosts() async {
var names = await NameListCalc().nameListCalc();
namesList.addAll(names[0]);
meaningsList.addAll(names[1]);
String s = 'test';
return s;
}
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: ListView.builder(
padding: EdgeInsets.zero,
itemBuilder: (context, position) {
return Row(
children: <Widget>[
Container(
width: 100,
child: Text(namesList[position]),
),
Container(
child: Text(meaningsList[position]),
)
],
);
},
itemCount: namesList.length,
),
);
} else {
return Text(':(');
}
},
);
}
}
I want to cache namesList and meaningsList for later use.
If someone can help it would be great :)
I didn't get complete requirement by your question description but you can use shared_preferences library to store the data list as following
Add following line pubspec.yaml
dependencies:
flutter:
sdk: flutter
shared_preferences:
You can use this example and add more utility methods as per you requirement.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
AppConfig.init(() {
runApp(MyApp());
});
}
class CustomModel {
int id;
String name;
CustomModel({this.id, this.name});
factory CustomModel.fromJson(Map<String, dynamic> json) {
return CustomModel(id: json["id"], name: json["name"]);
}
Map<String, dynamic> toJson() => {"id": id, "name": name};
#override
String toString() {
return "id: $id, name: $name";
}
}
class AppConfig {
static Future init(VoidCallback callback) async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferenceUtils.init();
callback();
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class SharedPreferenceUtils {
static SharedPreferences prefs;
static init() async {
prefs = await SharedPreferences.getInstance();
// storing lists
await putStringList("m_list", ["abc", "def"]);
await putObjectList("data",
[CustomModel(id: 1, name: "Bob"), CustomModel(id: 2, name: "Alice")]);
}
static Future<bool> putStringList(String key, List<String> list) async {
return prefs.setStringList(key, list);
}
static List<String> getStringList(String key) {
return prefs.getStringList(key);
}
static Future<bool> putObjectList(String key, List<Object> list) async {
if (prefs == null) return null;
List<String> _dataList = list?.map((value) {
return json.encode(value);
})?.toList();
return prefs.setStringList(key, _dataList);
}
static List<T> getObjList<T>(String key, T f(Map v),
{List<T> defValue = const []}) {
if (prefs == null) return null;
List<Map> dataList = getObjectList(key);
List<T> list = dataList?.map((value) {
return f(value);
})?.toList();
return list ?? defValue;
}
static List<Map> getObjectList(String key) {
if (prefs == null) return null;
List<String> dataList = prefs.getStringList(key);
return dataList?.map((value) {
Map _dataMap = json.decode(value);
return _dataMap;
})?.toList();
}
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(SharedPreferenceUtils.getStringList("m_list").toString()),
Text(SharedPreferenceUtils.getObjList<CustomModel>(
"data", (v) => CustomModel.fromJson(v)).toString()),
],
),
),
),
);
}
}
You don't need to store the lists in init() as it's done for this example. You can also pass data from one widget to others in multiple ways and if you are looking for state management then you can use BLOC or providers.
Here is my point: I have two pages. The first page has a textFormField and it's value I send to the second screen. In the second screen I want to create a list of what I received from the first page. But the problem is that the list is never created. It just shows the last element received.
import 'package:flutter/material.dart';
class PageTwo extends StatefulWidget {
final String descricao;
const PageTwo({Key key, this.descricao}) : super(key: key);
#override
_PageTwoState createState() => _PageTwoState();
}
class _PageTwoState extends State<PageTwo> {
final List<String> listDescricao = [];
#override
void initState() {
listDescricao.add(widget.descricao);
super.initState();
}
//List images items
Widget imgListItem() {
return ListView.builder(
itemCount: listDescricao.length,
itemBuilder: (BuildContext context, int index) {
return widget.descricao == null
? Container()
: Text(listDescricao[index]);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: imgListItem(),
);
}
}
As required this is the PAGE ONE:
import 'package:flutter/material.dart';
class PageOne extends StatefulWidget {
#override
_PageOneState createState() => _PageOneState();
}
class _PageOneState extends State<PageOne> {
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
final inputDescricaoController = TextEditingController();
//send image
doSend() async {
String descricao = inputDescricaoController.text ??= "";
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) => PageTwo(descricao: descricao)),
(Route<dynamic> route) => false);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: RaisedButton(
child: Column(
children: <Widget>[
TextField(
controller: inputDescricaoController,
),
Text(
'send',
),
],
),
onPressed: () async {
doSend();
},
),
);
}
}