You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中监听系统时区变化?iOS可监听NSSystemTimeZoneDidChangeNotification

Flutter监听系统时区变化的实现方法

Flutter框架本身没有提供直接监听系统时区变化的API,需要通过Platform Channel与原生平台交互,分别在iOS和Android端实现系统通知/广播的监听,再将事件回调到Flutter层。以下是具体实现步骤:

iOS端实现

在iOS中,我们可以监听系统的NSSystemTimeZoneDidChangeNotification通知,收到通知后通过MethodChannel将时区信息传递给Flutter。

代码示例(Swift)

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    private let channelName = "com.yourdomain.timezone/listener"
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        guard let controller = window?.rootViewController as? FlutterViewController else {
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
        // 注册时区变化通知监听
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(onTimeZoneChanged),
            name: NSSystemTimeZoneDidChangeNotification,
            object: nil
        )
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    @objc private func onTimeZoneChanged() {
        guard let controller = window?.rootViewController as? FlutterViewController else { return }
        let channel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
        // 获取当前时区ID并发送到Flutter
        let currentTimeZone = TimeZone.current.identifier
        channel.invokeMethod("onTimeZoneChanged", arguments: currentTimeZone)
    }
    
    deinit {
        // 移除通知观察者
        NotificationCenter.default.removeObserver(self)
    }
}

Android端实现

Android系统会在时区变化时发送ACTION_TIMEZONE_CHANGED广播,我们需要注册广播接收器监听该事件,再通过MethodChannel回调到Flutter。

代码示例(Kotlin)

1. 创建广播接收器

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import io.flutter.plugin.common.MethodChannel
import io.flutter.embedding.engine.FlutterEngineCache

class TimeZoneChangeReceiver : BroadcastReceiver() {
    private val channelName = "com.yourdomain.timezone/listener"
    
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_TIMEZONE_CHANGED) {
            val currentTimeZone = java.util.TimeZone.getDefault().id
            // 获取Flutter引擎并发送事件
            val flutterEngine = FlutterEngineCache.getInstance().get("default_engine")
            flutterEngine?.let {
                val channel = MethodChannel(it.dartExecutor.binaryMessenger, channelName)
                channel.invokeMethod("onTimeZoneChanged", currentTimeZone)
            }
        }
    }
}

2. 在Activity中动态注册接收器

import android.content.IntentFilter
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    private lateinit var timeZoneReceiver: TimeZoneChangeReceiver
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        timeZoneReceiver = TimeZoneChangeReceiver()
        // 动态注册广播接收器
        registerReceiver(
            timeZoneReceiver,
            IntentFilter(Intent.ACTION_TIMEZONE_CHANGED)
        )
    }
    
    override fun onDestroy() {
        super.onDestroy()
        // 销毁时注销接收器,避免内存泄漏
        unregisterReceiver(timeZoneReceiver)
    }
}

Flutter端实现

在Flutter层创建MethodChannel,监听原生发送的onTimeZoneChanged方法,处理时区变化事件。

代码示例(Dart)

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

class TimeZoneMonitor {
  static const MethodChannel _channel = MethodChannel('com.yourdomain.timezone/listener');
  static void Function(String)? onTimeZoneUpdated;

  static void initialize() {
    _channel.setMethodCallHandler((call) async {
      if (call.method == 'onTimeZoneChanged') {
        final timeZoneId = call.arguments as String;
        onTimeZoneUpdated?.call(timeZoneId);
      }
    });
  }
}

// 在Widget中使用
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String currentTimeZone = '';

  @override
  void initState() {
    super.initState();
    TimeZoneMonitor.initialize();
    TimeZoneMonitor.onTimeZoneUpdated = (timeZoneId) {
      setState(() {
        currentTimeZone = timeZoneId;
      });
      print('系统时区已变更为:$timeZoneId');
      // 这里添加你的业务逻辑
    };
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('时区监听示例')),
      body: Center(child: Text('当前时区:$currentTimeZone')),
    );
  }
}

注意事项

  • 确保iOS、Android和Flutter端的MethodChannel名称完全一致(示例中为com.yourdomain.timezone/listener,可根据自己的项目自定义)。
  • Android推荐使用动态注册广播接收器,避免静态注册带来的不必要的资源占用。
  • iOS在deinit方法中移除通知观察者,避免潜在的内存泄漏。

内容的提问来源于stack exchange,提问作者无夜之星辰

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:05:38