Flutter Webview添加Cookie的正确姿势

2020-09-22  本文已影响0人  小呆呆666

场景

h5页面要从cookie里面取数据,所以需要在flutter webview的cookie里面塞一些数据,设置的数据多达十几条;按照网上查的使用方式来设置,通过fiddler抓包发现,只能生效一条,来来回回试了很多次都只有一条,心态崩了

后来看到cookie设置数据也是类似键值对里面套键值对,灵机一动,变换下后就成功了,记录下正确的写法吧

正确姿势

引入

webview_flutter: ^0.3.22+1

错误示例

WebViewController _controller;
onWebViewCreated: (WebViewController wvc) {
    _controller = wvc;
}

onPageFinished: (String value) {
    _controller.evaluateJavascript( 'document.cookie = "SESSIONID=612bc4822b6996d6f335a963c20eb541fba72985; path=/"')
}
setSessionID() async {
  String sessionID = await LocalStorage.get("sessionID");
  if (Platform.isIOS) {
    _controller.evaluateJavascript("document.cookie = 'sessionID=${sessionID}'").then<String>((res) {
      print("webViewController.evaluateJavascript========>${res}");
      _onListCookies(_controller, context);
    });
  } else {
    _controller.evaluateJavascript('document.cookie = "sessionID=${sessionID};"').then<String>((res) {
      print("webViewController.evaluateJavascript========>${res}");
      _onListCookies(_controller, context);
    });
  }
}

多条cookie添加正确写法

///webview控制器
WebViewController _controller;
String _url = "写入你的链接";

WebView(
    initialUrl: _url,
    javascriptMode: JavascriptMode.unrestricted,
    onWebViewCreated: (controller) {
        _controller = controller;
    },
    onPageFinished: (url) {
        //页面加载结束
        String cookie =
            "document.cookie = 'name=IAmDaShuaiBi';document.cookie = 'id=233'";
        _controller.evaluateJavascript(cookie);
    },
    userAgent: "test;app/1.0.0",
)

优化写法

///webview控制器
WebViewController _controller;
String _url = "写入你的链接";

WebView(
    initialUrl: _url,
    javascriptMode: JavascriptMode.unrestricted,
    onWebViewCreated: (controller) {
        _controller = controller;
    },
    onPageFinished: (url) {
        //页面加载结束
        String cookie = '''
          document.cookie = 'nameOne=IAmDaShuaiBi';
          document.cookie = 'idOne=233';
          document.cookie = 'nameTwo=IAmDaShuaiBi';
          document.cookie = 'idTwo=233';
          document.cookie = 'nameThree=IAmDaShuaiBi';
          document.cookie = 'idThree=233';
        ''';
        _controller.evaluateJavascript(cookie);
    },
    userAgent: "test;app/1.0.0",
)

补充(弹窗封装,优化列表数据源)


效果

showBottomSingleDialog(
    context,
    list: list,
    showKey: 'name',
    callback: (item) {
        print(item.name);
        print(item.id);
    },
);

[图片上传失败...(image-6aba5e-1604839339900)]

[图片上传失败...(image-78239d-1604839339900)]

说明

底部单列表弹窗是非常实用的弹窗,但是可能大家经常有这样的一种使用体验,传数据源,一般都是传一个List类型,内部的泛型最最最常见的就是:String和固定的实体;说下这俩种情况的问题所在

吐槽:虽然上面俩种情况,第二种明显优于第一种,但是实际开发中,往往不假思索的用第一种,因为第一种不用去新建一个class啊!然后用起来就蛋痛了;有没有一种方法可以一劳永逸的方法呢,数据的list泛型随便用,只用指定泛型实体用于展示的key;然后在回调里面又能拿到我们传的实体呢?通过dart强大的动态类型,加一些巧妙转换是完全可以的

实现思路

java里可以通过泛型+反射;然后指定一个展示的key,理论上也是可以实现,我没试过,大家可以试试

实现思路

实现方法还是很简单的,这里说下思路就行了

实现步骤

举例

flutter_picker: ^1.1.5
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_picker/Picker.dart';

typedef ParamSingleCallback<E> = Void Function(E data);

void showBottomSingleDialog<E>(
    BuildContext context, {
        @required List<E> list,
        @required ParamSingleCallback<E> callback,
        String title = '请选择',
        String showKey = '',
    }) {
    List<PickerItem<E>> pickList = [];
    for (E item in list) {
        String showContent;
        if (showKey == '') {
            //兼容泛型为String的情况
            showContent = item as String;
        } else {
            //将实体转成map,通过设置的key指定展示的字段
            var map = json.decode(jsonEncode(item));
            showContent = map[showKey];
        }

        pickList.add(
            PickerItem(
                text: Text(showContent),
                value: item,
            ),
        );
    }

    Picker(
        adapter: PickerDataAdapter<E>(data: pickList),
        hideHeader: false,
        title: Text(title),
        cancelText: "取消",
        confirmText: "确定",
        onConfirm: (Picker picker, List value) async {
            //必须做一个延时操作,先执行回调内部的pop,不然pop页面无法回传值
            await Future.delayed(Duration(milliseconds: 10));
            callback(picker.getSelectedValues()[0]);
        },
    ).showModal(context);
}

使用

class InfoBean {
    String name;
    int id;

    InfoBean({this.id, this.name});

    /// jsonDecode(jsonStr) 方法中会调用实体类的这个方法。如果实体类中没有这个方法,会报错。
    Map toJson() {
        Map map = Map();
        map["name"] = this.name;
        map["id"] = this.id;
        return map;
    }
}

///创建数据源
List<InfoBean> list = [];
for (var i = 0; i < 10; i++) {
    list.add(InfoBean(name: "姓名-$i", id: i));
}
///指定泛型
showBottomSingleDialog<InfoBean>(
    context,
    list: list,
    showKey: 'name',
    callback: (item) {
        print(item.name);
        print(item.id);
    },
);

///不指定泛型
showBottomSingleDialog(
    context,
    list: list,
    showKey: 'name',
    callback: (item) {
        print(item.name);
        print(item.id);
    },
);

最后

代码地址

上一篇下一篇

猜你喜欢

热点阅读