I have a textfield that I will use with sharedpreference to store and pass the value into another page. so far it works.
how to make so that when I return on the page of my textfield there is my value which remains which remains in the textfield?
as it will be a page for setting parameters, when I come back to it, the elements in sharedpreferences will have to remain displayed like this when we modify 1 element, it keeps the others too.
Thanks in advance.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
final _pricesController = TextEditingController();
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
late Future<String> _prix;
Future<void> _voirLePrix() async {
final SharedPreferences prefs = await _prefs;
final String _pricesController =
(prefs.getString('saisie') ?? _prix.toString());
setState(() {
_prix = prefs.setString('saisie', _pricesController).then((bool success) {
return _pricesController;
});
});
}
#override
void initState() {
super.initState();
_voirLePrix();
_prix = _prefs.then((SharedPreferences prefs) {
return prefs.getString('saisie') ?? '';
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('test saisie')),
body: Center(
child: FutureBuilder<String>(
future: _prix,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const CircularProgressIndicator();
default:
if (snapshot.hasError) {
return Text('erreur: ${snapshot.error}');
} else {
return TextField(
controller: _pricesController,
autofocus: false,
decoration: const InputDecoration(
//hintText: 'saisir un prix',
border: OutlineInputBorder(),
),
);
}
}
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: _voirLePrix,
child: const Icon(Icons.add),
),
);
}
}
Related
I am making an app in a flutter in which I can select the contacts from phone book and saving them in shared preferences. No problem in data saving and retrieving but i m struggling with showing the updated list on my UI. It is showing the contacts list but every time I click on Load button it duplicates the list and showing 2 lists , 1 previous and other updated .
how can i show just updated list on UI ?
here is my code:
import 'package:contacts_test/select_contacts.dart';
import 'package:contacts_test/shared_pref.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import 'contact_model.dart';
void main() {
runApp(const 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 const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SharedPref sharedPref = SharedPref();
ContactModel modelLoad = ContactModel(displayName: 'saniya' , phoneNumber: '324235 ');
List _list = [];
#override
initState() {
super.initState();
// Add listeners to this clas
// loadSharedPrefs();
}
loadSharedPrefs() async {
try {
print('in load shared pref-- getting keys ');
final prefs = await SharedPreferences.getInstance();
final keys = prefs.getKeys();
print('now load shared pref ');
for (String key in keys) {
ContactModel user = ContactModel.fromJson(await sharedPref.read(key));
_list.add(user);
}
print('done load shared pref ');
}
catch (Excepetion) {
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("contacts "),
),
body: Builder(
builder: (context) {
return Column(children: [
RaisedButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Plugin1()));
},
child: const Text('fluttercontactpicker - plugin1'),
),
RaisedButton(
onPressed: () async {
await loadSharedPrefs();
},
child: Text('Load', style: TextStyle(fontSize: 20)),
),
Expanded(
child: _list.isNotEmpty ?
ListView.builder(
shrinkWrap: true,
itemCount: _list.length,
itemBuilder: (context, position) {
return ListTile(
leading: Icon(Icons.contacts),
title: Text(
_list[position].displayName.toString()
),
trailing: Icon(Icons.delete));
},
) : Center(child: Text('No list items to show')),
),
]);
}
),
);
}
}
Your loadSharedPrefs(); function adds each contact to the list you show. Every time you press the button, the same elements are added again to the list. There are multiple ways to avoid that. You can: empty the list before filling it, you can write a for loop to loop over the length of the incoming contacts and for each to add it to the list by always starting from index 0. In case you use some kind of replacement or removing method, make sure you call setState(()=> { });
Base on the answer, here is a possible solution:
import 'package:contacts_test/select_contacts.dart';
import 'package:contacts_test/shared_pref.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import 'contact_model.dart';
void main() {
runApp(const 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 const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SharedPref sharedPref = SharedPref();
ContactModel modelLoad = ContactModel(displayName: 'saniya' , phoneNumber: '324235 ');
List _list = [];
#override
initState() {
super.initState();
// Add listeners to this clas
// loadSharedPrefs();
}
loadSharedPrefs() async {
try {
print('in load shared pref-- getting keys ');
final prefs = await SharedPreferences.getInstance();
final keys = prefs.getKeys();
print('now load shared pref ');
var newList = [];
for (String key in keys) {
ContactModel user = ContactModel.fromJson(await sharedPref.read(key));
newList.add(user);
}
setState(()=> { _list = newList; });
print('done load shared pref ');
}
catch (Excepetion) {
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("contacts "),
),
body: Builder(
builder: (context) {
return Column(children: [
RaisedButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Plugin1()));
},
child: const Text('fluttercontactpicker - plugin1'),
),
RaisedButton(
onPressed: () async {
await loadSharedPrefs();
},
child: Text('Load', style: TextStyle(fontSize: 20)),
),
Expanded(
child: _list.isNotEmpty ?
ListView.builder(
shrinkWrap: true,
itemCount: _list.length,
itemBuilder: (context, position) {
return ListTile(
leading: Icon(Icons.contacts),
title: Text(
_list[position].displayName.toString()
),
trailing: Icon(Icons.delete));
},
) : Center(child: Text('No list items to show')),
),
]);
}
),
);
}
}
I expect that when I click the button I will add a single item that has brand and date in it in the Save Data function however I have no idea how to do that.Currently after each click they add tems however they are multiplied by themselves and that completely misses the point . I tried to add a single item however I get information about unsupported Error . In conclusion Please help
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'SharedPreferences Demo',
home: Test(),
);
}
}
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
List<Map<String, dynamic>> listItems = [];
List<String> cart = [];
final Map<String, dynamic> item = Map<String, String>();
saveData() async {
var date = DateTime.now();
print('save data ');
final Map<String, dynamic> item = Map<String, dynamic>();
item['brand'] = 'item';
item['date'] = 'date';
SharedPreferences prefs = await SharedPreferences.getInstance();
if (cart == null) cart = [];
setState(() {
cart = prefs.getStringList("cart") ?? [];
cart.add(jsonEncode(item));
listItems.add(jsonDecode(item));
//<-- when i click button i want add one item card. on but idk how
prefs.setStringList("cart", cart);
});
}
getUser() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var cart = prefs.getStringList("cart");
setState(() {
if (cart == null) {
print('null');
} else {
cart.forEach((item) {
listItems.add(jsonDecode(item));
});
}
});
}
#override
void initState() {
super.initState();
getUser();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: listItems.isNotEmpty
? ListView.builder(
itemCount: listItems.length, itemBuilder: buildList)
: Center(
child: Text('EMPTY LIST'),
)),
Center(
child: FloatingActionButton(
onPressed: saveData,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
)
],
),
);
}
Widget buildList(BuildContext context, int index) {
return Container(
margin: EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 2,
),
borderRadius: BorderRadius.circular(5)),
child: ListTile(
title: Text(listItems[index]['brand']),
subtitle: Text(listItems[index]['date'] ?? "null"),
),
);
}
}
}
I am newbie to state management using provider in flutter.
I've created a model named as Counter:
import 'package:flutter/foundation.dart';
class Counter with ChangeNotifier {
int value = 0;
void increment() {
value++;
notifyListeners();
}
void decrement() {
value--;
notifyListeners();
}
}
Now when value changes I can save it locally using SharedPreferences in order to start from that value next time.
But, I do not know what would be a proper way of loading data from local and set value in Counter class.
Should I load saved data in main.dart file when app is initalized and then setValue to that data?
Or are there any solutions, for example, loading data directly in my Counter class?
create a SharedPreferencesProvider
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesProvider {
final Future<SharedPreferences> sharedPreferences;
SharedPreferencesProvider(this.sharedPreferences);
Stream<SharedPreferences> get prefsState => sharedPreferences.asStream();
}
then create a Provider and with a StreamProvider as shown below
return MultiProvider(
providers: [
Provider<SharedPreferencesProvider>(create: (_) => SharedPreferencesProvider(SharedPreferences.getInstance())),
StreamProvider(create: (context) => context.read<SharedPreferencesProvider>().prefsState, initialData: null)
then consume the state within a Widget build with a context.watch
#override
Widget build(BuildContext context) {
sharedPrefs = context.watch<SharedPreferences>();
Try to use the future builder and then set it to the provider and be able to use SharedPreferences everywhere in the app:
#override
Widget build(BuildContext context) {
return FutureBuilder<SharedPreferences>(
future: SharedPreferences.getInstance(),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data != null) {
return MultiProvider(providers: [
Provider<SharedPreferences>(
create: (context) => snapshot.data!,
),
],
);
}
},
);
}
And you can use context.read() everywhere.
The question is leaning toward opinion. I'm also new to flutter -- the below may not be the best way, but it does work, so maybe it will help someone.
If it's the top level app, you can initialize the counter before actually using it, displaying a loading page during the load time (imperceptible in this case). You must include the first runApp however, otherwise shared_preferences will not be able to correctly access the file containing these preferences on the device.
A similar thing can be done with with FutureBuilder, but you must await a delay prior to attempting to read from shared_preferences.
(I don't think the loading page or delay are necessary if you aren't using the widget as your top level widget, which would probably be better anyway. In that case, probably FutureBuilder would be the correct solution. (?))
To note:
I added an async "constructor" to the Counter class that initializes from the shared_preferences.
I access the Counter via provider library in _MyHomePageState.build with context.watch<Counter>(), which causes this to rebuild on changes (without requiring calls to setState.
I've added async Counter._updatePreferences which is called in Counter.increment and Counter.decrement, which saves the current value of the Counter to the shared_preferences.
Imports and main for first method
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Future<void> main() async {
// run "loading" app while awaiting counter, then run app again
runApp(
const MaterialApp(
home: Center(
child: Text('Loading'),
),
)
);
final Counter counter = await Counter.fromPreferences();
runApp(
ChangeNotifierProvider<Counter>.value(
value: counter,
child: const MyApp(),
)
);
}
Imports and main (with FutureBuilder)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
// Get counter in future builder
runApp(
FutureBuilder<Counter>(
future: Counter.fromPreferences(),
builder: (BuildContext context, AsyncSnapshot<Counter> snapshot) {
Widget returnWidget = const MaterialApp(
home: Center(
child: Text('Loading'),
),
);
if (snapshot.connectionState == ConnectionState.waiting) {
} else if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
print(snapshot.error);
} else if (snapshot.hasData) {
final Counter counter = snapshot.data!;
returnWidget = ChangeNotifierProvider<Counter>.value(
value: counter,
child: const MyApp(),
);
} else {
print('No data');
}
} else if (snapshot.connectionState == ConnectionState.none) {
print('null future');
} else {
print(snapshot.connectionState);
}
return returnWidget;
},
),
);
}
MyApp and MyHomePage
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Counter App',
home: MyHomePage(title: 'Counter App Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final Counter counter = context.watch<Counter>();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${counter.value}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <FloatingActionButton>[
FloatingActionButton(
onPressed: counter.increment,
child: const Icon(Icons.add),
),
FloatingActionButton(
onPressed: counter.decrement,
child: const Icon(Icons.remove),
),
],
),
);
}
}
Counter Class (ChangeNotifier)
class Counter extends ChangeNotifier {
int value = 0;
static Future<Counter> fromPreferences() async {
final Counter counter = Counter();
// Must be included if using the FutureBuilder
// await Future<void>.delayed(Duration.zero, () {});
final SharedPreferences prefs = await SharedPreferences.getInstance();
final int value = prefs.getInt('counterValue') ?? 0;
counter.value = value;
return counter;
}
Future<void> _updatePreferences() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setInt('counterValue', value);
}
void increment() {
value++;
notifyListeners();
_updatePreferences();
}
void decrement() {
value--;
notifyListeners();
_updatePreferences();
}
}
Complete Example
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Future<void> main() async {
// run "loading" app while awaiting counter, then run app again
runApp(
const MaterialApp(
home: Center(
child: Text('Loading'),
),
)
);
final Counter counter = await Counter.fromPreferences();
runApp(
ChangeNotifierProvider<Counter>.value(
value: counter,
child: const MyApp(),
)
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Counter App',
home: MyHomePage(title: 'Counter App Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final Counter counter = context.watch<Counter>();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${counter.value}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <FloatingActionButton>[
FloatingActionButton(
onPressed: counter.increment,
child: const Icon(Icons.add),
),
FloatingActionButton(
onPressed: counter.decrement,
child: const Icon(Icons.remove),
),
],
),
);
}
}
class Counter extends ChangeNotifier {
int value = 0;
static Future<Counter> fromPreferences() async {
final Counter counter = Counter();
// Must be included if using the FutureBuilder
// await Future<void>.delayed(Duration.zero, () {});
final SharedPreferences prefs = await SharedPreferences.getInstance();
final int value = prefs.getInt('counterValue') ?? 0;
counter.value = value;
return counter;
}
Future<void> _updatePreferences() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setInt('counterValue', value);
}
void increment() {
value++;
notifyListeners();
_updatePreferences();
}
void decrement() {
value--;
notifyListeners();
_updatePreferences();
}
}
Use the shared_preferences plugin
enter link description here
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SharedPreferences Demo',
home: SharedPreferencesDemo(),
);
}
}
class SharedPreferencesDemo extends StatefulWidget {
SharedPreferencesDemo({Key key}) : super(key: key);
#override
SharedPreferencesDemoState createState() => SharedPreferencesDemoState();
}
class SharedPreferencesDemoState extends State<SharedPreferencesDemo> {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Future<int> _counter;
Future<void> _incrementCounter() async {
final SharedPreferences prefs = await _prefs;
final int counter = (prefs.getInt('counter') ?? 0) + 1;
setState(() {
_counter = prefs.setInt("counter", counter).then((bool success) {
return counter;
});
});
}
#override
void initState() {
super.initState();
_counter = _prefs.then((SharedPreferences prefs) {
return (prefs.getInt('counter') ?? 0);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("SharedPreferences Demo"),
),
body: Center(
child: FutureBuilder<int>(
future: _counter,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const CircularProgressIndicator();
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text(
'Button tapped ${snapshot.data} time${snapshot.data == 1 ? '' : 's'}.\n\n'
'This should persist across restarts.',
);
}
}
})),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Reference site : https://pub.dev/packages/shared_preferences#-example-tab-
I tried to read data using shared preferences and return my widget using FutureBuilder, but the problem is... when I click another tab screen and then back again to my home tab screen, the data inside widget always rerender.. is there a way so that my data always stick in my widget whenever I click another tab and back again to my home tab?
here is the code
class _SecondPageState extends State<SecondPage>
with AutomaticKeepAliveClientMixin<SecondPage> {
Future<int> _getUsername;
#override
bool get wantKeepAlive => true;
#override
void initState() {
_getUsername = SharedPreferences.getInstance().then((prefs) {
return prefs.getInt("username");
});
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
print("loading");
return Text("Loading username...");
// how to prevent this condition so that my data always stick in my widget without rerender
}
final username = snapshot.data.toString();
return Container(
child: Text("Hello $username"),
);
});
}
}
You can copy paste run full code below
You can use AutomaticKeepAliveClientMixin
code snippet
class _Page3State extends State<Page3>
with AutomaticKeepAliveClientMixin<Page3> {
...
#override
bool get wantKeepAlive => true;
FutureBuilder(
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
print("loading");
return Text("Loading username...");
Working demo, you can see console output only print one loading
Output
I/flutter ( 8528): loading
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MainPersistentTabBar(),
);
}
}
class MainPersistentTabBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
isScrollable: true,
tabs: [
Tab(
icon: Icon(Icons.directions_car),
text: "Non persistent",
),
Tab(icon: Icon(Icons.directions_transit), text: "Persistent"),
Tab(icon: Icon(Icons.directions_railway), text: "Test 1"),
Tab(icon: Icon(Icons.directions_subway), text: "Test 2"),
],
),
title: Text('Persistent Tab Demo'),
),
body: TabBarView(
children: [
Page1(),
Page2(),
Page3(),
Text('Page 4'),
],
),
),
);
}
}
class Page3 extends StatefulWidget {
#override
_Page3State createState() => _Page3State();
}
class _Page3State extends State<Page3>
with AutomaticKeepAliveClientMixin<Page3> {
Future<int> _getUsername;
#override
bool get wantKeepAlive => true;
#override
void initState() {
_getUsername = SharedPreferences.getInstance().then((prefs) {
return prefs.getInt("username");
});
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
print("loading");
return Text("Loading username...");
// how to prevent this condition so that my data always stick in my widget without rerender
}
final username = snapshot.data.toString();
return Container(
child: Text("Hello $username"),
);
});
}
}
class Page1 extends StatefulWidget {
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
var list = List();
_loadList() async {
final response =
await http.get("https://jsonplaceholder.typicode.com/posts/");
if (response.statusCode == 200) {
await new Future.delayed(const Duration(seconds: 1));
if (mounted) {
setState(() {
list = json.decode(response.body) as List;
});
}
} else {
throw Exception('Failed to load posts');
}
}
#override
void initState() {
_loadList();
super.initState();
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
final data = list[index];
return ListTile(
contentPadding: EdgeInsets.all(10.0),
title: Text(data['title']),
subtitle: Text(
data['body'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
);
},
);
}
}
class Page2 extends StatefulWidget {
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2>
with AutomaticKeepAliveClientMixin<Page2> {
var list = List();
_loadList() async {
final response =
await http.get("https://jsonplaceholder.typicode.com/photos/");
if (response.statusCode == 200) {
await new Future.delayed(const Duration(seconds: 1));
if (mounted) {
setState(() {
list = json.decode(response.body) as List;
});
}
} else {
throw Exception('Failed to load posts');
}
}
#override
void initState() {
_loadList();
super.initState();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Container(
child: ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
final data = list[index];
return ListTile(
contentPadding: EdgeInsets.all(10.0),
title: Text(data['title']),
trailing: Image.network(
data['thumbnailUrl'],
height: 20.0,
width: 20.0,
),
);
},
),
);
}
// TODO: implement wantKeepAlive
#override
bool get wantKeepAlive => true;
}
I a trying to save the searched item from searchbar to sharedpreference and want to display the list of searched list in other page but unable to achieve it. Below is my code how I am saving and retrieving it from the sharedprefernce.
I have updated my code please go through it.
Update
I have query which I am passing it to the url and getting the list directly
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Ayurwikilist> ayurwikilist = [];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Ayurwiki'),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.search),
onPressed: () {
showSearch(
context: context,
delegate: CustomSearchDelegate(ayurwikilist));
},
),
],
),
body: _body(),
);
}
class CustomSearchDelegate extends SearchDelegate {
List<Ayurwikilist> ayurwikilist = [];
CustomSearchDelegate(this.ayurwikilist);
Future<Ayurwikilist> fetchPost() async {
final response = await http.get(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
print(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
return Ayurwikilist.fromJson(json.decode(response.body));
}
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () async{
query = '';
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('name', "$query");
print(query);
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
return Container();
}
#override
Widget buildSuggestions(BuildContext context) {
return FutureBuilder<Ayurwikilist>(
future: fetchPost(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
print(snapshot.data.toString());
return ListView.builder(
itemCount: snapshot.data.query.search.length,
itemBuilder: (BuildContext context, int index) {
var title = snapshot.data.query.search[index].title;
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detailpage(
snapshot.data.query.search[index].title,
// 'images/ayurwiki.png'
),
));
},
child: ListTile(
title: Text(title),
),
);
});
} else {
return Center(
child: Text(
'Search in ayurwiki',
style: TextStyle(color: Colors.grey, fontSize: 18),
),
);
}
},
);
}
}
class _HistoryState extends State<History> {
var myName;
getCredential() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var query = prefs.getString('query');
setState(() {
myName = query;
});
print('item : $query');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:Text('Rcently viewed item'),
),
body: Container(
decoration: new BoxDecoration(color: Colors.white),
child: myName == null ? Text('No items') : Text('$myName'),
),
);
}
}
Update
Future<Ayurwikilist> fetchPost() async {
final response = await http.get(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
print(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setStringList('name', query as List);
return Ayurwikilist.fromJson(json.decode(response.body));
}
getCredential() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var name = prefs.getStringList('name');
setState(() {
myName = name;
});
print('item : $name');
}
you should call getCredential() function in initState
class _HistoryState extends State<History> {
var myName;
initState(){
super.initState();
getCredential();
}
getCredential() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var query = prefs.getString('query');
setState(() {
myName = query;
});
print('item : $query');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:Text('Rcently viewed item'),
),
body: Container(
decoration: new BoxDecoration(color: Colors.white),
child: myName == null ? Text('No items') : Text('$myName'),
),
);
}
}
update:
Future<Ayurwikilist> fetchPost() async {
query = 'something you need';
final response = await http.get(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
print(
'https://www.example.org/api.php?action=query&list=search&srsearch=$query&utf8=&format=json');
prefs.setString('name', query);
return Ayurwikilist.fromJson(json.decode(response.body));
}