flutter_webview_plugin & fluro 实现 app webview 所有功能
安装
核心webview实现
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import './login.dart';
import '../bottom_navigation_widget.dart';
import '../utils/storage.dart';
import '../router/custome_router.dart';
_setUrl (String url) {
if (url.indexOf('?')> -1) {
return '$url&v=${DateTime.now().millisecondsSinceEpoch}';
} else {
return '$url?v=${DateTime.now().millisecondsSinceEpoch}';
}
}
class WebWiew extends StatefulWidget {
String url;
String sessionId;
String token;
WebWiew(
this.url,
[this.sessionId,
this.token,]
);
@override
_WebWiewState createState() => _WebWiewState();
}
class _WebWiewState extends State<WebWiew> {
FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin();
String title = "页面跳转中";
String _thisUrl = '';
String _intUrl = '';
//获取h5页面标题
getWebTitle() async {
String script = 'window.document.title';
var title = await
flutterWebviewPlugin.evalJavascript(script);
setState(() {
this.title = title.replaceAll('\"',' ');
});
}
@override
void initState() {
super.initState();
flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged webViewState) async {
print('onStateChanged');
switch (webViewState.type) {
case WebViewState.finishLoad:
break;
case WebViewState.shouldStart:
break;
case WebViewState.startLoad:
break;
case WebViewState.abortLoad:
break;
}
});
/**
* 监听页面加载url
*/
flutterWebviewPlugin.onUrlChanged.listen((String url) {
setState(() {
_thisUrl = url;
});
if (_intUrl == ''){
setState(() {
_intUrl = url;
});
}
print(url);
getWebTitle();
if (url.indexOf('authorize.html') > -1) {
clearToken();
flutterWebviewPlugin.stopLoading();
// 关闭webView 跳转到app登录页
flutterWebviewPlugin.close();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) => Login()),
(route) => route == null
);
}
});
}
@override
Widget build(BuildContext context) {
return Container(
child: WebviewScaffold(
url: _setUrl(widget.url),
// 默认加载地址
appBar: AppBar(
title: Text(title),
leading:Container(
padding: EdgeInsets.only(left:4.0),
child: InkWell(
child: Icon(Icons.arrow_back_ios),
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
// 使用自定义的动画跳转路由
CustomRoute(BottomNavigationWidget()),
// MaterialPageRoute(builder: (BuildContext context) => BottomNavigationWidget()),
(route) => route == null
);
},
),
),
),
scrollBar: false,
withZoom: false,
headers: {
'app-session-id': widget.sessionId,
'x-auth-token': widget.token,
}
)
);
}
@override
void dispose() {
flutterWebviewPlugin.dispose();
super.dispose();
}
void setHeaders () {
// flutterWebviewPlugin
}
}
fluro 使用
/// application.dart
import 'package:fluro/fluro.dart';
class Application {
static Router router;
}
/// route_handlers.dart
var rootHandler = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return Home();
});
var mycenterHandler = Handler(
handlerFunc: (BuildContext context, Map <String, dynamic> params) {
String sessionId = params['sessionId']?.first;
String token = params['token']?.first;
String id = params['arg1']?.first;
String agency = params['arg2']?.first;
return WebWiew('${baseUrl}static/mycenter.html', sessionId, token);
});
var withoutLoginPageHandler = Handler(
handlerFunc: (BuildContext context, Map <String, dynamic> params) {
String url = params['url']?.first;
print(url);
return WebWiew(Uri.decodeComponent(url));
}
);
/// routers.dart
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import './route_handlers.dart';
class Routes {
static String root = '/';
static String myCenter = '/mycenter';
static String withoutLoginPage = '/withoutLoginPage';
static void configureRoutes(Router router){
router.notFoundHandler= new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params){
print('ERROR====>ROUTE WAS NOT FONUND!!!');
return null;
}
);
router.define(root, handler: rootHandler);
router.define(myCenter, handler: mycenterHandler);
router.define('withoutLoginPage/:url', handler: withoutLoginPageHandler);
}
}
封装一个HTTP请求
import 'dart:io';
import 'dart:convert';
import 'dart:async';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import '../config/config.dart';
import '../common/eventBus.dart';
import '../utils/storage.dart';
import '../utils/tools.dart';
class HttpUtils {
/// global dio object
static Dio dio;
/// http request methods
static const String GET = 'get';
static const String POST = 'post';
static const String PUT = 'put';
static const String PATCH = 'patch';
static const String DELETE = 'delete';
/// request method
static Future<Map> request (
String url,
{ data, method}) async {
data = data ?? {};
method = method ?? 'GET';
data.forEach((key, value) {
if (url.indexOf(key) != -1) {
url = url.replaceAll(':$key', value.toString());
}
});
/// 打印请求相关信息:请求地址、请求方式、请求参数
print('请求地址:【' + method + ' ' + url + '】');
print('请求参数:' + jsonEncode(data));
Dio dio = createInstance();
var result;
try {
Response response = await dio.request(
url,
data: FormData.from(data),
options: new Options(
method: method,
contentType: ContentType.parse("application/x-www-form-urlencoded;charset=utf-8"),
)
);
if (response.statusCode != 200) {
toastError('请求服务器失败');
return null;
} else {
result = jsonDecode(response.data);
return result;
}
/// 打印响应相关信息
print('响应数据:' + response.toString());
} on DioError catch (e) {
/// 打印请求失败相关信息
print('请求出错:' + e.toString());
toastError('请求服务器失败');
}
}
/// 创建 dio 实例对象
static Dio createInstance () {
if (dio == null) {
/// 全局属性:请求前缀、连接超时时间、响应超时时间
BaseOptions options = new BaseOptions(
baseUrl: baseUrl,
connectTimeout: 15000,
receiveTimeout: 30000,
contentType: ContentType.JSON,
responseType: ResponseType.plain,
);
dio = new Dio(options);
// Fiddler抓包设置代理
// (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client){
// client.findProxy = (url){
// return "PROXY 192.168.50.85:8888";
// };
// };
dio.interceptors.add(InterceptorsWrapper(
onRequest:(RequestOptions options){
// 来自app的请求 后期可以做特殊处理
options.headers["x-auth-from"] = 'fromApp';
// 在请求被发送之前做一些事情
return options; //continue
},
onResponse:(Response response) {
// 在返回响应数据之前做一些预处理
if(response.toString() == 'InvalidToken') {
print('请求拦截数据====未登录 跳转登录页面======');
eventBus.fire(LoginEvent(true));
clearToken();
return null;
} else {
var _token = response.headers['x-auth-token'];
if (_token != null) setToken(_token[0]);
var sessionId = response.headers['app-session-id'];
if (sessionId != null) setSessionId(sessionId[0]);
return response; // continue
}
},
onError: (DioError e) {
// 当请求失败时做一些预处理
return e;//continue
}
));
var cj = new CookieJar();
dio.interceptors.add(CookieManager(cj));
}
// 获取cookie
// List results = cj.loadForRequest(Uri.parse(baseUrl));
// if (results.length >= 1) {
// setSessionId(results[1].toString().split(';')[0].split('=')[1]);
// }
return dio;
}
/// 清空 dio 对象
static clear () {
dio = null;
}
}
HTTP使用
Future refreshToken () async {
final prefs = await SharedPreferences.getInstance();
var result = await HttpUtils.request(
api['refreshToken'],
method: HttpUtils.POST,
data: {
'x-auth-token': prefs.getString('token')
}
);
return result;
}
持续增加中……