Flutter GetX 框架实战:简易天气应用开发指南

1. 项目初始化
# pubspec.yaml 依赖
dependencies:
  flutter:
    sdk: flutter
  get: ^4.6.5      # GetX 核心库
  http: ^1.1.0     # 网络请求
  get_storage: ^2.1.1 # 本地存储
  intl: ^0.18.1    # 日期格式化

2. 数据模型
// models/weather_model.dart
class WeatherModel {
  final String city;
  final double temperature;
  final String condition;
  final int humidity;

  WeatherModel({
    required this.city,
    required this.temperature,
    required this.condition,
    required this.humidity,
  });

  factory WeatherModel.fromJson(Map<String, dynamic> json) {
    return WeatherModel(
      city: json['name'],
      temperature: json['main']['temp'].toDouble(),
      condition: json['weather'][0]['main'],
      humidity: json['main']['humidity'],
    );
  }
}

3. 网络请求服务
// services/weather_service.dart
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import '../models/weather_model.dart';

class WeatherService extends GetConnect {
  static const baseUrl = "https://api.openweathermap.org/data/2.5/weather";
  static const apiKey = "YOUR_API_KEY"; // 替换为实际API密钥

  Future<WeatherModel> fetchWeather(String city) async {
    final response = await http.get(
      Uri.parse("$baseUrl?q=$city&appid=$apiKey&units=metric")
    );

    if (response.statusCode == 200) {
      return WeatherModel.fromJson(json.decode(response.body));
    } else {
      throw Exception("天气数据获取失败");
    }
  }
}

4. 控制器实现
// controllers/weather_controller.dart
import 'package:get/get.dart';
import '../services/weather_service.dart';
import '../models/weather_model.dart';

class WeatherController extends GetxController {
  final WeatherService _weatherService = WeatherService();
  var weatherData = WeatherModel(
    city: '',
    temperature: 0,
    condition: '',
    humidity: 0,
  ).obs;
  var isLoading = true.obs;
  var errorMessage = ''.obs;

  @override
  void onInit() {
    fetchWeather("Beijing"); // 默认加载北京天气
    super.onInit();
  }

  Future<void> fetchWeather(String city) async {
    try {
      isLoading(true);
      final data = await _weatherService.fetchWeather(city);
      weatherData(data);
      errorMessage('');
    } catch (e) {
      errorMessage("加载失败: ${e.toString()}");
    } finally {
      isLoading(false);
    }
  }
}

5. UI 视图层
// views/weather_view.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/weather_controller.dart';

class WeatherView extends StatelessWidget {
  final WeatherController _controller = Get.put(WeatherController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX 天气应用')),
      body: Obx(() {
        if (_controller.isLoading.value) {
          return Center(child: CircularProgressIndicator());
        }
        if (_controller.errorMessage.isNotEmpty) {
          return Center(child: Text(_controller.errorMessage.value));
        }
        return WeatherCard(weather: _controller.weatherData.value);
      }),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _showCityDialog(context),
        child: Icon(Icons.search),
      ),
    );
  }

  void _showCityDialog(BuildContext context) {
    final TextEditingController cityController = TextEditingController();
    Get.dialog(
      AlertDialog(
        title: Text("输入城市"),
        content: TextField(controller: cityController),
        actions: [
          TextButton(
            onPressed: () => Get.back(),
            child: Text("取消"),
          ),
          TextButton(
            onPressed: () {
              _controller.fetchWeather(cityController.text);
              Get.back();
            },
            child: Text("确认"),
          ),
        ],
      ),
    );
  }
}

class WeatherCard extends StatelessWidget {
  final WeatherModel weather;

  const WeatherCard({Key? key, required this.weather}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        elevation: 8,
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(weather.city, style: TextStyle(fontSize: 24)),
              SizedBox(height: 20),
              Text('${weather.temperature.toStringAsFixed(1)}°C', 
                   style: TextStyle(fontSize: 48)),
              SizedBox(height: 10),
              Text(weather.condition, style: TextStyle(fontSize: 18)),
              SizedBox(height: 10),
              Text('湿度: ${weather.humidity}%', style: TextStyle(fontSize: 16)),
            ],
          ),
        ),
      ),
    );
  }
}

6. 主入口文件
// main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'views/weather_view.dart';

void main() {
  runApp(GetMaterialApp(
    title: 'GetX 天气应用',
    home: WeatherView(),
    theme: ThemeData(primarySwatch: Colors.blue),
  ));
}

关键功能说明

  1. 状态管理:使用 Obx 自动响应数据变化
  2. 依赖注入:通过 Get.put() 自动管理控制器生命周期
  3. 网络请求:封装 HTTP 服务,支持错误处理
  4. 交互设计
    • 浮动按钮触发城市搜索
    • GetX 原生对话框组件
    • 加载状态提示

运行效果

  • 启动时自动加载北京天气数据
  • 点击右下角搜索按钮可切换城市
  • 数据加载时显示进度条
  • 错误时显示友好提示

提示:使用前需在OpenWeatherMap申请免费API密钥替换YOUR_API_KEY,每日限额1000次请求。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐