在 Flutter 混合开发中,Android 原生层通知 Dart 界面更新状态

在 Flutter 混合开发中,Android 原生层通知 Dart 界面更新状态,主要通过 MethodChannelinvokeMethod 从原生调用 Dart,或者使用 EventChannel 建立持续的数据流。


方案一:MethodChannel 单向通知(简单场景)

Android 原生层调用 Dart

kotlin 复制代码
// MainActivity.kt 或 Service.kt
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    
    private lateinit var channel: MethodChannel

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        
        channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "flutter_launcher")
        
        // Dart 调用原生的处理器
        channel.setMethodCallHandler { call, result ->
            when (call.method) {
                "getSystemInfo" -> result.success(getSystemInfo())
                else -> result.notImplemented()
            }
        }
    }

    /**
     * 主动通知 Dart 更新(例如:电池变化、应用安装/卸载)
     */
    fun notifyDart(event: String, data: Map<String, Any>) {
        // 在主线程调用
        runOnUiThread {
            channel.invokeMethod(event, data)
        }
    }

    /**
     * 示例:电池变化时通知 Dart
     */
    fun onBatteryChanged(level: Int) {
        notifyDart("onBatteryChanged", mapOf("level" to level))
    }

    /**
     * 示例:应用安装/卸载时通知 Dart
     */
    fun onAppChanged(action: String, packageName: String) {
        notifyDart("onAppChanged", mapOf(
            "action" to action,  // "installed" | "uninstalled" | "updated"
            "package" to packageName
        ))
    }
}

Dart 层接收通知

dart 复制代码
// lib/services/desktop_service.dart
import 'dart:async';
import 'package:flutter/services.dart';

class DesktopService {
  static const MethodChannel _channel = MethodChannel('flutter_launcher');
  
  // 状态流控制器
  static final _batteryController = StreamController<int>.broadcast();
  static final _appChangeController = StreamController<Map<String, dynamic>>.broadcast();
  
  // 公开的数据流
  static Stream<int> get batteryStream => _batteryController.stream;
  static Stream<Map<String, dynamic>> get appChangeStream => _appChangeController.stream;

  static void init() {
    // 设置方法调用处理器,接收原生通知
    _channel.setMethodCallHandler(_handleMethodCall);
  }

  static Future<<dynamic> _handleMethodCall(MethodCall call) async {
    switch (call.method) {
      case 'onBatteryChanged':
        final level = call.arguments['level'] as int?;
        if (level != null) {
          _batteryController.add(level);
        }
        return null;
        
      case 'onAppChanged':
        final data = call.arguments as Map<<dynamic, dynamic>;
        _appChangeController.add({
          'action': data['action'],
          'package': data['package'],
        });
        return null;
        
      case 'onTimeTick':
        // 每分钟通知
        return null;
        
      case 'onWifiChanged':
        final enabled = call.arguments['enabled'] as bool?;
        // 通知WiFi状态变化
        return null;
        
      default:
        return null;
    }
  }

  // 主动调用原生方法
  static Future<Map<String, dynamic>> getSystemInfo() async {
    final result = await _channel.invokeMethod('getSystemInfo');
    return _toStringMap(result);
  }

  static Future<void> launchApp(String package) async {
    await _channel.invokeMethod('launchApp', {'package': package});
  }

  static Map<String, dynamic> _toStringMap(dynamic data) {
    if (data == null) return {};
    final map = data as Map<<dynamic, dynamic>;
    return map.map((k, v) => MapEntry(k.toString(), v));
  }

  static void dispose() {
    _batteryController.close();
    _appChangeController.close();
  }
}

UI 层监听状态变化

dart 复制代码
// lib/widgets/status_bar.dart
import 'package:flutter/material.dart';
import '../services/desktop_service.dart';

class StatusBar extends StatefulWidget {
  const StatusBar({super.key});

  @override
  State<<StatusBar> createState() => _StatusBarState();
}

class _StatusBarState extends State<<StatusBar> {
  int _battery = 100;
  bool _wifi = false;
  String _time = '';

  @override
  void initState() {
    super.initState();
    
    // 初始化服务
    DesktopService.init();
    
    // 监听电池变化(来自原生通知)
    DesktopService.batteryStream.listen((level) {
      setState(() => _battery = level);
    });
    
    // 定时刷新时间
    Stream.periodic(const Duration(seconds: 1)).listen((_) {
      setState(() {
        _time = '${DateTime.now().hour.toString().padLeft(2, '0')}:'
                '${DateTime.now().minute.toString().padLeft(2, '0')}';
      });
    });
    
    // 初始加载
    _loadSystemInfo();
  }

  Future<void> _loadSystemInfo() async {
    final info = await DesktopService.getSystemInfo();
    setState(() {
      _battery = info['battery'] ?? 100;
      _wifi = info['wifi'] ?? false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 36,
      color: Colors.black.withOpacity(0.6),
      padding: const EdgeInsets.symmetric(horizontal: 12),
      child: Row(
        children: [
          Text(_time, style: const TextStyle(color: Colors.white)),
          const Spacer(),
          Icon(_wifi ? Icons.wifi : Icons.wifi_off, color: Colors.white, size: 18),
          const SizedBox(width: 8),
          Text('$_battery%', style: const TextStyle(color: Colors.white)),
        ],
      ),
    );
  }
}

方案二:EventChannel 持续数据流(适合高频数据)

Android 原生层

kotlin 复制代码
// service/SystemEventChannel.kt
package com.example.flutter_launcher.service

import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.EventSink

class SystemEventChannel : EventChannel.StreamHandler {
    
    private var eventSink: EventSink? = null

    override fun onListen(arguments: Any?, events: EventSink?) {
        eventSink = events
        startListening()
    }

    override fun onCancel(arguments: Any?) {
        eventSink = null
        stopListening()
    }

    /**
     * 发送事件到 Dart
     */
    fun sendEvent(event: String, data: Any) {
        eventSink?.success(mapOf(
            "event" to event,
            "data" to data
        ))
    }

    private fun startListening() {
        // 注册系统监听器(电池、WiFi、时间等)
    }

    private fun stopListening() {
        // 注销监听器
    }
}

Dart 层

dart 复制代码
// lib/services/event_service.dart
import 'dart:async';
import 'package:flutter/services.dart';

class EventService {
  static const EventChannel _eventChannel = EventChannel('flutter_launcher/events');
  
  static Stream<Map<String, dynamic>>? _eventStream;

  static Stream<Map<String, dynamic>> get eventStream {
    _eventStream ??= _eventChannel
        .receiveBroadcastStream()
        .map((event) {
          final map = event as Map<<dynamic, dynamic>;
          return {
            'event': map['event'],
            'data': map['data'],
          };
        });
    return _eventStream!;
  }
}

方案三:BroadcastReceiver + 通知(系统事件)

Android 原生层监听系统广播

kotlin 复制代码
// receiver/SystemEventReceiver.kt
package com.example.flutter_launcher.receiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager

class SystemEventReceiver(
    private val onEvent: (String, Map<String, Any>) -> Unit
) : BroadcastReceiver() {

    fun register(context: Context) {
        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_BATTERY_CHANGED)
            addAction(Intent.ACTION_TIME_TICK)
            addAction(Intent.ACTION_TIME_CHANGED)
            addAction(Intent.ACTION_PACKAGE_ADDED)
            addAction(Intent.ACTION_PACKAGE_REMOVED)
            addAction(Intent.ACTION_PACKAGE_REPLACED)
            addAction("android.net.wifi.STATE_CHANGE")
        }
        context.registerReceiver(this, filter)
    }

    fun unregister(context: Context) {
        context.unregisterReceiver(this)
    }

    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            Intent.ACTION_BATTERY_CHANGED -> {
                val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
                val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
                val percent = (level * 100 / scale).coerceIn(0, 100)
                
                onEvent("battery", mapOf("level" to percent))
            }
            
            Intent.ACTION_TIME_TICK, Intent.ACTION_TIME_CHANGED -> {
                onEvent("time", mapOf("time" to System.currentTimeMillis()))
            }
            
            Intent.ACTION_PACKAGE_ADDED -> {
                val packageName = intent.data?.schemeSpecificPart ?: ""
                onEvent("app_added", mapOf("package" to packageName))
            }
            
            Intent.ACTION_PACKAGE_REMOVED -> {
                val packageName = intent.data?.schemeSpecificPart ?: ""
                onEvent("app_removed", mapOf("package" to packageName))
            }
            
            "android.net.wifi.STATE_CHANGE" -> {
                val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as android.net.wifi.WifiManager
                onEvent("wifi", mapOf("enabled" to wifiManager.isWifiEnabled))
            }
        }
    }
}

在 Service 或 Activity 中使用

kotlin 复制代码
class MainActivity : FlutterActivity() {
    
    private lateinit var eventReceiver: SystemEventReceiver
    private lateinit var channel: MethodChannel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        channel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "flutter_launcher")
        
        // 初始化广播接收器
        eventReceiver = SystemEventReceiver { event, data ->
            // 通知 Dart
            runOnUiThread {
                channel.invokeMethod("onSystemEvent", mapOf(
                    "event" to event,
                    "data" to data
                ))
            }
        }
        eventReceiver.register(this)
    }

    override fun onDestroy() {
        eventReceiver.unregister(this)
        super.onDestroy()
    }
}

完整状态更新流程图

复制代码
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Android 系统    │     │  Android 原生层  │     │   Flutter Dart  │
│                 │     │                 │     │                 │
│ 电池变化         │────→│ BroadcastReceiver│────→│ MethodChannel   │
│ 时间变化         │     │ 或 Service 监听  │     │ setMethodCallHandler
│ 应用安装/卸载     │     │                 │     │                 │
│ WiFi状态变化      │     │                 │     │  StreamController
│                 │     │                 │     │  通知 UI 更新     │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                              ↑
                              │ 主动查询
                         ┌────┴────┐
                         │ invokeMethod
                         │ getSystemInfo
                         └─────────┘

推荐用法总结

场景 方案 代码示例
单次状态查询 MethodChannel 双向 invokeMethod('getSystemInfo')
状态变化通知 MethodChannel + Stream invokeMethod('onBatteryChanged')StreamController
高频数据流 EventChannel 电池实时变化、传感器数据
系统广播事件 BroadcastReceiver + MethodChannel 应用安装卸载、时间变化
相关推荐
小书房2 小时前
移动开发跨平台方案之RN/Flutter/KMP/CMP
flutter·react native·react·跨平台·rn·kmp·cmp
故渊at2 小时前
系列一:架构思想进阶 | 第1篇 Android 架构演进实录:从 MVC 的“万能类”到 MVVM 的数据驱动
android·架构·mvc
●VON3 小时前
AtomGit Flutter鸿蒙客户端:安全JSON解析
安全·flutter·华为·json·harmonyos·鸿蒙
●VON3 小时前
AtomGit Flutter鸿蒙客户端:项目架构概览
flutter·华为·架构·harmonyos·鸿蒙
流星白龙3 小时前
【MySQL高阶】22.双写缓冲区,重做日志
android·mysql·adb
世人万千丶3 小时前
鸿蒙PC问题解决:窗口配置错误修复指南
android·学习·华为·开源·harmonyos·鸿蒙·鸿蒙系统
故渊at3 小时前
第一板块:Android 系统基石与运行原理 | 第一篇:Android 系统架构分层与 AOSP 规范
android·系统架构·android系统·aosp
故渊at4 小时前
系列三:组件化与模块化进阶 | 第12篇 老项目重构实战(绞杀者模式):从单体巨石到组件化架构的无痛迁移
android·重构·架构·模块化·组件化