在创建世界时钟应用程序时,我遇到了此处所述的问题

时间:2020-06-03 14:56:31

标签: flutter flutter-layout flutter-dependencies

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

1 个答案:

答案 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