mvvm_provider 1.0.1 mvvm_provider: ^1.0.1 copied to clipboard
Simple and effective architecture MVVM using Provider to approach Flutter with lifecycles
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mvvm_provider/base/FlutterView.dart';
import 'package:mvvm_provider/base/FlutterViewModel.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(ExampleApp());
class ExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MVVM Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeView(),
);
}
}
class HomeView extends FlutterView {
@override
FlutterViewState<FlutterView, FlutterViewModel> getViewState() {
return _HomeViewState();
}
}
class _HomeViewState extends FlutterViewState<HomeView, HomeViewModel> {
@override
void onViewModelReady() {
debugPrint('-------------_HomeViewState onCreate');
viewModel.getTodoList();
}
@override
void onResume() {
super.onResume();
debugPrint('-------------_HomeViewState onResume');
}
@override
void onPause() {
super.onPause();
debugPrint('-------------_HomeViewState onPause');
}
@override
Widget getView() {
return Scaffold(
backgroundColor: Colors.grey[300],
appBar: AppBar(
title: Text('MVVM Example'),
),
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: viewModel.isLoading
? Center(child: CupertinoActivityIndicator())
: viewModel.list.isEmpty
? Center(child: Text('No data'))
: ListView.separated(
padding: EdgeInsets.all(16),
itemBuilder: (_, index) =>
_todoItem(viewModel.list[index]),
separatorBuilder: (_, __) => SizedBox(height: 16),
itemCount: viewModel.list.length)),
Container(
color: Colors.grey,
width: double.infinity,
height: kToolbarHeight,
child: Center(
child: FlatButton(
onPressed: () {
viewModel.addTodo(Todo(
DateTime.now().millisecondsSinceEpoch,
'Hi ${DateTime.now().millisecondsSinceEpoch}'));
},
child: Text('Add Todo')),
),
)
],
),
),
);
}
@override
HomeViewModel getViewModel() {
return HomeViewModel();
}
Widget _todoItem(Todo item) {
return Container(
padding: EdgeInsets.all(16),
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(child: Text(item.todo)),
SizedBox(width: 8),
FlatButton(
onPressed: () {
viewModel.deleteTodo(item);
},
child: Text('Delete'))
],
),
);
}
}
class HomeViewModel extends FlutterViewModel {
List<Todo> list = [];
void getTodoList() async {
final data = await _getTodos();
list.clear();
list.addAll(data);
isLoading = false;
notifyListeners();
}
void addTodo(Todo todo) async {
final data = await _getTodos();
data.add(todo);
await _setTodos(data);
getTodoList();
}
void deleteTodo(Todo todo) async {
final data = await _getTodos();
data.removeWhere((element) => element.id == todo.id);
await _setTodos(data);
getTodoList();
}
Future<List<Todo>> _getTodos() async {
final sp = await SharedPreferences.getInstance();
if (!sp.containsKey('todos') || sp.getString('todos') == null) return [];
final rawJson = sp.getString('todos');
final parsedJsonList = jsonDecode(rawJson) as List<dynamic>;
return parsedJsonList.map((json) => Todo.fromJson(json)).toList();
}
Future<List<Todo>> _setTodos(List<Todo> data) async {
final sp = await SharedPreferences.getInstance();
if (data == null || data.isEmpty) {
await sp.setString('todos', null);
return data;
}
final parsedJsonList = data.map((single) => single.toJson()).toList();
await sp.setString('todos', jsonEncode(parsedJsonList));
return data;
}
}
class Todo {
int id;
String todo;
Todo(this.id, this.todo);
Todo.fromJson(Map<String, dynamic> json)
: id = json['id'],
todo = json['todo'];
Map<String, dynamic> toJson() => {'id': id, 'todo': todo};
}