昨天,我在汽车颤振应用程序中实现了停泊数据库,随后又进行了无聊的颤振开发演示。
数据库工作正常,当我按下心脏IconButton时,汽车将插入到停泊数据库中;当我再次按下按钮(如果汽车在停泊数据库中)时,它将被删除,而且如果我关闭应用程序并重新打开元素仍然保留喜爱。 主要的问题是,当我按下按钮图标时,它仍然保持不变,在我的情况下,心脏带有边框并且不会在整个心脏中摆动。但只有当我上下滚动listview并重建主页时,它才会更改。 我还尝试将.watch()移至查询中的select()之后,但未进行任何更改。
在ui.dart中,我是数据库的流生成器。
非常感谢任何想帮助我的人
这是我的代码:
main.dart
FirebaseUtils databaseUtils;
PageController _pageController;
var _page = 0;
List<Car> carList = new List<Car>();
Query _carQuery;
StreamSubscription<Event> _onAddedSubscription;
StreamSubscription<Event> _onChangedSubscription;
@override
void initState() {
databaseUtils = new FirebaseUtils();
databaseUtils.initState();
_pageController = PageController();
_carQuery = databaseUtils.getRef();
_onAddedSubscription = _carQuery.onChildAdded.listen(_onEntryAdded);
_onChangedSubscription = _carQuery.onChildChanged.listen(_onEntryChanged);
// _scrollController = ScrollController()..addListener(() => setState(() {}));
super.initState();
}
@override
void dispose() {
databaseUtils.dispose();
_pageController.dispose();
_onAddedSubscription.cancel();
_onChangedSubscription.cancel();
super.dispose();
}
void navigationTapped(int page) {
_pageController.animateToPage(
page,
duration: Duration(milliseconds: 300),
curve: Curves.easeIn,
);
}
void onPageChanged(int page) {
setState(() {
this._page = page;
});
}
_onEntryChanged(Event event) {
var oldEntry = carList.singleWhere((entry) {
print(entry.key);
print(event.snapshot.key);
return entry.key == event.snapshot.key;
});
setState(() {
carList[carList.indexOf(oldEntry)] = Car.fromSnapshot(event.snapshot);
});
}
_onEntryAdded(Event event) {
setState(() {
carList.add(Car.fromSnapshot(event.snapshot));
});
}
Widget _showListView() {
if (carList.length > 0) {
return ListView.builder(
shrinkWrap: true,
itemCount: carList.length,
itemBuilder: (BuildContext context, int index) {
return HomePageUi(carList[index]);
});
} else {
return new Center(
child:
CircularProgressIndicator() //new Text("Nessun veicolo presente"),
);
}
}
Widget _showList() {
return new SafeArea(
child: Column(
children: <Widget>[
new Container(
margin: EdgeInsets.symmetric(horizontal: 16.0),
width: MediaQuery.of(context).size.width,
height: kExpandedHeight,
child: MyFlexiableAppBar()),
new Expanded(child: _showListView())
],
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> _myPages = [
_showList(),
Container(),
FavoritesScreen(carList)
];
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: AppTheme.darkerBlue,
fixedColor: AppTheme.orangeText,
unselectedItemColor: Colors.white,
showSelectedLabels: false,
showUnselectedLabels: false,
onTap: navigationTapped,
currentIndex: _page,
items: [
new BottomNavigationBarItem(
title: new Text(''), icon: new Icon(Icons.home)),
new BottomNavigationBarItem(
title: new Text(''),
icon: IconButton(
icon: Icon(Icons.search),
onPressed: () async {
final Car searchRes = await showSearch<Car>(
context: context, delegate: searchPage(carList));
if (searchRes != null)
Navigator.of(context).push(new PageRouteBuilder(
pageBuilder: (_, __, ___) => new CarPage(searchRes)));
},
)),
new BottomNavigationBarItem(
title: new Text(''), icon: new Icon(Icons.favorite_border))
],
),
body: new PageView.builder(
controller: _pageController,
onPageChanged: onPageChanged,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
itemCount: _myPages.length,
itemBuilder: (BuildContext context, int position) =>
_myPages[position]),
);
ui.dart
final _favoriteButton = StreamBuilder<bool>(
stream: MyDatabase().isFavorite(int.parse(car.key)),
builder: (context, snapshot) {
print("rebuilding");
if (snapshot.hasData && snapshot.data) {
return IconButton(
onPressed: () =>
MyDatabase().removeFavorite(int.parse(car.key)),
icon: Icon(Icons.favorite, color: AppTheme.orangeText));
}
return IconButton(
onPressed: () => MyDatabase().addFavorite(car),
icon: Icon(Icons.favorite_border, color: AppTheme.darkBlue));
});
final carCardContent = new Padding(
padding: EdgeInsets.all(10.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(car.title,
style: headerTextStyle, textAlign: TextAlign.center),
new SizedBox(height: 5.0),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text(
car.price,
style: headerTextStyle,
),
new Text(" - ", style: regularTextStyle),
new Text("Iva Esclusa",
style: regularTextStyle.copyWith(
decoration: TextDecoration.underline))
],
),
new SizedBox(height: 5.0),
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
carThumb,
SizedBox(width: 10.0),
carDetails,
],
),
SizedBox(height: 5.0),
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text("Aggiungimi ai prefereriti ", style: subHeaderTextStyle),
_favoriteButton
],
),
],
),
);
final carCard = Container(
child: carCardContent,
decoration: new BoxDecoration(
color: AppTheme.nearlyWhite,
shape: BoxShape.rectangle,
borderRadius: new BorderRadius.circular(8.0),
boxShadow: <BoxShadow>[
new BoxShadow(
color: Colors.black12,
blurRadius: 5.0,
offset: new Offset(0.0, 6.0))
]),
);
favorites_database.dart
import 'package:moor_flutter/moor_flutter.dart';
import 'package:moor/moor.dart';
import 'package:pastore_app/car.dart';
// assuming that your file is called filename.dart. This will give an error at first,
// but it's needed for moor to know about the generated code
part 'favorites_database.g.dart';
// this will generate a table called "Favorites" for us. The rows of that table will
// be represented by a class called "Favorites".
class Favorites extends Table {
IntColumn get id => integer().customConstraint('UNIQUE')();
TextColumn get rif => text()();
TextColumn get title => text()();
}
// this annotation tells moor to prepare a database class that uses both of the
// tables we just defined. We'll see how to use that database class in a moment.
@UseMoor(tables: [Favorites])
class MyDatabase extends _$MyDatabase {
MyDatabase()
// Specify the location of the database file
: super((FlutterQueryExecutor.inDatabaseFolder(
path: 'db1.sqlite',
// Good for debugging - prints SQL in the console
logStatements: true,
)));
// Bump this when changing tables and columns.
// Migrations will be covered in the next part.
@override
int get schemaVersion => 1;
Future<List<Favorite>> get allFavoritesEntries => select(favorites).get();
Stream<List<Favorite>> get allFavoritesWatch => select(favorites).watch();
// watches all Favorites entries in a given category. The stream will automatically
// emit new items whenever the underlying data changes.
/*
Stream<bool> isFavorite(int rifId) {
return (select(favorites)..where((favorite) => favorite.id.equals(rifId)))
.watch()
.map((favoritesList) => favoritesList.length >= 1);
}
*/
void addFavorite(Car car) {
var favorite =
Favorite(id: int.parse(car.key), rif: car.rif, title: car.title);
into(favorites).insert(favorite);
}
void removeFavorite(int keyId) =>
(delete(favorites)..where((t) => t.id.equals(keyId))).go();
Stream<bool> isFavorite(int keyId) {
return (select(favorites).watch().map((favoritesList) =>
favoritesList.where((favorite) => favorite.id == keyId).length >= 1));
}
}