场景
h5页面要从cookie外面取数据,所以须要在flutter webview的cookie外面塞一些数据,设置的数据多达十几条;依照网上查的应用形式来设置,通过fiddler抓包发现,只能失效一条,来来回回试了很屡次都只有一条,心态崩了
起初看到cookie设置数据也是相似键值对外面套键值对,眉头一皱;计上心来,变换下后就胜利了,记录下正确的写法吧
正确姿态
引入
- 应用的是flutter官网保护的webview插件
webview_flutter: ^0.3.22+1
谬误示例
- 这是最坑的一个,widget都都没写全,就写了俩个回调,这么写只会失效一条
WebViewController _controller;onWebViewCreated: (WebViewController wvc) { _controller = wvc;}onPageFinished: (String value) { _controller.evaluateJavascript( 'document.cookie = "SESSIONID=612bc4822b6996d6f335a963c20eb541fba72985; path=/"')}
- 这个只写了一条cookie,这个是没问题的,和下面的区别就是,这个应用双引号包住单引号,只写了一条的应用也是让人肝痛
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增加正确写法
- 推敲半天试出来的正确写法,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",)
- 最重要的变动就是每条cookie都要用document.cookie作为key,这是最最最要害的
优化写法
- 下面的写法是写成一行,写成一行是很致命的操作,让赋值操作会变得很蛊惑,优化下
///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",)
- ok,搞定
补充(弹窗封装,优化列表数据源)
- 就这么点内容就水了一片文章,显得我是个水笔,为了证实我不是个水笔,再补充个开发小技巧
成果
- 来看下封装后的应用
- 数据源List的泛型能够随便,showKey是你指定显示在弹窗列表上的字段
showBottomSingleDialog( context, list: list, showKey: 'name', callback: (item) { print(item.name); print(item.id); },);
- 效果图
阐明
底部单列表弹窗是十分实用的弹窗,然而可能大家常常有这样的一种应用体验,传数据源,个别都是传一个List类型,外部的泛型最最最常见的就是:String和固定的实体;说下这俩种状况的问题所在
String:显然该泛型,外部解决解决起来非常简单,间接拿String值展现就行,回调间接把抉择的String返回;这种String类型存在一个十分致命的的问题,在应用前后都存在问题
- 应用前:咱们必须把数据类型转换成List<String>类型,咱们数据源个别都是通过接口获取,接口外面List数据源外面的泛型形形色色的,往往须要做循环转化成List<String>类型去应用
- 应用后:点击抉择后,拿到咱们抉择的展现名,接口提交往往是须要该种抉择类型的id,一般来说还须要去做遍历拿出抉择名称对应的id,而后保留做提交操作
规定实体:应用规定的泛型实体,有一个益处,能够防止在应用后去遍历比照,而后去取id的操作,所以他只存在应用前的麻烦
- 应用前:这里咱们必须把拿到的数据源转换符合要求的List规定实体泛型,这步操作就能够把id等信息一起放在规定的实体外面,抉择之后也能够间接从实体外面拿了
吐槽:尽管下面俩种状况,第二种显著优于第一种,然而理论开发中,往往不假思索的用第一种,因为第一种不必去新建一个class啊!而后用起来就蛋痛了;有没有一种办法能够一劳永逸的办法呢,数据的list泛型轻易用,只用指定泛型实体用于展现的key;而后在回调外面又能拿到咱们传的实体呢?通过dart弱小的动静类型,加一些奇妙转换是齐全能够的
实现思路
java里能够通过泛型+反射;而后指定一个展现的key,实践上也是能够实现,我没试过,大家能够试试
实现思路
实现办法还是很简略的,这里说下思路就行了
实现步骤
数据源定义为List<E>类型,而后指定一个展现的key
- 泛型不指定的话,会默认为动静类型,这样的话,便有了很大的操作空间
- 遍历这个List,而后拿到遍历列表时的实体
- 将实体转换成Map类型,通过指定的key,获取展现内容就行了
- 回调时,传进去选的实体就ok,似不似很简略
举例
- 引入:flutter_picker
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));}
应用
- 这中央指不指定泛型都是能够的,不指定泛型默认为动静类型,item点的时候没有提醒,能够凭着本人的记忆写key值,只有是key是对,齐全能拿到数据
///指定泛型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); },);
成果试用
- https://cnad666.gitee.io/flutter_use/#/dialog
最初
代码地址
- Github:范例我的项目代码地址