【发布时间】:2020-04-21 23:39:56
【问题描述】:
我有一个应用程序,它在到达第二页并根据此信息构建 ui 时仅检查一个值是否存在,如果我以常规方式执行此操作,则需要时间并在页面前一秒出现空错误还构建了我必须比我想要的更频繁地读取数据库,所以有没有办法在连接到互联网时仅从离线数据库中检查数据?
编辑:
总而言之,我有一个主页,它显示整个列表属于使用 ListView.Builder 记录为收藏的用户,用户只能看到并能够从该屏幕中删除它们,添加任何内容到列表的唯一方法是从我的第二页,我在构建时检查是否添加了项目,如果它添加了我最喜欢的按钮形状更改,如果它不是同一个按钮,则在按下时将其删除,将其保存到收藏夹。您可以查看以下代码(相关部分)
主页:
class MyFirstPage extends StatefulWidget {
MyFirstPage({Key key, this.auth, this.userId, this.logoutCallback, this.user})
: super(key: key);
final BaseAuth auth;
final VoidCallback logoutCallback;
final String userId;
final FirebaseUser user;
static String routeName = "/MyFirstPage";
@override
_MyFirstPageState createState() => new _MyFirstPageState();
}
class _MyFirstPageState extends State<MyFirstPage> {
String userId;
List<Movies> _moviesList;
Query _moviesQuery;
final FirebaseDatabase _database = FirebaseDatabase.instance;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
StreamSubscription<Event> _onMoviesAddedSubscription;
StreamSubscription<Event> _onMoviesChangedSubscription;
AuthStatus authStatus;
@override
void initState() {
// TODO: implement initState
super.initState();
_moviesList = new List();
_moviesQuery = _database
.reference()
.child("movies")
.orderByChild("userId")
.equalTo(widget.userId);
_onMoviesAddedSubscription = _moviesQuery.onChildAdded.listen(onEntryAdded);
_onMoviesChangedSubscription =
_moviesQuery.onChildChanged.listen(onEntryChanged);
widget.auth.getCurrentUser().then((user) {
setState(() {
if (user != null) {
userId = user?.uid;
}
authStatus =
user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
});
});
}
void dispose() {
_onMoviesAddedSubscription.cancel();
_onMoviesChangedSubscription.cancel();
super.dispose();
}
onEntryChanged(Event event) {
var oldEntry = _moviesList.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
_moviesList[_moviesList.indexOf(oldEntry)] =
Movies.fromSnapshot(event.snapshot);
});
}
onEntryAdded(Event event) {
setState(() {
_moviesList.add(Movies.fromSnapshot(event.snapshot));
});
}
signOut() async {
try {
await widget.auth.signOut();
widget.logoutCallback();
} catch (e) {
print(e);
}
}
updateMovies(Movies movies) {
//Toggle completed
movies.watched = !movies.watched;
if (movies != null) {
_database.reference().child("movies").set(movies.toJson());
}
}
deleteMovies(String moviesId, int index) {
_database.reference().child("movies").child(moviesId).remove().then((_) {
print("Delete $moviesId successful");
setState(() {
_moviesList.removeAt(index);
});
});
}
...
ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _moviesList.length,
itemBuilder: (BuildContext context, int index) {...}
第二页:
class MovieDetailPage extends StatefulWidget {
MovieDetailPage({Key key, this.title, this.auth, this.userId, this.user})
: super(key: key);
final BaseAuth auth;
final String userId;
final FirebaseUser user;
static String routeName = "/MovieDetailPage";
final String title;
@override
_MovieDetailPageState createState() => _MovieDetailPageState();}
class _MovieDetailPageState extends State<MovieDetailPage> {
final GlobalKey<InnerDrawerState> _innerDrawerKey = GlobalKey<InnerDrawerState>();
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
Future<void> recorded(String idname) async{
final dbRef = await FirebaseDatabase.instance.reference().child(
"movies").orderByChild("unique").equalTo(idname).once();
return dbRef;
}
String userId;
final FirebaseDatabase _database = FirebaseDatabase.instance;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
List<Movies> _moviesList;
AuthStatus authStatus;
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) =>
getNamePreferences().then(updateName));
});
_moviesList = new List();
widget.auth.getCurrentUser().then((user) {
if (user != null) {
userId = user?.uid;
}});
}
//I have a FutureBuilder for getting details
FutureBuilder<Payload>(
future: getData(_name),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done && firstRun == true)
return Center(child: Image.asset("images/dice.gif"));
if (snapshot.connectionState == ConnectionState.done)
if (snapshot.hasError)
{....
// and I have a second FutureBuilder for my FAB because its change according to data
floatingActionButton: FutureBuilder(
future: recorded(userId+snapshot.data.imdbId),
builder: (context, snapshots) {
return Container(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
heroTag: 3,
backgroundColor: Colors.blueGrey.withOpacity(0.4),
onPressed: ()
{
Movies movies = new Movies(snapshot.data.imdbId, snapshot.data.originalTitle, snapshot.data.posterPath, snapshot.data.backdropPath, snapshot.data.releaseDate, snapshot.data.title, snapshot.data.voteAverage, snapshot.data.genres, false, userId, userId+snapshot.data.imdbId);
snapshots.data.value == null ?
_database.reference().child("movies").push().set(movies.toJson())
:
FirebaseDatabase.instance.reference()
.child('movies')
.orderByChild('unique')
.equalTo(userId+snapshot.data.imdbId)
.once()
.then((DataSnapshot snapshot) {
Map<dynamic, dynamic> children = snapshot.value;
children.forEach((key, value) {
FirebaseDatabase.instance.reference()
.child('movies')
.child(key)
.remove();
});
});
setState(() {});
},
child: Icon(snapshots.data.value != null ? Icons.favorite : Icons.favorite_border )
)
],
),
);
}
),
【问题讨论】:
-
我们能看看你目前的做法吗?它们是等待未来响应的多种方式。给我们更多细节
-
我在原始帖子中添加了更多信息和代码示例。
标签: flutter firebase-realtime-database