Flutter 59: 图解 Android Native 获取 Flutter 资源文件
小菜前段时间研究了 Android Native 与 Flutter 之间的交互;若两端均需要相同资源文件,若不能共享则势必会增加整体包大小;今天和尚研究一下如何通过 Android Native 获取 Flutter 中资源文件;
官网对于 assets 介绍很简洁,使用过程代码量也很少,虽简洁但依然值得研究;小菜以 Android 为主工程,Flutter 作为 Module 进行测试;
FlutterView
小菜在学习 Android 与 Flutter 交互时会用到 FlutterView 作为桥接控件;而对于资源文件的获取也同样适用;其核心方法是 getLookupKeyForAsset;
源码分析
逐层分析源码,通过 getLookupKeyForAsset 方法我们可以获取资源文件的路径,根目录是固定的 flutter_assets 而非 Module 名;
public String getLookupKeyForAsset(String asset) { return FlutterMain.getLookupKeyForAsset(asset); } public static String getLookupKeyForAsset(String asset) { return fromFlutterAssets(asset); } private static String fromFlutterAssets(String filePath) { return sFlutterAssetsDir + File.separator + filePath; } private static String sFlutterAssetsDir = "flutter_assets";
案例测试
小菜通过 getLookupKeyForAsset 获取文件路径,以 images/ic_launcher.png 图片为例,借助 assetManager.open 转为流信息转为 Bitmap 进行展示;
// 文件路径:flutter_assets/images/ic_launcher.png try { AssetManager assetManager = getAssets(); InputStream is = assetManager.open(flutterView.getLookupKeyForAsset("images/ic_launcher.png")); Bitmap bitmap = BitmapFactory.decodeStream(is); flutterIv.setImageBitmap(bitmap); } catch (Exception e) { System.out.println("异常信息:" + e.toString()); }
小菜测试可以用如下方式获取资源文件路径;
// Activity flutterView.getLookupKeyForAsset("images/ic_launcher.png"); // Fragment (FlutterView) getView().getLookupKeyForAsset("images/ic_launcher.png"); // 通用 FlutterMain.getLookupKeyForAsset("images/ic_launcher.png");
PluginRegistry.Registrar
另一种常用的方式是以插件方式,Flutter 在使用 AndroidView 方式嵌入 Native View 与 Android 进行交互时;核心方法同样是 lookupKeyForAsset 获取资源路径,之后便是用原生方法解析 assets 资源文件;
小菜测试时主要注意两点:
- 获取 PluginRegistry.Registrar,不能直接 new 对象,需要注册自定义 Native View;
- 在获取文件路径后尝试了 AssetFileDescriptor 方式解析数据流,完全可以用于 assetManager.open 方式解析;
// 文件路径:flutter_assets/images/ic_launcher.png // Flutter 端 Container( child: AndroidView( viewType: "com.ace.ace_demo01/method_layout", creationParamsCodec: const StandardMessageCodec(), creationParams: {'method_layout_size': 450}), color: Colors.greenAccent, height: 200.0) // Android 端 final String key = "NMethodLayout"; if (this.hasPlugin(key)) return; PluginRegistry.Registrar registrar = this.registrarFor(key); registrar.platformViewRegistry() .registerViewFactory("com.ace.ace_demo01/method_layout", new NMethodLayoutFactory(registrar.messenger())); try { AssetManager assetManager = registrar.context().getAssets(); String assetKey = registrar.lookupKeyForAsset("images/ic_launcher.png"); AssetFileDescriptor fileDescriptor = assetManager.openFd(assetKey); Bitmap bitmap = BitmapFactory.decodeStream(fileDescriptor.createInputStream()); mIv.setImageBitmap(bitmap); } catch (Exception e) { e.printStackTrace(); }
注意事项
无论是 FlutterView 还是 PluginRegistry.Registrar 方式均需 lookupKeyForAsset 获取 Flutter 端资源文件路径,且获取类型与原生 assets 中一致;小菜测试获取一个 json 文件进行解析;
final String key = "NMethodLayout"; if (this.hasPlugin(key)) return; PluginRegistry.Registrar registrar = this.registrarFor(key); registrar.platformViewRegistry() .registerViewFactory("com.ace.ace_demo01/method_layout", new NMethodLayoutFactory(registrar.messenger())); try { AssetManager assetManager = registrar.context().getAssets(); Log.e("===getJson===", getJson(registrar.lookupKeyForAsset("images/star.json"))); } catch (Exception e) { e.printStackTrace(); } public String getJson(String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { //获取assets资源管理器 AssetManager assetManager = getAssets(); //通过管理器打开文件并读取 InputStreamReader inputReader = new InputStreamReader( assetManager.open(fileName) ); BufferedReader bufReader = new BufferedReader(inputReader); String line="", result=""; while((line = bufReader.readLine()) != null) result += line; return result; } catch (IOException e) { e.printStackTrace(); } return stringBuilder.toString(); } // ===getJson===: { "stars": [ { "name": "水瓶座", "name_en": "Aquarius" }, { "name": "双鱼座", "name_en": "Pisces" }, { "name": "白羊座", "name_en": "Aries" }, { "name": "金牛座", "name_en": "Taurus" }, { "name": "双子座", "name_en": "Gemini" }, { "name": "巨蟹座", "name_en": "Cancer" }, { "name": "狮子座", "name_en": "Leo" }, { "name": "处女座", "name_en": "Virgo" }, { "name": "天秤座", "name_en": "Libra" }, { "name": "天蝎座", "name_en": "Scorpio" }, { "name": "射手座", "name_en": "Sagittarius" }, { "name": "摩羯座", "name_en": "Capricorn" } ]}
小菜还未成功尝试 Flutter 获取 Native 的资源文件,依旧是从零探索中;如有错误请多多指导!
来源: 阿策小和尚
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android Studio ARouter插件
点一下图上的定位按钮就会跳到对应的activity当中去
- 下一篇
UITableView 组件化
源起 在 iOS 开发中,UITableView 可以说是最常用的控件。几行代码,实现对应方法,系统就会给你呈现一个 60 帧无比流畅的列表,让初学者成就感爆棚。然而随着开发的深入,我们就会慢慢觉察到当前的 UITableView 实现会有这样或那样的问题。 繁琐的重用流程 几乎所有 TableView Adapter 中都有如下的代码registerClass(Nib):forCellReuseIdentifier进行 cell 重用的注册,后续又需要使用dequeueReusableCellWithIdentifier:获取对应 cell。苹果的这套重用机制对于开发者来说相当简单友好,但写多了难免觉得重复乏味。同时如何给 cell 设置一个有意义且不重复的 reuseIdentifier 又会成为众多强迫症程序员的烦恼之一。 不安全的 model 和 cell 映射关系 随着业务深入,一个 UITableView 往往会包含多种 model,对应不同形式的 cell,那么建立 model 和 cell 的映射关系就会非常蛋疼,无论是if else,switch,还是 map 都不是...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境