main.dart
import 'package:flutter/material.dart';
import 'package:worldtime/pages/home.dart';
import 'package:worldtime/pages/loading.dart';
import 'package:worldtime/pages/choose_location.dart';
void main() {
runApp(MaterialApp(
//initialRoute is used to declare the default screen of the app
//it is the alternate of the home property of the material app
//home property can also be used for the same purpose
initialRoute: '/',
//routes is used to move between the screens
//route works like dictionary in python with routes as key and context as value
//context locates the current position of the widget in the widget tree
//on a route as a key and context as value it routes return the class of the screen
routes: {
'/': (context) => Loading(),
'/home': (context) => Home(),
'/location': (context) => ChooseLocation(),
},
));
}
home.dart
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
//Creating empty map to receive data from loading screen
Map data = {};
@override
Widget build(BuildContext context) {
//Receive the actual argument in empty data map from loading screen
//We are not using setState as this is first time Build function running and no widget has been yet returned
//and checks if after pop the loading screen we should store the dat
data = data.isNotEmpty ? data : ModalRoute.of(context).settings.arguments;
//Set Background
String bgImage = data['isDaytime'] ? 'day.jpg' : 'night.jpg';
Color bgColor = data['isDaytime'] ? Colors.grey[900] : Colors.black;
return Scaffold(
backgroundColor: bgColor,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/$bgImage'),
fit: BoxFit.cover,
)),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 120.0, 0, 0),
child: Column(
children: <Widget>[
FlatButton.icon(
//long async function to go to loading screen
//select option and get the data
//pop the loading screen and
//come back to home screen with data
onPressed: () async {
dynamic result = await Navigator.pushNamed(context, '/location');
setState(() {
data = {
'time': result['time'],
'location': result['location'],
'isDaytime': result['isDaytime'],
'flag': result['flag'],
};
});
},
icon: Icon(
Icons.edit_location,
color: Colors.white60,
),
label: Text(
'Edit Location',
style: TextStyle(color: Colors.white60),
),
),
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
data['location'],
style: TextStyle(
fontSize: 28.0,
letterSpacing: 2.0,
color: Colors.white,
),
),
],
),
SizedBox(height: 20.0),
Text(
data['time'],
style: TextStyle(
fontSize: 66.0,
color: Colors.white,
),
)
],
),
),
),
),
);
}
}
choose_location.dart
import 'package:flutter/material.dart';
import 'package:worldtime/services/world_time.dart';
class ChooseLocation extends StatefulWidget {
@override
_ChooseLocationState createState() => _ChooseLocationState();
}
class _ChooseLocationState extends State<ChooseLocation> {
List<WorldTime> locations = [
WorldTime(
url: 'http://worldtimeapi.org/timezone/Asia/Kolkata',
location: 'Kolkata',
flag: 'india.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Asia/Hong_Kong',
location: 'Hong_Kong',
flag: 'china.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Asia/Tokyo',
location: 'Tokyo',
flag: 'japan.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Asia/Singapore',
location: 'Singapore',
flag: 'singapore.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Europe/London',
location: 'London',
flag: 'uk.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Europe/Berlin',
location: 'Berlin',
flag: 'germany.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/Africa/Cairo',
location: 'Cairo',
flag: 'egypt.png'),
WorldTime(
url: 'http://worldtimeapi.org/timezone/America/New_York',
location: 'New_York',
flag: 'usa.png')
];
void updateTime(index) async {
WorldTime instance = locations[index];
await instance.getTime();
//Navigate to home screen and pass the data we get to the home screen
//as home screen is already sitting underneath in the app we will pop loading screen
//to get back to home screen
Navigator.pop(context, {
'location': instance.location,
'time': instance.time,
'flag': instance.flag,
'isDaytime': instance.isDaytime,
});
}
//initializes the widget again by overriding the initial widget inherited from StatefulWidget
//helps to update the widget on change of the data while using API to fetch the data
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
elevation: 0,
title: Text('Change Location'),
centerTitle: true,
),
body: ListView.builder(
itemCount: locations.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
child: Card(
child: ListTile(
onTap: () {
updateTime(index);
},
title: Text(
locations[index].location,
),
leading: CircleAvatar(
backgroundImage: AssetImage(
'assets/${locations[index].flag}',
),
),
),
),
);
},
),
);
}
}
loading.dart
import 'package:flutter/material.dart';
import 'package:worldtime/services/world_time.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
class Loading extends StatefulWidget {
@override
_LoadingState createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
//Creating instance of WorldTime class
void setupWorldTime() async {
WorldTime instance = WorldTime(
location: 'Berlin', flag: 'germany.png', url: 'Europe/Berlin');
await instance.getTime();
Navigator.pushReplacementNamed(context, '/home', arguments: {
'location': instance.location,
'time': instance.time,
'flag': instance.flag,
'isDaytime': instance.isDaytime,
});
}
@override
void initState() {
super.initState();
setupWorldTime();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[900],
body: Center(
child: SpinKitFadingCube(
color: Colors.white,
size: 50.0,
)),
);
}
}
world_time.dart
import 'package:http/http.dart';
import 'dart:convert';
import 'package:intl/intl.dart';
class WorldTime {
//initializing the properties of the class
String location; //location name for the UI
String time; //time in that location
String flag; //URL to asset flag image
String url; //location in the url for the API call
bool isDaytime; //true or false if day or night
//Constructor of the class
WorldTime({this.location, this.flag, this.url, this.time});
//Function is gone return future
//it is temporary place holder value until this async function completes
Future <void> getTime() async {
//First, we come to await. The await part basically says -
// go ahead and run this function asynchronously and,
// when it is done, continue on to the next line of code
//and this all is done in asynchronous function not in sync one
//Handling the Error Occurring While Loading Data
try {
//make request to api and waiting until data is returned from api
Response response = await get(
'http://worldtimeapi.org/api/timezone/$url');
//Convert json string data to string
Map data = jsonDecode(response.body);
//Get properties from data map (like dictionary in python)
String datetime = data['datetime'];
String offset = data['utc_offset'];
//Create a DateTime Object
DateTime now = DateTime.parse(
datetime); //creates an instance now of the DateTime object from
// DateTime class by parsing a string
//Our offset time is in format +xy: zw
//To add offset time to now time we need to convert offset time in xy: zw format
//and now save the hour part and minute part of the offset in different int variables
//for that we need to take the hour and minute part of that string as substring
//and after that we have to convert that substring part to int by parsing the string
int hour = int.parse(offset.substring(1, 3));
int minute = int.parse(offset.substring(5, 6));
//now adding the now time from datetime with the add method and giving the duration
//by giving hours and minutes
now = now.add(Duration(hours: hour, minutes: minute));
//Using ternary operator to check whether its day time or not
//Ternary operator format is:
// variable_store_result = condition ? if satisfied then value : else the value;
isDaytime = now.hour > 6 && now.hour < 20 ? true : false;
//convert now object to more readable format
time = DateFormat.jm().format(now);
}
catch (error) {
print(error);
time = 'Could Not Load The Time Data';
}
}
}
引发的错误是:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building Home(dirty, dependencies: [_ModalScopeStatus], state: _HomeState#73021):
Failed assertion: boolean expression must not be null
The relevant error-causing widget was:
Home file:///C:/Users/abhij/AndroidStudioProjects/world_time/lib/main.dart:20:29
When the exception was thrown, this was the stack:
#0 _HomeState.build (package:worldtime/pages/home.dart:22:26)
#1 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
#2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
#3 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:11)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
问题在传递布尔参数时在home.dart和world_time.dart中,我的猜测是在home.dart的第19行中,我使用了三元运算符...我试图解决它但是无法做到..请帮帮我!!
它说在构建Home(脏,依赖项:[_ ModalScopeStatus],状态:_HomeState#73021)时引发了以下断言: 断言失败:布尔表达式不能为空
The relevant error-causing widget was:
Home file:///C:/Users/abhij/AndroidStudioProjects/world_time/lib/main.dart:20:29
When the exception was thrown, this was the stack:
#0 _HomeState.build (package:worldtime/pages/home.dart:22:26)
#1 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
#2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
#3 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:11)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
我的系统配置是: Android Studio版本3 Windows 10
答案 0 :(得分:0)
错误提示。boolean expression must not be null
表示您正在尝试检查null
变量的值。为了解决这个问题,您应该使用完整语句检查它是否为真。
String bgImage = data['isDaytime']==true ? 'day.jpg' : 'night.jpg';
Color bgColor = data['isDaytime']==true ? Colors.grey[900] : Colors.black;
在这种情况下,如果变量为null,则表达式为false