1.分析上一節(jié)中Web插件的不足
- methodchannel是通過(guò)字節(jié)數(shù)組傳遞的在web中是比必要的,因?yàn)閣eb最后都是js代碼
For one, there is unnecessary overhead of sending plugin method calls over a MethodChannel. On the web, your entire app is compiled into one JavaScript bundle, so the plugin code is needlessly serializing the method call into a byte array, which is then instantly deserialized by the web plugin.
- methodchannel 使用字符串和插件匹配遵堵,在其他平臺(tái)箱玷,這個(gè)web插件是不必要的,上一講的寫(xiě)法不利于屏蔽web插件代碼
Another disadvantage of using a MethodChannel is that it makes it difficult for the compiler to remove (by tree-shaking) unused plugin code. The web plugin calls the appropriate method based on the name of the method call passed by the MethodChannel, so the compiler has to assume that all of the methods in the plugin are live, and none of them can be tree-shaken out
2.interface模塊引入陌宿,依賴(lài)關(guān)系如下
3.關(guān)鍵代碼分析
平臺(tái)接口的launch和closeWebView對(duì)應(yīng)原來(lái)methodChannel方法
import 'dart:async';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:url_launcher_platform_interface/link.dart';
import 'method_channel_url_launcher.dart';
abstract class UrlLauncherPlatform extends PlatformInterface {
/// Constructs a UrlLauncherPlatform.
UrlLauncherPlatform() : super(token: _token);
static final Object _token = Object();
static UrlLauncherPlatform _instance = MethodChannelUrlLauncher();
/// The default instance of [UrlLauncherPlatform] to use.
///
/// Defaults to [MethodChannelUrlLauncher].
static UrlLauncherPlatform get instance => _instance;
themselves.
// TODO(amirh): Extract common platform interface logic.
// https://github.com/flutter/flutter/issues/43368
static set instance(UrlLauncherPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
/// The delegate used by the Link widget to build itself.
LinkDelegate? get linkDelegate;
/// Returns `true` if this platform is able to launch [url].
Future<bool> canLaunch(String url) {
throw UnimplementedError('canLaunch() has not been implemented.');
}
/// Returns `true` if the given [url] was successfully launched.
///
/// For documentation on the other arguments, see the `launch` documentation
/// in `package:url_launcher/url_launcher.dart`.
Future<bool> launch(
String url, {
required bool useSafariVC,
required bool useWebView,
required bool enableJavaScript,
required bool enableDomStorage,
required bool universalLinksOnly,
required Map<String, String> headers,
String? webOnlyWindowName,
}) {
throw UnimplementedError('launch() has not been implemented.');
}
/// Closes the WebView, if one was opened earlier by [launch].
Future<void> closeWebView() {
throw UnimplementedError('closeWebView() has not been implemented.');
}
}
url_lancher_web給出實(shí)現(xiàn)
注意registerWith不再是創(chuàng)建個(gè)methodChannel接收調(diào)用锡足,而是更加平臺(tái)接口的實(shí)現(xiàn)為當(dāng)前web插件
UrlLauncherPlatform.instance = UrlLauncherPlugin();
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:html' as html;
import 'src/shims/dart_ui.dart' as ui;
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:meta/meta.dart';
import 'package:url_launcher_platform_interface/link.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import 'src/link.dart';
import 'src/third_party/platform_detect/browser.dart';
const _safariTargetTopSchemes = {
'mailto',
'tel',
'sms',
};
String? _getUrlScheme(String url) => Uri.tryParse(url)?.scheme;
bool _isSafariTargetTopScheme(String url) =>
_safariTargetTopSchemes.contains(_getUrlScheme(url));
/// The web implementation of [UrlLauncherPlatform].
///
/// This class implements the `package:url_launcher` functionality for the web.
class UrlLauncherPlugin extends UrlLauncherPlatform {
html.Window _window;
bool _isSafari = false;
// The set of schemes that can be handled by the plugin
static final _supportedSchemes = {
'http',
'https',
}.union(_safariTargetTopSchemes);
/// A constructor that allows tests to override the window object used by the plugin.
UrlLauncherPlugin({@visibleForTesting html.Window? debugWindow})
: _window = debugWindow ?? html.window {
_isSafari = navigatorIsSafari(_window.navigator);
}
/// Registers this class as the default instance of [UrlLauncherPlatform].
static void registerWith(Registrar registrar) {
UrlLauncherPlatform.instance = UrlLauncherPlugin();
ui.platformViewRegistry.registerViewFactory(linkViewType, linkViewFactory);
}
@override
LinkDelegate get linkDelegate {
return (LinkInfo linkInfo) => WebLinkDelegate(linkInfo);
}
/// Opens the given [url] in the specified [webOnlyWindowName].
///
/// Returns the newly created window.
@visibleForTesting
html.WindowBase openNewWindow(String url, {String? webOnlyWindowName}) {
// We need to open mailto, tel and sms urls on the _top window context on safari browsers.
// See https://github.com/flutter/flutter/issues/51461 for reference.
final target = webOnlyWindowName ??
((_isSafari && _isSafariTargetTopScheme(url)) ? '_top' : '');
return _window.open('https://baidu.com', target);
}
@override
Future<bool> canLaunch(String url) {
return Future<bool>.value(_supportedSchemes.contains(_getUrlScheme(url)));
}
@override
Future<bool> launch(
String url, {
bool useSafariVC = false,
bool useWebView = false,
bool enableJavaScript = false,
bool enableDomStorage = false,
bool universalLinksOnly = false,
Map<String, String> headers = const <String, String>{},
String? webOnlyWindowName,
}) {
return Future<bool>.value(
openNewWindow('https://baidu.com', webOnlyWindowName: webOnlyWindowName) != null);
}
}
url_lancher插件接口修改
以前是主插件那里,發(fā)送個(gè)methodchannel調(diào)用壳坪,現(xiàn)在則是改成平臺(tái)接口調(diào)用舶得,而平臺(tái)接口的實(shí)現(xiàn)可以是通過(guò)methodchannel方式,而對(duì)應(yīng)web插件的實(shí)現(xiàn)爽蝴,則是直接調(diào)用了沐批,不再是methodchannel
插件url_launcher.dart
Future<bool> canLaunch(String urlString) async {
return await UrlLauncherPlatform.instance.canLaunch(urlString);
}
版本依賴(lài)和發(fā)布
目前認(rèn)為纫骑,先把被依賴(lài)的發(fā)布上去,和maven庫(kù)發(fā)布流程類(lèi)似吧九孩,具體沒(méi)有實(shí)際操作過(guò)先馆!