An application might require local storage to store information about user's activity and/or profile
localstorage
package provides LocalStorage
which can be used to implement json storage in an application
Check Flutter installation to setup Flutter
Use flutter create
command to create a Flutter project (here local_storage_app :
flutter create local_storage_app
Add state_persistence
package to pubspec.yaml
dependencies:
state_persistence:
localstorage: ^3.0.0
flutter:
sdk: flutter
Run following command to add dependency
flutter pub get
import 'package:localstorage/localstorage.dart';
LocalStorage
A string is passed to LocalStorage as an identifier
final LocalStorage storage = new LocalStorage('local_storage_example_widget');
storage.ready.then((ready) { setState(() { var item = storage.getItem('local_storage_example_widget'); }); });
Get storage data for a specific key
var item = storage.getItem('local_storage_example_widget');
Store an object for a specific key
storage.setItem('local_storage_example_widget', map);
The home screen widget renders a TabBar whose selected index is stored to persist over restarts (check app with state persistence)
JsonStorageWidget
renders an input form and uses LocalStorage
to store username and email, when user types in those fields, and a boolean for a checkbox field
password is stored when submit button is clicked and these are filled when app is restarted
If the boolean value is true then user is shown some data instead of form when submit button is clicked or app is restarted (by using another bool)
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:state_persistence/state_persistence.dart';
import 'package:localstorage/localstorage.dart';
void main() => runApp(PersistentStorageApp());
class PersistentStorageApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PersistedAppState(
storage: JsonFileStorage(initialData: {
'tab': 1,
}),
child: MaterialApp(
title: 'Persistent Storage Example App',
theme: ThemeData(primarySwatch: Colors.blue),
home: EgWidget(),
),
);
}
}
class EgWidget extends StatefulWidget {
@override
_EgWidgetState createState() => _EgWidgetState();
}
class _EgWidgetState extends State<EgWidget> with SingleTickerProviderStateMixin {
PersistedData _data;
TabController _controller;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_data = PersistedAppState.of(context);
if (_data != null && _controller == null) {
print("init controller");
_controller = TabController(initialIndex: _data['tab'] ?? 0, vsync: this, length: 4);
_controller.addListener(_onTabChanged);
}
}
void _onTabChanged() {
if (!_controller.indexIsChanging) {
_data['tab'] = _controller.index;
}
}
@override
void dispose() {
_controller?.removeListener(_onTabChanged);
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_data != null) {
return Scaffold(
appBar: AppBar(
title: Text('Persistent Tab Example'),
bottom: TabBar(
controller: _controller,
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Shared Preference'),
Tab(text: 'Json Storage'),
Tab(text: 'Cache Storage'),
],
),
),
body: TabBarView(
controller: _controller,
children: [
Container(color: Colors.cyanAccent[400], child: Center(child: Text('Tab 1', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
Container(color: Colors.amber[600], child: Center(child: Text('Tab 2', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
JsonStorageWidget(),
Container(color: Colors.brown[900], child: Center(child: Text('Tab 1', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
],
)
);
}
else {
return Center(child: CircularProgressIndicator());
}
}
}
class UserData {
String email = '';
String password = '';
String username = '';
bool isIt = true;
toJSONEncodable() {
Map<String, dynamic> map = new Map();
map['email'] = email;
map['password'] = password;
map['username'] = username;
map['isIt'] = isIt;
return map;
}
static UserData from(Map<String, dynamic> map) {
UserData userData = new UserData();
userData.username = map['username'] ;
userData.email = map['email'] ;
userData.password = map['password'] ;
userData.isIt = map['isIt'] ;
return userData;
}
}
Map<String, TextEditingController> getTextEditingControllers(List<String> labels) {
Map<String, TextEditingController> map = new Map();
for(String label in labels) {
map[label] = new TextEditingController();
}
return map;
}
class JsonStorageWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => new JsonStorageWidgetState();
}
class JsonStorageWidgetState extends State<JsonStorageWidget> {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
UserData userData = new UserData();
final Map<String, TextEditingController> tecMap =
getTextEditingControllers(['email','password','username','isIt']);
final LocalStorage storage = new LocalStorage('local_storage_example_widget');
bool showForm = true;
void initState() {
super.initState();
init();
}
void init() async {
storage.ready.then((ready) {
if(mounted)
setState(() {
_getFromStorage();
if(showForm) {
_setFormValues();
}
});
});
}
void submit() {
if (this._formKey.currentState.validate()) {
_formKey.currentState.save();
setState(() {
if(userData.isIt) {
showForm = false;
}
_saveToStorage();
_getFromStorage();
_setFormValues();
});
}
}
_getFromStorage() {
userData = new UserData();
var item = storage.getItem('local_storage_example_widget');
if(item != null) {
userData = UserData.from(item);
showForm = item["showForm"];
}
}
_setFormValues() {
_setControllerValue(tecMap['email'], userData.email);
_setControllerValue(tecMap['password'], userData.password);
_setControllerValue(tecMap['username'], userData.username);
}
_setControllerValue(TextEditingController controller, String value) {
controller.value = TextEditingValue(
text: value,
selection: TextSelection.fromPosition(
TextPosition(offset: value.length),
),
);
}
_saveToStorage() {
var map = userData.toJSONEncodable();
map["showForm"] = showForm;
print(map);
storage.setItem('local_storage_example_widget', map);
}
_clearStorage() async {
await storage.clear();
setState(() {
showForm = true;
_getFromStorage();
_setFormValues();
});
}
Widget getForm() {
return new Form(
key: this._formKey,
child: new ListView(
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(hintText: 'ign', labelText: 'Username'),
controller: tecMap["username"],
onChanged: (String value) { this.userData.username = value; _saveToStorage(); }
),
new TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: new InputDecoration(hintText: 'Email', labelText: 'Enter email'),
onChanged: (String value) { this.userData.email = value; _saveToStorage(); },
controller: tecMap["email"],
),
new TextFormField(
obscureText: true, // To display typed char with *
decoration: new InputDecoration(hintText: 'Password',
labelText: 'Enter password'
),
onSaved: (String value) { this.userData.password = value; _saveToStorage(); },
controller: tecMap["password"],
),
CheckboxListTile(
value: this.userData.isIt,
title: Text("Is it?"),
onChanged: (bool selected) {
setState(() {
this.userData.isIt = selected;
});
},
),
new Container(
child: new RaisedButton(
child: new Text('Login', style: new TextStyle(color: Colors.white),),
onPressed: this.submit,
color: Colors.blue,
),
margin: new EdgeInsets.only(top: 20.0),
),
],
),
);
}
Widget showData() {
return new ListView(
children: <Widget>[
Text("${this.userData.username}"),
Text("${this.userData.email}"),
Text("${this.userData.password}"),
new Container(
child: new RaisedButton(
child: new Text('Clear Storage', style: new TextStyle(color: Colors.white),),
onPressed: this._clearStorage,
color: Colors.blue,
),
margin: new EdgeInsets.only(top: 20.0),
),
],
);
}
@override
Widget build(BuildContext context) {
final Size screenSize = MediaQuery.of(context).size;
return new Scaffold(
appBar: new AppBar(title: new Text('JsonStorageWidget'),),
body: new Container(
padding: new EdgeInsets.all(20.0),
child: showForm? getForm(): showData(),
),
);
}
}
Ensure a supported device is connected or emulator/simulator is started
Go to project directory
Use flutter run
command to run
flutter run
It builds and runs app on an available android/ios device