当前位置: 首页 > news >正文

网站建设客户相关问题用手机域名做网站

网站建设客户相关问题,用手机域名做网站,鄂州网站网站建设,如何不备案做购物网站本文由 句号君 授权投稿原文链接#xff1a;https://blog.csdn.net/qizewei123/article/details/102963340Flutter 官方在 GitHub 上声明是暂时不支持热更新的#xff0c;但是在 Flutter 的源码里#xff0c;是有一部分预埋的热更新相关的代码#xff0c;并且通过一些我们自… 本文由 句号君 授权投稿原文链接https://blog.csdn.net/qizewei123/article/details/102963340Flutter 官方在 GitHub 上声明是暂时不支持热更新的但是在 Flutter 的源码里是有一部分预埋的热更新相关的代码并且通过一些我们自己的手段在Android端是能够实现动态更新的功能的。Flutter 产物的探究不论是创建完全的 Flutter项目还是 Native以 Moudle的方式集成 Flutter亦或是 Native以 aar方式集成  Flutter最终  Flutter在 Andorid端的 App 都是以 Native项目 Flutter 的UI产物存在的。所以在这里拆开一个 Flutter在 release模式下编译后生成 aar包来做分析我们关注重点在 assetsjnilibs 这 3 个目录中其他的文件都是 Nactive层壳工程的产物。jni 该目录下存在文件 libflutter.so该文件为 Flutter Engine (引擎) 层的 C实现提供skia(绘制引擎)DartText(纹理绘制)等支持。libs该目录下存在文件为 flutter.jar该文件为 Flutter embedding (嵌入) 层的 Java实现该层提供给 Flutter 许多Native层平台系统功能的支持比如创建线程。assets:该目录下分为两部分flutter_assets 目录该目录下存放Flutter 我们应用层的资源包括images,font等isolate_snapshot_dataisolate_snapshot_instrvm_snapshot_datavm_snapshot_instr 文件这 4 个文件分别对应 isolate、VM 的数据段和指令段文件这就是我们自己的 Flutter 代码的产物了。Flutter 代码的热更新代码探究在我们的 Native 项目中会在 FlutterMainActivity 中通过调用 Flutter 这个类来创建 ViewflutterView  Flutter.createView(this, getLifecycle(), route);layoutParams  new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT);addContentView(flutterView, layoutParams);查看 Flutter 类代码发现 Flutter 类主要做了几件事使用 FlutterNative 加载 View设置路由使用 lifecycle 绑定生命周期使用 FlutterMain 初始化重点关注这里。public static FlutterView createView(NonNull final Activity activity, NonNull Lifecycle lifecycle, String initialRoute) {FlutterMain.startInitialization(activity.getApplicationContext());FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), (String[])null);FlutterNativeView nativeView  new FlutterNativeView(activity);所以真正初始化的相关代码是在 FlutterMian 中public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {    if (Looper.myLooper() ! Looper.getMainLooper()) {        throw new IllegalStateException(startInitialization must be called on the main thread);    } else if (sSettings  null) {        sSettings  settings;        long initStartTimestampMillis  SystemClock.uptimeMillis();        initConfig(applicationContext);        initAot(applicationContext);        initResources(applicationContext);        System.loadLibrary(flutter);        long initTimeMillis  SystemClock.uptimeMillis() - initStartTimestampMillis;        nativeRecordStartTimestamp(initTimeMillis);    }}在 startInitialization 中主要执行了三个初始化方法 initConfig(applicationContext)initAot(applicationContext)initResources(applicationContext)最后记录了执行时间。在 initConfig 中private static void initConfig(Context applicationContext) {    try {        Bundle metadata  applicationContext.getPackageManager().getApplicationInfo(applicationContext.getPackageName(), 128).metaData;        if (metadata ! null) {            sAotSharedLibraryPath  metadata.getString(PUBLIC_AOT_AOT_SHARED_LIBRARY_PATH, app.so);            sAotVmSnapshotData  metadata.getString(PUBLIC_AOT_VM_SNAPSHOT_DATA_KEY, vm_snapshot_data);            sAotVmSnapshotInstr  metadata.getString(PUBLIC_AOT_VM_SNAPSHOT_INSTR_KEY, vm_snapshot_instr);            sAotIsolateSnapshotData  metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_DATA_KEY, isolate_snapshot_data);            sAotIsolateSnapshotInstr  metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_INSTR_KEY, isolate_snapshot_instr);            sFlx  metadata.getString(PUBLIC_FLX_KEY, app.flx);            sFlutterAssetsDir  metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, flutter_assets);         }    } catch (NameNotFoundException var2) {        throw new RuntimeException(var2);    }}在 initResources 中sResourceExtractor  new ResourceExtractor(applicationContext);sResourceExtractor.addResource(fromFlutterAssets(sFlx)).addResource(fromFlutterAssets(sAotVmSnapshotData)).addResource(fromFlutterAssets(sAotVmSnapshotInstr)).addResource(fromFlutterAssets(sAotIsolateSnapshotData)).addResource(fromFlutterAssets(sAotIsolateSnapshotInstr)).addResource(fromFlutterAssets(kernel_blob.bin));if (sIsPrecompiledAsSharedLibrary) {    sResourceExtractor.addResource(sAotSharedLibraryPath);} else {    sResourceExtractor.addResource(sAotVmSnapshotData).addResource(sAotVmSnapshotInstr).addResource(sAotIsolateSnapshotData).addResource(sAotIsolateSnapshotInstr);} sResourceExtractor.start();在 ResourceExtractor 类中通过名字就能知道这个类是做资源提取的。把 add 的 Flutter 相关文件从 assets 目录中取出来该类中 ExtractTask 的 doInBackground 方法中File dataDir new File(PathUtils.getDataDirectory(ResourceExtractor.this.mContext))这句话指定了资源提取的目的地即 data/data/包名/app_flutter如下如图可以看到该目录是的访问权限是可读可写所以理论上我们只要把自己的 Flutter 产物下载后从内存 copy 到这里便能够实现代码的动态更新。代码实现public class FlutterUtils {    private static String TAG  FlutterUtils.class;    private static String flutterZipName  flutter-code.zip;    private static String fileSuffix  .zip;    private static String zipPath  Environment.getExternalStorageDirectory().getPath()  /k12/  flutterZipName;    private static String targetDirPath  zipPath.replace(fileSuffix, );    private static String targetDirDataPath  zipPath.replace(fileSuffix, /data);    /** * Flutter 代码热更新第一步 解压 Flutter 的压缩文件 */    public static void unZipFlutterFile() {        Log.i(TAG, unZipFile: Start);        try {            unZipFile(zipPath, targetDirPath);            Log.i(TAG, unZipFile: Finish);        } catch (Exception e) {            e.printStackTrace();        }    }    /** * Flutter 代码热更新第二步 将 Flutter 的相关文件移动到 AppData 的相关目录,APP启动时调用 * * param mContext 获取 AppData 目录需要 */    public static void copyDataToFlutterAssets(Context mContext) {        String appDataDirPath  PathUtils.getDataDirectory(mContext.getApplicationContext())  File.separator;        Log.d(TAG, copyDataToFlutterAssets-filesDirPath:  targetDirDataPath);        Log.d(TAG, copyDataToFlutterAssets-appDataDirPath:  appDataDirPath);        File appDataDirFile  new File(appDataDirPath);        File filesDirFile  new File(targetDirDataPath);        File[] files  filesDirFile.listFiles();        for (File srcFile : files) {            if (srcFile.getPath().contains(isolate_snapshot_data)                || srcFile.getPath().contains(isolate_snapshot_instr)                || srcFile.getPath().contains(vm_snapshot_data)                || srcFile.getPath().contains(vm_snapshot_instr)) {                File targetFile  new File(appDataDirFile  /  srcFile.getName());                FileUtil.copyFileByFileChannels(srcFile, targetFile);                Log.i(TAG, copyDataToFlutterAssets-copyFile:  srcFile.getPath());            }        }        Log.i(TAG, copyDataToFlutterAssets: Finish);    }    /** * 解压缩文件到指定目录 * * param zipFileString 压缩文件路径 * param outPathString 目标路径 * throws Exception */    private static void unZipFile(String zipFileString, String outPathString) {        try {            ZipInputStream inZip  new ZipInputStream(new FileInputStream(zipFileString));            ZipEntry zipEntry;            String szName  ;            while ((zipEntry  inZip.getNextEntry()) ! null) {                szName  zipEntry.getName();                if (zipEntry.isDirectory()) {                    szName  szName.substring(0, szName.length() - 1);                    File folder  new File(outPathString  File.separator  szName);                    folder.mkdirs();                } else {                    File file  new File(outPathString  File.separator  szName);                    if (!file.exists()) {                        Log.d(TAG, Create the file:  outPathString  File.separator  szName);                        file.getParentFile().mkdirs();                        file.createNewFile();                    }                    FileOutputStream out  new FileOutputStream(file);                    int len;                    byte[] buffer  new byte[1024];                    while ((len  inZip.read(buffer)) ! -1) {                        out.write(buffer, 0, len);                        out.flush();                    }                    out.close();                }            }            inZip.close();        } catch (Exception e) {            Log.i(TAG,e.getMessage());            e.printStackTrace();        }    }    /** * 使用FileChannels复制文件。 * * param source 原路径 * param dest 目标路径 */    public static void copyFileByFileChannels(File source, File dest) {        FileChannel inputChannel  null;        FileChannel outputChannel  null;        try {            inputChannel  new FileInputStream(source).getChannel();            outputChannel  new FileOutputStream(dest).getChannel();            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());            refreshMedia(BaseApplication.getBaseApplication(), dest);        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                inputChannel.close();                outputChannel.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /** * 更新媒体库 * * param cxt * param files */    public static void refreshMedia(Context cxt, File... files) {        for (File file : files) {            String filePath  file.getAbsolutePath();            refreshMedia(cxt, filePath);        }    }    public static void refreshMedia(Context cxt, String... filePaths) {        MediaScannerConnection.scanFile(cxt.getApplicationContext(),                                        filePaths, null,                                        null);    }}Flutter 资源的热更新我们的App安装到手机上后是很难再修改 Assets 目录下的资源所以关于资源的替换目前的方案是使用 Flutter 的 API Image.file() 来从存储卡中读取图片。通常我们的 Flutter 项目中应当存有关于 App 的图片尽量保证在热更新的时候使用已经存在的图片。其次我们可以使用 Image.network() 来加载网络资源的图片如果还不能满足需求兜底的方案就是使用 Image.file()将资源图片放到Zip目录下一起下发并在Flutter代码中使用 Image.file() 来加载。通过 Native 层方法拿到图片文件夹的内存地址 dataDir判断图片是否存在存在则加载不存在则加载已经存在的图片占位new File(dataDir hotupdate_test.png).existsSync()? Image.file(new File(dataDir hotupdate_test.png)): Image.asset(images/net_error.png),总结在 Flutter 代码产物替换中因为替换的 4 个文件皆为直接加载到内存中的引擎代码所以这部分优化空间有限。但在资源的热更新中资源是从Assets取得所以这里应该有更优的方案。Flutter 的热更新意味着可以实在App的一个入口里像 H5 一样无穷的嵌入页面但又有和原生媲美的流畅体验。未来 Flutter 热更新技术如果成熟应用开发可能只需要 Android端和 IOS端实现本地业务功能模块的封装业务和UI的代码都放在 Flutter 中便能够真正的实现移动两端一份业务代码并且赋予产品在不影响用户体验的情况下拥有动态部署APP内容的能力。推荐阅读如何写出让同事好维护的代码一线大厂的程序员职级对标真正的强者敢于在寒冬里裸辞编程·思维·职场欢迎扫码关注
http://www.huolong8.cn/news/264809/

相关文章:

  • 群站优化之链轮模式教育类网站如何做
  • 网站建设广告平台推广免费网站建设平台哪个好
  • 建设网站五个步骤成都软件开发外包
  • 做实验教学视频的网站微网站建设价格
  • 浙江省建设厅网站证件哪有做网站公司
  • 北京时间网站建设网站登录怎么退出
  • wordpress建站插件安全汉口网站制作
  • 官方网站建设哪家公司好网站群建设技术规范
  • 苏州建设招聘信息网站宣传软文模板
  • 创意经济型网站建设友链大全
  • 东莞网站优化公免签支付接入wordpress
  • 网站建设的总体设计思想新余百度网站建设
  • 丽江手机网站建设截止今天全世界新冠病人多少
  • 上海企业网站模板建站wordpress文章图片怎么居中
  • wordpress插件图片无法加载网站开发seo要求
  • 备案号注销了 新网站怎么备案上海科技网站设计建设
  • 如何运用网站模板装修公司网页设计模板
  • 如何在图片上做网站水印图类似源码之家的网站
  • 优秀购物网站成都网络优化网站建设
  • wordpress xml大于2m宁波seo哪家好推广
  • 宿州网站建设网站珠海公众号开发
  • 云南高端网站制作价格长沙市教育局官网
  • 如何进行网站建设设计机构
  • 昆明企业网站模板建站企业所得税优惠政策最新2023年100万以下
  • 大连零基础网站建设教学服务网站开发公司上
  • 网站建设服务费账务处理笑话小网站模板html
  • 佛山网站建设专业的公司国际网站怎么做
  • 发布了一个网站 显示建设中上海做网站的
  • 开福区城乡建设局门户网站汽车保养网站模板
  • 如何创建网站系统教程如何在百度上为企业做网站