Flutter實戰1 --- 寫一個天氣查詢的APP

小德_REN發表於2018-12-18

寫一個查詢天氣的demo。

程式碼github地址:github.com/koudle/GDG_…

1.建立工程

在Android Studio中,File -> New ->New Flutter Project -> Flutter Application

建立完工程後,有三個目錄

android:Android工程的目錄

ios:iOS工程的目錄

lib: Flutter工程的目錄

其中android、ios下的檔案我們都不動,我們只改動lib目錄下的dart檔案。

2.執行Flutter工程

  1. 連線手機
  • 這裡不建議用模擬器,因為模擬器在用GPU渲染時可能會出問題,導致圖片渲染不出來。
  1. 然後按Run 在手機上把程式跑起來。

3.天氣API介面申請

註冊地址console.heweather.com/register

註冊完後,再看API文件 www.heweather.com/documents

demo這裡用的是,獲取當天天氣情況的API:www.heweather.com/documents/a…

用的請求URL如下:

https://free-api.heweather.com/s6/weather/now?location=廣州&key=******
複製程式碼

4.介面編寫

在建立的工程裡,有個main.dart裡面有一段顯示介面的程式碼如下:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
        // counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
複製程式碼

其中home 就是要顯示的介面,這裡我們要把MyHomePage換成我們自己的。

4.1 建立WeatherWidget

通過 new -> Dart File 在lib目錄下建立WeatherWidget

class WeatherWidget extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new WeatherState();
  }
}

class WeatherState extends State<WeatherWidget>{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
    );
  }            
}
複製程式碼

建立完後,在main.dart中將home改為WeatherWidget,如下:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: WeatherWidget(),
    );
  }
複製程式碼

4.2 HotReload

在寫UI的工程中,我們可以用到Flutter的hot reload的特性,寫佈局的時候,按ctrl+scmd+s就可以在手機上實時看到介面的變化。

這個功能很好用。

4.3新增圖片資源

Flutter可以新增不同的資源,例如圖片、文字、配置檔案、靜態資料等。

新增資源時,需要在pubspec.yaml檔案中的flutter屬性下新增assets,並標明要新增資源的路徑,例如,我們要加入指定的圖片時,可以這麼寫:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png
複製程式碼

如果要新增的資源太多,也可以新增資料夾,例如:

flutter:
  assets:
    - assets/
複製程式碼

在本demo中,要新增一個背景圖,我們在工程的根目錄下建立images目錄,將背景圖放在images目錄下,然後在pubspec.yaml中新增:

flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true
  assets:
    - images/
複製程式碼

4.4 寫WeatherWidget的UI佈局

Scaffold中新增body的屬性,來寫UI的佈局,如下:

class WeatherState extends State<WeatherWidget>{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: new Stack(
        fit: StackFit.expand,
        children: <Widget>[
          new Image.asset("images/weather_bg.jpg",fit: BoxFit.fitHeight,),
          new Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              new Container(
                width: double.infinity,
                margin: EdgeInsets.only(top: 40.0),
                child: new Text(
                  "廣州市",
                  textAlign: TextAlign.center,
                  style: new TextStyle(
                    color: Colors.white,
                    fontSize: 30.0,
                  ),
                ),
              ),
              new Container(
                width: double.infinity,
                margin: EdgeInsets.only(top: 100.0),
                child: new Column(
                  children: <Widget>[
                    new Text(
                        "20 °",
                        style: new TextStyle(
                            color: Colors.white,
                            fontSize: 80.0
                        )),
                    new Text(
                        "晴",
                        style: new TextStyle(
                            color: Colors.white,
                            fontSize: 45.0
                        )),
                    new Text(
                      "溼度  80%",
                      style: new TextStyle(
                          color: Colors.white,
                          fontSize: 30.0
                      ),
                    )
                  ],
                ),
              )
            ],
          )
        ],
      ),
    );
  }

}
複製程式碼

ctrl+s,在手機上就可以看到寫好的UI,但這時候的資料是寫死的,下來看如何通過http獲取資料。

5.通過http獲取資料

要通過http資料,我們首先要新增http的依賴庫,在pubspec.yaml中的dependencies新增如下:

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  http: ^0.12.0
複製程式碼

然後在當前工程目錄下執行以下命令列:

$ flutter packages get
複製程式碼

或者在Android Stuido 開啟pubspec.yaml 檔案,點選上面的packages get

這裡操作的意義是,拉取http的庫。

5.1 建立WeatherData類

通過 new -> Dart File 在lib目錄下建立WeatherData

class WeatherData{
  String cond; //天氣
  String tmp; //溫度
  String hum; //溼度

  WeatherData({this.cond, this.tmp, this.hum});

  factory WeatherData.fromJson(Map<String, dynamic> json) {
    return WeatherData(
      cond: json['HeWeather6'][0]['now']['cond_txt'],
      tmp: json['HeWeather6'][0]['now']['tmp']+"°",
      hum: "溼度  "+json['HeWeather6'][0]['now']['hum']+"%",
    );
  }

  factory WeatherData.empty() {
    return WeatherData(
      cond: "",
      tmp: "",
      hum: "",
    );
  }
}
複製程式碼

5.2 資料獲取

class WeatherState extends State<WeatherWidget>{

  WeatherData weather = WeatherData.empty();

  WeatherState(){
    _getWeather();
  }

  void _getWeather() async{
    WeatherData data = await _fetchWeather();
    setState((){
      weather = data;
    });
  }

  Future<WeatherData> _fetchWeather() async{
    final response = await http.get('https://free-api.heweather.com/s6/weather/now?location=廣州&key=ebb698e9bb6844199e6fd23cbb9a77c5');
    if(response.statusCode == 200){
      return WeatherData.fromJson(json.decode(response.body));
    }else{
      return WeatherData.empty();
    }
  }



  @override
  Widget build(BuildContext context) {
    ...
  }
}  
複製程式碼

5.3 將之前寫死的資料換成WeatherData

				...                
                child: new Column(
                  children: <Widget>[
                    new Text(
                        weather?.tmp,
                        style: new TextStyle(
                            color: Colors.white,
                            fontSize: 80.0
                        )),
                    new Text(
                        weather?.cond,
                        style: new TextStyle(
                            color: Colors.white,
                            fontSize: 45.0
                        )),
                    new Text(
                      weather?.hum,
                      style: new TextStyle(
                          color: Colors.white,
                          fontSize: 30.0
                      ),
                    )
                  ],
                ),
                ...
複製程式碼

6.執行介面

iOS執行介面

Android執行介面

相關文章