写点什么

Dart 层如何 兼容 Android 和 iOS 平台特性 (1),Android 开发面试技巧

用户头像
Android架构
关注
发布于: 刚刚

private fun isApplicationAvilible(packageName: String): Boolean {val installedPackages = packageManager.getInstalledPackages(0)if (installedPackages != null) {for (packageInfo in installedPackages) {if (packageInfo.packageName == packageName) {return true}}}return false}


}


到此 flutter 调用 Android 就完成了,看起来还是挺简单的。


由于没有 iPhone 真机,模拟器上没有安装 微信,就以打开浏览器为例子吧:


@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {GeneratedPluginRegistrant.register(with: self)let controller : FlutterViewController = window?.rootViewController as! FlutterViewController;// 1. 声明方法通道 let batteryChannel = FlutterMethodChannel.init(name: "samples.chenhang/utils",binaryMessenger: controller.binaryMessenger);batteryChannel.setMethodCallHandler({//2.处理 flutter 的请求(call: FlutterMethodCall, result: FlutterResult) -> Void inif(call.method=="openWeChat"){// 处理方法名为 openWeChat 的请求 self.openWeChat()result(0)}else{result(FlutterMethodNotImplemented)}// Handle battery messages.});return super.application(application, didFinishLaunchingWithOptions: launchOptions)}// 调用原生打开浏览器 func openWeChat() {let urlString = "https://flutterchina.club/platform-channels/"let url = URL(string: urlString)if #available(iOS 10.0, *) {UIApplication.shared.open(url!, options: [:], completionHandler: nil)} else {// Fallback on earlier versions}}}


找到 找到 Flutter 应用的入口,也就是在 AppDelegate,然后在 application 方法中进行 flutter 的请求处理。

flutter 如何使用原生视图

通过方法通道,我们可以把原生操作系统提供的底层能力,以及现有原生开发中一些相对成熟的解决方案,以接口封装的形式在 Dart 层快速搞定,从而解决原生代码在 Flutter 上的复用问题。然后,我们可以利用 Flutter 本身提供的丰富控件,做好 UI 渲染。


是不是只要通过方法通道就完成了 APP 开发中的所有事情呢?显然并不是这样的,下面我们一起来看看复杂 APP 的构建都有什么组成。



通过 flutter 和方法通道,我们可以解决了应用层能力、应用层渲染、底层能力但是 对于那些涉及到底层渲染,比如浏览器、相机、地图,以及原生自定义视图的场景,自己在 Flutter 上重新开发一套显然不太现实。


Flutter 提供了一个平台视图(Platform View)的概念。它提供了一种方法,允许开发者在 Flutter 里面嵌入原生系统(Android 和 iOS)的视图,并加入到 Flutter 的渲染树中,实现与 Flutter 一致的交互体验。


创建平台视图的流程:


  • 首先,由作为客户端的 Flutter,通过向原生视图的 Flutter 封装类(在 iOS 和 Android 平台分别是 UIKitView 和 AndroidView)传入视图标识符,用于发起原生视图的创建请求;

  • 然后,原生代码侧将对应原生视图的创建交给平台视图工厂(PlatformViewFactory)实现;

  • 最后,在原生代码侧将视图标识符与平台视图工厂进行关联注册,让 Flutter 发起的视图创建请求可以直接找到对应的视图创建工厂。


下面就以一个 使用 Android TextView 和 iOS 的 UIText 为例子:


flutter 端


// 加载原生视图,Android 使用:AndroidView;ios 使用 UiKitViewclass NativeWidget extends StatelessWidget {@overrideWidget build(BuildContext context) {if (defaultTargetPlatform == TargetPlatform.android) {return AndroidView(viewType: "com.example.flutter_base_app/textView");} else {return UiKitView(viewType: "com.example.flutter_base_app/textView",);}}}


class NativeWidgetDemo extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("显示原生控件"),),body: Center(child: NativeWidget(),),);}}


非常简单,只需要根据不同平台,创建不同的 widget 即可;Android 为 AndroidView;ios 为 UiKitView。

Android:

  1. 构建返回的 view 继承 PlatformView


class NativeTextView(val context: Context?, val message: BinaryMessenger) : PlatformView, MethodChannel.MethodCallHandler {// 传入 BinaryMessenger 只是为了创建 MethodChannel 使用 private var textView: TextView? = nullprivate val updateText = "update_text"


init {textView = TextView(context)textView?.t


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ext = "我是来自 Android 的 textView"val methodChannel = MethodChannel(message, "")methodChannel.setMethodCallHandler(this)}


override fun getView(): View {return textView!!}


override fun dispose() {}


override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {when (call.method) {updateText -> {


}}


}


}


  1. 创建 视图工厂 实现


class NativeViewFactory(private val message: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {return NativeTextView(context = context, message = message)}


}


  1. 自定义 Plugin 类,注册视图工厂


object NativeViewPlugin {private val viewTypeId = "com.example.flutter_base_app/textView"


fun registerWith(flutterEngine: FlutterEngine?) {flutterEngine?.let {val key = NativeViewPlugin::class.java.canonicalNameval shimPluginRegistry = ShimPluginRegistry(flutterEngine);if (shimPluginRegistry.hasPlugin(key)) returnval registry = shimPluginRegistry.registrarFor(key)registry.platformViewRegistry().registerViewFactory(viewTypeId, NativeViewFactory(registry.messenger()))}


}}

iOS

  1. 在 info.plist 添加 io.flutter.embedded_views_preview= true



2. 创建返回的视图类


import Foundation


import Foundationimport Flutterclass PlatformTextView: NSObject,FlutterPlatformView {let frame: CGRect;let viewId: Int64;var text:String = ""


init(_ frame: CGRect,viewID: Int64,args :Any?) {self.frame = frameself.viewId = viewID// if(args is NSDictionary){// let dict = args as! NSDictionary// self.text = dict.value(forKey: "text") as! String// }}func view() -> UIView {let label = UILabel()

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Dart 层如何 兼容 Android 和iOS平台特性 (1),Android开发面试技巧