我首先清除了所有缓存记录。当我第一次登录执行我的APP时,代码弹出一个错误说foreach方法等于null,但是我跳转到其他页面时可以读取数据。我无法理解原因。我该怎么做才能解决这个问题?
这是我的代码
路径参考
advanced() async {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser currentUser = await _auth.currentUser();
final db = Firestore.instance;
(new Offline(currentUser.uid)).getData().then((data) { //call data at this line
var vip = new Vip(currentUser.uid);
vip.isVip().then((vipStatus) {
if (vipStatus) {
setState(() {
_advancedWidget = Container(
child: Center(
child: Container(
padding: const EdgeInsets.only(left: 8.0, top: 8),
child: Text(
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
style: AppTheme.getTextStyle(themeData.textTheme.subtitle1,
fontWeight: FontWeight.w500),
maxLines: 5,
),
),
),
);
});
for (var course in data['course']) {
if (course['start'].millisecondsSinceEpoch <=
DateTime.now().millisecondsSinceEpoch &&
DateTime(
DateTime.fromMillisecondsSinceEpoch(
course['start'].millisecondsSinceEpoch)
.year,
DateTime.fromMillisecondsSinceEpoch(
course['start'].millisecondsSinceEpoch)
.month,
DateTime.fromMillisecondsSinceEpoch(
course['start'].millisecondsSinceEpoch)
.day +
course['period'] -
1,
23,
59,
00)
.millisecondsSinceEpoch >=
DateTime.now().millisecondsSinceEpoch) {
// 期間內
final dayFromRegister = ((DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day).millisecondsSinceEpoch -
course['start'].millisecondsSinceEpoch) /
1000 /
60 /
60 /
24)
.round();
_advancedList.clear();
for (var i = 0; i < 28; i++) {
DateTime date = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day)
.add(new Duration(days: (dayFromRegister - i) * -1));
List<dynamic> result = data['records'].reversed.toList();
int completion = 0;
for (var r in result) {
if (r['year'] == date.year &&
r['month'] == date.month &&
r['day'] == date.day &&
r['time_period'] == 'am') {
completion += 1;
break;
}
}
for (var r in result) {
if (r['year'] == date.year &&
r['month'] == date.month &&
r['day'] == date.day &&
r['time_period'] == 'pm') {
completion += 1;
break;
}
}
setState(() {
_advancedList.add({
'index': i,
'name': '第 ${i + 1} 天',
'date':
'${date.year}/${date.month < 10 ? '0${date.month}' : date.month}/${date.day < 10 ? '0${date.day}' : date.day}',
'_date': date,
'completion': completion,
});
});
}
setState(() {
_advancedWidget = Container(
child: Container(
child: ListView(
children: <Widget>[
if (data['advanceType'] != null)
Container(
margin: EdgeInsets.all(4),
child: Center(
child: Text('進階肌膚分類: ${data['advanceType']}', style: TextStyle(fontSize: 18),),
),
),
for (var AList in _advancedList)
InkWell(
child: Card(
margin: EdgeInsets.all(4),
color: AList['completion'] > 0
? Colors.lightGreen
: themeData.cardColor,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(
left: 8.0, top: 8),
child: Text(
'${AList['name']}',
style: AppTheme.getTextStyle(
themeData.textTheme.subtitle1,
fontWeight: FontWeight.w500),
maxLines: 5,
),
),
Container(
padding: const EdgeInsets.only(
left: 8.0, top: 8, bottom: 8),
child: Text(
'${AList['date']}',
style: AppTheme.getTextStyle(
themeData.textTheme.subtitle2,
fontWeight: FontWeight.w400),
maxLines: 5,
),
),
],
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Icon(
AList['completion'] == 0
? MdiIcons.circleOutline
: AList['completion'] == 1
? MdiIcons.circleHalfFull
: MdiIcons.circle,
color: themeData.colorScheme.onBackground
.withAlpha(200),
size: 24.0,
),
),
],
),
),
onTap: () {
if (DateTime.parse(AList['_date'].toString())
.isBefore(DateTime.now())) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Advanced(
index: AList['index'],
date: AList['_date'])));
}
},
)
],
),
),
);
});
}
}
} else {
// 期間內
_advancedList.clear();
for (var i = 0; i < 28; i++) {
DateTime date = DateTime.now().add(new Duration(days: i));
setState(() {
_advancedList.add({
'index': i,
'name': '第 ${i + 1} 天',
'date':
'${date.year}/${date.month < 10 ? '0${date.month}' : date.month}/${date.day < 10 ? '0${date.day}' : date.day}',
'_date': date,
'completion': 0,
});
});
}
setState(() {
_advancedWidget = Container(
child: Container(
child: ListView.builder(
itemCount: _advancedList.length,
itemBuilder: (context, index) {
return InkWell(
child: Card(
margin: EdgeInsets.all(4),
color: _advancedList[index]['completion'] > 0
? Colors.lightGreen
: themeData.cardColor,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(
left: 8.0, top: 8),
child: Text(
'${_advancedList[index]['name']}',
style: AppTheme.getTextStyle(
themeData.textTheme.subtitle1,
fontWeight: FontWeight.w500),
maxLines: 5,
),
),
Container(
padding: const EdgeInsets.only(
left: 8.0, top: 8, bottom: 8),
child: Text(
'${_advancedList[index]['date']}',
style: AppTheme.getTextStyle(
themeData.textTheme.subtitle2,
fontWeight: FontWeight.w400),
maxLines: 5,
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Icon(
_advancedList[index]['completion'] == 0
? MdiIcons.circleOutline
: _advancedList[index]['completion'] == 1
? MdiIcons.circleHalfFull
: MdiIcons.circle,
color: themeData.colorScheme.onBackground
.withAlpha(200),
size: 24.0,
),
),
],
),
),
onTap: () {},
);
},
),
),
);
});
}
});
});
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:sembast/sembast_io.dart';
import 'package:sembast/timestamp.dart' as ts;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sembast/sembast.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
class Offline {
String _uid; //使用者 ID
DocumentReference _userDoc;
Offline(this._uid) {
final db = Firestore.instance;
if (this._uid != null) this._userDoc = db.collection('users').document(this._uid);
}
Future<void> run() async {
final path = await this.checkPath();
switch (path) {
case 1:
this.localToRemote();
break;
case 2:
this.remoteToLocal();
break;
default:
// none;
}
}
Future<int> checkPath() async {
final data = await _userDoc.get();
var prefs = await SharedPreferences.getInstance();
int originalRemoteDataDate = data.data['remote_data_date'] == null ? 0 : data.data['remote_data_date'];
int originalLocalDataDate = prefs.getInt('_local_data_date') == null ? 0 : prefs.getInt('_local_data_date');
if (originalRemoteDataDate == 0) {
int newRemoteDataDate = DateTime.now().millisecondsSinceEpoch.toInt();
await Firestore.instance.collection('users').document(_uid).updateData({'remote_data_date': newRemoteDataDate});
originalRemoteDataDate = newRemoteDataDate;
}
if (originalLocalDataDate > originalRemoteDataDate) {
// 本地至雲端
return 1;
} else if (originalLocalDataDate < originalRemoteDataDate) {
// 雲端至本地
return 2;
} else {
// 不動作
return 0;
}
}
Future<void> localToRemote() async {
var prefs = await SharedPreferences.getInstance();
int originalLocalDataDate = prefs.getInt('_local_data_date') == null ? 0 : prefs.getInt('_local_data_date');
Directory appDocDirectory = await getApplicationDocumentsDirectory();
String dbPath = appDocDirectory.path + '/temp$_uid.db';
DatabaseFactory dbFactory = databaseFactoryIo;
Database db = await dbFactory.openDatabase(dbPath);
var store = StoreRef<String, dynamic>.main();
var vip = await store.record('vip').get(db);
var course = await store.record('course').get(db);
var records = await store.record('records').get(db);
var advanceType = await store.record('advanceType').get(db);
var basicType = await store.record('basicType').get(db);
var courseList = [];
await course.forEach((each) {
courseList.add({
'period': each['period'],
'records': each['records'],
'resultData': each['resultData'],
'start': DateTime.fromMicrosecondsSinceEpoch(each['start'].microsecondsSinceEpoch),
'survey': each['survey']
});
});
await _userDoc.updateData({
'vip': vip!=false?{
'buy_time': DateTime.fromMicrosecondsSinceEpoch(vip['buy_time'].microsecondsSinceEpoch),
'expire_time': DateTime.fromMicrosecondsSinceEpoch(vip['expire_time'].microsecondsSinceEpoch),
'status': vip['status']
}:false,
'course': courseList,
'records': records,
'advanceType': advanceType,
'basicType': basicType,
'remote_data_date': originalLocalDataDate,
});
//await db.close();
}
Future<void> remoteToLocal() async {
final data = await _userDoc.get();
var prefs = await SharedPreferences.getInstance();
int originalRemoteDataDate = data.data['remote_data_date'] == null ? 0 : data.data['remote_data_date'];
Directory appDocDirectory = await getApplicationDocumentsDirectory();
String dbPath = appDocDirectory.path + '/temp$_uid.db';
DatabaseFactory dbFactory = databaseFactoryIo;
Database db = await dbFactory.openDatabase(dbPath);
var store = StoreRef<String, dynamic>.main();
await store.record('vip').put(db, data.data['vip']!=false?{
'buy_time': ts.Timestamp.parse(data.data['vip']['buy_time'].toDate().toString()),
'expire_time': ts.Timestamp.parse(data.data['vip']['expire_time'].toDate().toString()),
'status': data.data['vip']['status']
}:false);
var course = List();
await data.data['course'].forEach((each) {
course.add({
'period': each['period'],
'records': each['records'],
'resultData': each['resultData'],
'start': ts.Timestamp.parse(each['start'].toDate().toString()),
'survey': each['survey'],
});
});
await store.record('course').put(db, course);
await store.record('records').put(db, data.data['records']);
await store.record('advanceType').put(db, data.data['advanceType']);
await store.record('basicType').put(db, data.data['basicType']);
await store.record('staff').put(db, data.data['staff']);
await store.record('admin').put(db, data.data['admin']);
await prefs.setInt('_local_data_date', originalRemoteDataDate);
//await db.close();
}
Future<Map<String, dynamic>> getData() async {
Directory appDocDirectory = await getApplicationDocumentsDirectory();
String dbPath = appDocDirectory.path + '/temp$_uid.db';
DatabaseFactory dbFactory = databaseFactoryIo;
Database db = await dbFactory.openDatabase(dbPath);
var store = StoreRef<String, dynamic>.main();
var vip = await store.record('vip').get(db);
var course = await store.record('course').get(db);
var records = await store.record('records').get(db);
var advanceType = await store.record('advanceType').get(db);
var basicType = await store.record('basicType').get(db);
var staff = await store.record('staff').get(db);
var admin = await store.record('admin').get(db);
var courseList = List();
await course.forEach((each) {
courseList.add({
'period': each['period'],
'records': each['records'],
'resultData': each['resultData'],
'start': DateTime.fromMicrosecondsSinceEpoch(each['start'].microsecondsSinceEpoch),
});
});
if (staff == true || admin == true) {
return {
'staff': staff,
'admin': admin,
};
} else {
return {
'vip': vip!=false?{
'buy_time': DateTime.fromMicrosecondsSinceEpoch(vip['buy_time'].microsecondsSinceEpoch),
'expire_time': DateTime.fromMicrosecondsSinceEpoch(vip['expire_time'].microsecondsSinceEpoch),
'status': vip['status']
}:false,
'course': courseList,
'records': records,
'advanceType': advanceType,
'basicType': basicType,
'staff': staff,
'admin': admin,
};
}
}
Future<void> updateData(Map<String, dynamic> updateData) async {
updateData.forEach((key, value) async {
Directory appDocDirectory = await getApplicationDocumentsDirectory();
String dbPath = appDocDirectory.path + '/temp$_uid.db';
DatabaseFactory dbFactory = databaseFactoryIo;
Database db = await dbFactory.openDatabase(dbPath);
var store = StoreRef<String, dynamic>.main();
await store.record(key).update(db, value);
//await db.close();
var prefs = await SharedPreferences.getInstance();
await prefs.setInt('_local_data_date', DateTime.now().millisecondsSinceEpoch.toInt());
});
}
Future<void> newSession() async {
var prefs = await SharedPreferences.getInstance();
await prefs.setInt('_local_data_date', 0);
//Directory appDocDirectory = await getApplicationDocumentsDirectory();
//String dbPath = appDocDirectory.path + '/temp.db';
//await File(dbPath).delete();
}
}
请帮帮我,谢谢大家