1. 程式人生 > >Flutter實戰2 --- 寫一個天氣查詢的APP

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

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

前面一篇文章Flutter實戰1 --- 寫一個天氣查詢的APP ,實現了一個顯示城市、溫度、天氣、溼度的介面,但是這個介面只有一個顯示的功能,沒有任何可互動的地方,本篇文章繼續完善查詢天氣的APP的功能。

增加兩個功能:

  1. 新增一個城市選擇的頁面
  2. 在城市選擇頁面,點選城市,跳轉到對應城市天氣的頁面

1. 建立城市選擇頁面

在Android中新建一個頁面,需要用Activity,在iOS中需要用ViewController,但在Flutter中,新建一個頁面只需要用Widge就行,所以我們新建一個CityWidget.dart

CityWidget是一個ListView,從伺服器拉取城市的列表並顯示,我們用CityData.dart來儲存城市的資料。程式碼如下:

  • CityData.dart
class CityData{
  String cityName;

  CityData(this.cityName);
}
複製程式碼
  • CityWidget.dart

CityWidget是一個StatefulWidget,因為CityWidget裡的資料是從伺服器上拉的,是變的,所以需要用StatefulWidget來實現,從伺服器拉取資料的程式碼和Flutter實戰1 --- 寫一個天氣查詢的APP

裡的WeatherWidget一樣,不同的是:

  1. CityWidget是一個List,用ListView.builder實現,需要填兩個引數itemCount(List資料的個數)和itemBuilder(List中item的view),在itemBuilder中有index的引數,可以直接從data中去到資料
  2. 為了讓List的item響應點選事件,在List的item外面包了一層GestureDetectorGestureDetector也是一個Widget,因為在Flutter裡處理點選事件的也是一個Widget,所以你想讓你的Widget處理事件,必須得包一層處理事件的Widget,在Widget裡的onTap
    處理點選事件
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:gdg_weather/page/city/CityData.dart';
import 'package:gdg_weather/page/weather/WeatherWidget.dart';
import 'package:http/http.dart' as http;

class CityWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return CityState();
  }

}

class CityState extends State<CityWidget>{

  List<CityData> cityList = new List<CityData>();

  CityState(){
    _getCityList();
  }

  void _getCityList() async{
    List<CityData> citys = await _fetchCityList();
    setState(() {
      cityList = citys;
    });
  }

  //拉取城市列表
  Future<List<CityData>> _fetchCityList() async{
    final response = await http.get('https://search.heweather.net/top?group=cn&key=ebb698e9bb6844199e6fd23cbb9a77c5');

    List<CityData> cityList = new List<CityData>();

    if(response.statusCode == 200){
      //解析資料
      Map<String,dynamic> result = json.decode(response.body);
      for(dynamic data in result['HeWeather6'][0]['basic']){
        CityData cityData = CityData(data['location']);
        cityList.add(cityData);
      }
      return cityList;
    }else{
      return cityList;
    }
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ListView.builder(
        itemCount: cityList.length,
        itemBuilder: (context,index){
          return ListTile(
            title: GestureDetector(
              child:  Text(cityList[index].cityName),
              onTap:(){
                Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => WeatherWidget(cityList[index].cityName))
                );
              },
            ),
          );
        });
  }

}
複製程式碼

2.路由

要開啟一個頁面,Android中是先初始化Intent,然後呼叫startActivity();在iOS中是先初始化ViewController,然後呼叫pushViewController;在web裡,是呼叫一個跳轉連結。

那麼在Dart中如何從一個頁面跳轉到另一個頁面呢?

答案就是 路由

路由有多種實現,這裡給出一個:

  • 開啟一個頁面
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => WeatherWidget(cityList[index].cityName))
);
複製程式碼
  • 返回
Navigator.pop(context);
複製程式碼

3.WeatheWidget

天氣頁面需要知道上個頁面點選的是哪個城市,所以將城市當做WeaterWidget的構造引數傳過來。

4.頁面調整

因為我們想第一個開啟的頁面是城市列表,點選城市列表後,跳轉到天氣頁面,所以調整一下main.dart裡面的程式碼,將WeatherWidget改為CityWidget

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: Scaffold(
        body: CityWidget(),
      ),
    );
  }
}
複製程式碼

5.程式碼目錄跳轉

其實到前面一步,功能已經實現,但是因為現在已經有很多類了,現在目錄結構太混亂了,調整一下,如下:

6.執行介面