美文网首页
[Flutter插件开发] 网络状态监听组件

[Flutter插件开发] 网络状态监听组件

作者: 蜗牛是不是牛 | 来源:发表于2023-02-08 20:56 被阅读0次

    前言

    本文讲述如何开发一个Flutter插件,用于监听手机网络状态的改变。需要注意的是,此插件目前只支持安卓平台。

    使用

    每当网络状态改变时,NetworkListener的builder方法都会被调用,通过status回调网络状态。

    NetworkListener(
     builder: (_,status){
     var networkStatuds = "";
     if (status == ConnectivityResult.none) {
     networkStatuds = "网络不可用";
     }
     if (status == ConnectivityResult.has) {
     networkStatuds = "网络可用";
     }
     return  Text(networkStatuds);
     },
    ) 
    

    原理

    使用StreamBuilder

    NetworkListener内部封装了一个StreamBuilder,接收native端返回的Stream,便可回调网络状态。代码如下:

    class NetworkListener extends StatelessWidget {
     const NetworkListener({
     required this.builder,
     Key? key}) : super(key: key);
    
     final  Widget Function(BuildContext context, ConnectivityResult connectivityResult) builder;
    
     @override
     Widget build(BuildContext context) {
     return StreamBuilder(
     stream: NetworkStatusNotifier.getNetworkStatus(),
     builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
     if(snapshot.connectionState == ConnectionState.active && snapshot.hasData){
     return builder(context,snapshot.data);
     }
    
     return builder(context,ConnectivityResult.none);
     },
     );
     }
    } 
    

    如何让native端返回Stream

    如何让native端返回的Strea呢?首先,需要在native端FlutterPlugin的 onAttachedToEngine中创建一个EventChannel,通过其setStreamHandler方法设置好回调什么内容给dart端。代码如下,注意network_status_notifier_ec,其需要与dart端对应。

    // ...
    private EventChannel eventChannel;
    
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
     eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),"network_status_notifier_ec");
     ConnectivityBroadcastReceiver connectivityBroadcastReceiver = new ConnectivityBroadcastReceiver(flutterPluginBinding.getApplicationContext());
     eventChannel.setStreamHandler(connectivityBroadcastReceiver);
    }
    
    // ... 
    

    在dart端,同样创建一个EventChannel,用于接收native返回的stream

    /// Connection status check result.
    enum ConnectivityResult {
     /// has network.
     has,
     /// None: Device not connected to any network
     none
    }
    
    class NetworkStatusNotifier {
    
     static const EventChannel _eventChannel = EventChannel("network_status_notifier_ec");
    
     static Stream<ConnectivityResult>? _networkStatus;
    
     static Stream<ConnectivityResult> getNetworkStatus(){
     _networkStatus ??= _eventChannel.receiveBroadcastStream().map((satues) => parseResult(satues));
     return _networkStatus!;
     }
    
     static ConnectivityResult parseResult(int i){
     switch(i){
     case 0:
     return ConnectivityResult.none;
     case 1:
     return ConnectivityResult.has;
     default:
     return ConnectivityResult.none;
     }
     }
    } </pre>
    
    ## 如何监听网络
    
    监听网络在不同的安卓版本有不同的实现,此项目在安卓N以下采用监听广播的方式监听网络状态,而大于安卓N则采用注册回调的方式。代码如下:
    
    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n26" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public class ConnectivityBroadcastReceiver  extends BroadcastReceiver
     implements EventChannel.StreamHandler{
    
     public ConnectivityBroadcastReceiver(Context context) {
     this.context = context;
     connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
    
     private Context context;
     private ConnectivityManager connectivityManager;
     // 回调结果
     private EventChannel.EventSink events;
     public static final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";
     private Handler mainHandler = new Handler(Looper.getMainLooper());
     private ConnectivityManager.NetworkCallback networkCallback;
    
     @Override
     public void onReceive(Context context, Intent intent) {
     if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
     NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
     //
     if (networkInfo != null && networkInfo.isAvailable()) {
     // network is available.
     callbackNetworkStatus(1);
     } else {
     // network is unavailable.
     callbackNetworkStatus(0);
     }
     }
     }
    
     @Override
     public void onListen(Object arguments, EventChannel.EventSink events) {
     this.events = events;
    
     if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
     networkCallback =
     new ConnectivityManager.NetworkCallback() {
     @Override
     public void onAvailable(Network network) {
     sendEvent(1);
     }
    
     @Override
     public void onUnavailable() {
     sendEvent(0);
     }
    
     @Override
     public void onLost(Network network) {
     sendEvent(0);
     }
     };
     connectivityManager.registerDefaultNetworkCallback(networkCallback);
     } else {
     context.registerReceiver(this, new IntentFilter(CONNECTIVITY_CHANGE));
     }
     }
    
     @Override
     public void onCancel(Object arguments) {
     if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
     if (networkCallback != null) {
     connectivityManager.unregisterNetworkCallback(networkCallback);
     }
     } else {
     context.unregisterReceiver(this);
     }
     }
    
     private void callbackNetworkStatus(int status){
     if(events != null){
     events.success(status);
     }
     }
    
     private void sendEvent(final int status) {
     Runnable runnable =
     new Runnable() {
     @Override
     public void run() {
     events.success(status);
     }
     };
     mainHandler.post(runnable);
     }
    } 
    

    完整代码

    github.com/obweix/flut…

    相关文章

      网友评论

          本文标题:[Flutter插件开发] 网络状态监听组件

          本文链接:https://www.haomeiwen.com/subject/rstckdtx.html