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;
}
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');
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();
RequestEntity entity = new Gson().fromJson(data,
new TypeToken<RequestEntity>() {}.getType());
Log.d(TAG,"onListen()--suc->"+entity.toString());
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"};
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进行实现。
|