-
Notifications
You must be signed in to change notification settings - Fork 146
Support for Streams from query objects #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3ed735f
8a6bc25
502edad
a5d177e
372de28
f19c4e2
bd6f3ee
70a038c
b3e5fda
113fb55
3a6184d
0c79ef0
e00bdfd
2a4c6f8
80b1256
6aacbf9
5d69ebf
3c9698f
b3483ed
63600bb
e62ad2a
cd4a391
298169e
c32df43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,9 @@ import 'package:objectbox/objectbox.dart'; | |
import 'package:intl/intl.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'objectbox.g.dart'; | ||
import 'package:objectbox/src/observable.dart'; | ||
import 'dart:async'; | ||
import 'dart:io'; | ||
|
||
@Entity() | ||
class Note { | ||
|
@@ -11,14 +14,17 @@ class Note { | |
|
||
String text; | ||
String comment; | ||
int date; // TODO: use DateTime class | ||
int date; | ||
|
||
Note(); | ||
|
||
Note.construct(this.text) { | ||
date = DateTime.now().millisecondsSinceEpoch; | ||
print('constructed date: $date'); | ||
} | ||
|
||
get dateFormat => DateFormat('dd.MM.yyyy hh:mm:ss') | ||
.format(DateTime.fromMillisecondsSinceEpoch(date)); | ||
} | ||
|
||
void main() => runApp(MyApp()); | ||
|
@@ -43,143 +49,169 @@ class MyHomePage extends StatefulWidget { | |
_MyHomePageState createState() => _MyHomePageState(); | ||
} | ||
|
||
class _MyHomePageState extends State<MyHomePage> { | ||
final _noteInputController = TextEditingController(); | ||
class ViewModel { | ||
Store _store; | ||
Box<Note> _box; | ||
List<Note> _notes = []; | ||
Query<Note> _query; | ||
|
||
ViewModel(Directory dir) { | ||
_store = Store(getObjectBoxModel(), directory: dir.path + '/objectbox'); | ||
_box = Box<Note>(_store); | ||
|
||
final dateProp = Note_.date; | ||
final dummyCondition = dateProp.greaterThan(0); | ||
|
||
_query = _box | ||
.query(dummyCondition) | ||
greenrobot-team marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.order(dateProp, flags: Order.descending) | ||
.build(); | ||
} | ||
|
||
void addNote(Note note) => _box.put(note); | ||
|
||
void removeNote(Note note) => _box.remove(note.id); | ||
|
||
get queryStream => _query.findStream(); | ||
|
||
get allNotes => _query.find(); | ||
|
||
void dispose() { | ||
_query.close(); | ||
_store.unsubscribe(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this should be part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's called by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, sorry, should have been more clear: was talking about not even exposing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. |
||
_store.close(); | ||
} | ||
} | ||
|
||
class _MyHomePageState extends State<MyHomePage> { | ||
final _noteInputController = TextEditingController(); | ||
final _listController = StreamController<List<Note>>(sync:true); | ||
Stream<List<Note>> _stream; | ||
ViewModel _vm; | ||
|
||
void _addNote() { | ||
if (_noteInputController.text.isEmpty) return; | ||
final newNote = Note.construct(_noteInputController.text); | ||
newNote.id = _box.put(newNote); | ||
setState(() => _notes.add(newNote)); | ||
_vm.addNote(Note.construct(_noteInputController.text)); | ||
_noteInputController.text = ''; | ||
} | ||
|
||
void _removeNote(int index) { | ||
_box.remove(_notes[index].id); | ||
setState(() => _notes.removeAt(index)); | ||
} | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
getApplicationDocumentsDirectory().then((dir) { | ||
_store = Store(getObjectBoxModel(), directory: dir.path + '/objectbox'); | ||
_box = Box<Note>(_store); | ||
final notesFromDb = _box.getAll(); | ||
setState(() => _notes = notesFromDb); | ||
// TODO: don't show UI before this point | ||
_vm = ViewModel(dir); | ||
_stream = _listController.stream; | ||
|
||
setState(() {}); | ||
|
||
_listController.add(_vm.allNotes); | ||
_listController.addStream(_vm.queryStream); | ||
}); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_noteInputController.dispose(); | ||
_listController.close(); | ||
_vm.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: Text(widget.title), | ||
), | ||
body: Column( | ||
children: <Widget>[ | ||
Padding( | ||
padding: EdgeInsets.all(20.0), | ||
child: Row( | ||
children: <Widget>[ | ||
Expanded( | ||
GestureDetector Function(BuildContext, int) _itemBuilder(List<Note> notes) { | ||
return (BuildContext context, int index) { | ||
return GestureDetector( | ||
onTap: () => _vm.removeNote(notes[index]), | ||
child: Row( | ||
children: <Widget>[ | ||
Expanded( | ||
child: Container( | ||
child: Padding( | ||
padding: | ||
EdgeInsets.symmetric(vertical: 18.0, horizontal: 10.0), | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: <Widget>[ | ||
Padding( | ||
padding: EdgeInsets.only(right: 10.0), | ||
child: TextField( | ||
decoration: | ||
InputDecoration(hintText: 'Enter new note'), | ||
controller: _noteInputController, | ||
Text( | ||
notes[index].text, | ||
style: TextStyle( | ||
fontSize: 15.0, | ||
), | ||
), | ||
Padding( | ||
padding: EdgeInsets.only(top: 10.0, right: 10.0), | ||
child: Align( | ||
alignment: Alignment.centerRight, | ||
child: Text( | ||
'Click a note to remove it', | ||
style: TextStyle( | ||
fontSize: 11.0, | ||
color: Colors.grey, | ||
), | ||
padding: EdgeInsets.only(top: 5.0), | ||
child: Text( | ||
'Added on ${notes[index].dateFormat}', | ||
style: TextStyle( | ||
fontSize: 12.0, | ||
), | ||
), | ||
), | ||
], | ||
), | ||
), | ||
Column( | ||
children: <Widget>[ | ||
RaisedButton( | ||
onPressed: _addNote, | ||
child: Text('Add'), | ||
) | ||
], | ||
) | ||
], | ||
decoration: BoxDecoration( | ||
border: Border(bottom: BorderSide(color: Colors.black12))), | ||
), | ||
), | ||
), | ||
Expanded( | ||
child: ListView.builder( | ||
shrinkWrap: true, | ||
padding: EdgeInsets.symmetric(horizontal: 20.0), | ||
itemCount: _notes.length, | ||
itemBuilder: (BuildContext context, int index) { | ||
return GestureDetector( | ||
onTap: () => _removeNote(index), | ||
child: Row( | ||
children: <Widget>[ | ||
Expanded( | ||
child: Container( | ||
child: Padding( | ||
padding: EdgeInsets.symmetric( | ||
vertical: 18.0, horizontal: 10.0), | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: <Widget>[ | ||
Text( | ||
_notes[index].text, | ||
style: TextStyle( | ||
fontSize: 15.0, | ||
), | ||
), | ||
Padding( | ||
padding: EdgeInsets.only(top: 5.0), | ||
child: Text( | ||
"Added on ${DateFormat('dd.MM.yyyy hh:mm:ss').format(DateTime.fromMillisecondsSinceEpoch(_notes[index].date))}", | ||
style: TextStyle( | ||
fontSize: 12.0, | ||
), | ||
), | ||
), | ||
], | ||
), | ||
], | ||
), | ||
); | ||
}; | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: Text(widget.title), | ||
), | ||
body: Column(children: <Widget>[ | ||
Padding( | ||
padding: EdgeInsets.all(20.0), | ||
child: Row( | ||
children: <Widget>[ | ||
Expanded( | ||
child: Column( | ||
children: <Widget>[ | ||
Padding( | ||
padding: EdgeInsets.symmetric(horizontal: 10.0), | ||
child: TextField( | ||
decoration: | ||
InputDecoration(hintText: 'Enter a new note'), | ||
controller: _noteInputController, | ||
onSubmitted: (String) => _addNote() | ||
), | ||
), | ||
Padding( | ||
padding: EdgeInsets.only(top: 10.0, right: 10.0), | ||
child: Align( | ||
alignment: Alignment.centerRight, | ||
child: Text( | ||
'Tap a note to remove it', | ||
style: TextStyle( | ||
fontSize: 11.0, | ||
color: Colors.grey, | ||
), | ||
decoration: BoxDecoration( | ||
border: Border( | ||
bottom: BorderSide(color: Colors.black12))), | ||
), | ||
), | ||
], | ||
), | ||
); | ||
}, | ||
), | ||
), | ||
], | ||
), | ||
) | ||
], | ||
), | ||
], | ||
), | ||
), | ||
Expanded( | ||
child: StreamBuilder<List<Note>>( | ||
stream: _stream, | ||
builder: (context, snapshot) { | ||
return ListView.builder( | ||
shrinkWrap: true, | ||
padding: EdgeInsets.symmetric(horizontal: 20.0), | ||
itemCount: snapshot.hasData ? snapshot.data.length : 0, | ||
itemBuilder: _itemBuilder(snapshot.data)); | ||
})) | ||
]), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason why rxdart? Are there other alternatives you've considered?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be the most popular one, and it supports Stream which is more idiomatic, by way of extensions. I expose a stream property from an observable query for that reason.