IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Flutter调用原生网络请求的封装 -> 正文阅读

[移动开发]Flutter调用原生网络请求的封装

Flutter调用原生侧时,目前主要是通过官方提供的Channel的方式实现,在Flutter中Channel主要分为三种

  • MethondChannel,用于方法的调用
  • EventChannel,用于事件流的发送
  • MessageChannel,传递字符串和半结构化信息
    在封装网络请求时,主要使用了EventChannel,方便回调的使用

第一步,使用构建者模式封装参数

Flutter侧参数的初始化封装

class NetBuilder<T>{
  String _domain = "";
  String _path = "";
  String _type = "";
  Map<String,dynamic>? _param;

  NetBuilder setDomain(String domain){
    _domain = domain;
    return this;
  }

  NetBuilder setPath(String path){
    _path = path;
    return this;
  }

  NetBuilder setType(String type){
    _type = type;
    return this;
  }

  NetBuilder setParam(Map<String,dynamic> param){
    _param = param;
    return this;
  }

  NetCall build() => NetCall(this);
}

第二步,实现具体的网络请求实现

class NetCall<T>{
  static const String GET = "get";
  static const String POST = "post";
  //服务器地址
  String _domain = "";
  //请求地址
  String _path = "";
  //请求类型
  String _type = "";
  //请求参数
  Map<String,dynamic>? _param;

  NetCall(NetBuilder builder){
    _domain = builder._domain;
    _path = builder._path;
    _type = builder._type;
    _param = builder._param;
  }

    //创建EventChannel
  static const EventChannel _eventChannel = EventChannel("com.base.net");

  //开始注册调用原生侧的函数
  void execute({void Function(T result)? onSuccess, void Function(ResponseEntity error)? onError}){
    String requestData = json.encode({"domain":_domain,"path":_path,"type":_type,"param":_param});
    _eventChannel.receiveBroadcastStream(requestData)
        .listen((event) {
      if(event != null){
        print('Received success event---> $event');
        Map<String, dynamic> map = jsonDecode(event);
        //解析原生侧返回的网络请求并转换为实体
        ResponseEntity<String> entity = ResponseEntity.fromJson(map);
        print('Received success: $entity');
        //根据ResultType判断是否请求成功
        if(entity.ResultType == 0){
          onSuccess!(entity.AppendData as T);
        }else {
          onError!(entity);
        }
      }
    });
  }
}

对应的ResponseEntity如下

class ResponseEntity<T>{
   int ResultType;
   int Code;
   String Message;
   T AppendData;

   ResponseEntity(this.ResultType,this.Code,this.Message,this.AppendData);

   factory ResponseEntity.fromJson(Map<String, dynamic> json) {
     return ResponseEntity(json['ResultType'], json['Code'], json['Message'], json['AppendData']);
   }

   @override
  String toString() {
    return "[Code:$Code,ResultType:$ResultType,Message:$Message,AppendData:$AppendData]";
  }
}

第三步,Android原生侧的实现

主要是创建对应的Channel,根据Flutter侧传递的参数进行网络请求,并返回相应的结果。
注:CHANNEL_NAME和Flutter中创建的Channel传入的要保持一致,相当于管道名称。

import android.util.Log;

import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {

    private String TAG = "MainActivity";
    private EventChannel channel = null;

    private MethodChannel methodChannel = null;

    private static final String CHANNEL_NAME = "com.base.net";
    private static final String METHOD_NAME= "request";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        channel = new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),CHANNEL_NAME);
        channel.setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                Log.d(TAG,"onListen()--->"+arguments);
                String data = arguments.toString();
                //解析Flutter传递过来的参数进行解析
                RequestEntity entity = new Gson().fromJson(data,
                        new TypeToken<RequestEntity>() {}.getType());
                Log.d(TAG,"onListen()--suc->"+entity.toString());
                //此处省略原生侧网络请求的具体实现
                //拿到网络请求返回的结果进行callback到Flutter。
                ResponseEntity<String> responseEntity = new ResponseEntity<>();
                if (entity.getType().equals("post")){
                    responseEntity.setCode(200);
                    responseEntity.setMessage("请求成功");
                    responseEntity.setAppendData("success");
                    responseEntity.setResultType(1);
                    String result = new Gson().toJson(responseEntity);
                    events.success(result);
                }else {
                    responseEntity.setCode(404);
                    responseEntity.setMessage("请求失败");
                    responseEntity.setAppendData("fails");
                    responseEntity.setResultType(0);
                    String result = new Gson().toJson(responseEntity);
                    events.success(result);
                }
            }

            @Override
            public void onCancel(Object arguments) {

            }
        });
    }
}

对应的RequestEntity和ResponseEntity


import java.io.Serializable;

public class ResponseEntity<T> implements Serializable {
    private int Code;
    private String Message;
    private int ResultType;
    private T AppendData;

    public int getCode() {
        return Code;
    }

    public void setCode(int code) {
        Code = code;
    }

    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }

    public int getResultType() {
        return ResultType;
    }

    public void setResultType(int resultType) {
        ResultType = resultType;
    }

    public T getAppendData() {
        return AppendData;
    }

    public void setAppendData(T appendData) {
        AppendData = appendData;
    }

    @Override
    public String toString() {
        return "ResponseEntity{" +
                "Code=" + Code +
                ", Message='" + Message + '\'' +
                ", ResultType=" + ResultType +
                ", AppendData=" + AppendData +
                '}';
    }
}


import java.util.Map;

public class RequestEntity {
    private String domain;
    private String path;
    private String type;
    private Map<String,Object> param;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Map<String, Object> getParam() {
        return param;
    }

    public void setParam(Map<String, Object> param) {
        this.param = param;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    @java.lang.Override
    public java.lang.String toString() {
        return "RequestEntity{" +
                "domain='" + domain + '\'' +
                ", path='" + path + '\'' +
                ", type='" + type + '\'' +
                ", param=" + param +
                '}';
    }
}

最后在Flutter侧调用时,有两种方式

第一种,通过构建者模式创建对应的NetCall,然后执行execute函数

String url = "/app/url";
Map<String,dynamic>  param = {"name":"zhangsan"};

// // Net().setType("get").setPath(url).setParam(param).build()
NetCall call = NetBuilder<String>().setPath(url).setType("get").setParam(param).build();
call.execute( onSuccess: (result){
  setState(() {
    _counter = result;
  });
});

第二种,使用了Dart的扩展函数属性进行一步封装

String url = "/app/url";
Map<String,dynamic>  param = {"name":"zhangsan"};
url.requestGet<String>(param).execute(onSuccess: (result){
  setState(() {
    _counter = result;
  });
},onError: (error){
  print("NetManager---error->"+error.Message);
});

详细实现如下:

extension StringExt on String{

  NetCall requestGet<T>(Map<String,dynamic> param){
    return _createCall(NetCall.GET, param);
  }
  NetCall requestPost<T>(Map<String,dynamic> param){
    return _createCall(NetCall.POST, param);
  }

  NetCall _createCall(String type,Map<String,dynamic> param){
    return NetBuilder()
        .setPath(this)
        .setType(type)
        .setParam(param)
        .build();
  }
}

第二种方式,主要针对于全局主域名访问,相较于第一种,进行了进一步的封装,但如果要使用其他的域名进行网络请求时,需要使用第一种方式。
总结:该封装过程,主要针对于Flutter混合开发,原生侧网络请求比较复杂且稳定的情况下,为了节约时间,使用Channel的方式,直接调用原生侧的网络请求的实现,此处使用了EventChannel,当前也可以使用MethondChannel进行实现。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:33:51  更:2022-05-12 16:34:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:32:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码