分类: 默认

  • Flutter中的IoC

    因为长期做后端开发,Spring提供的IoC功能确实用的很多。到了Flutter中各种依赖项目的管理也很麻烦,也影响单元测试的编写。

    所以在Flutter还是希望延续平时的习惯,使用IoC去控制依赖等关系。但是Flutter中有一些特殊的情况,比如Flutter禁用了dart:mirrors,反射的使用上有一些问题。对比了几个框架,最开始考虑的是Google下面的inject.dart,但是文档这块比较缺,还有就是注解+代码生成的方式强大,但是不是很喜欢,也用不了这么强的功能。由于名字的原因也看了下ioc库(https://pub.dev/packages/ioc),对于API的语法不是很喜欢。最后选择使用GetIt。

    使用上比较简单,引用依赖

    dependencies:
      get_it: ^3.1.0

    代码中专门配置一个方法用于管理所有依赖配置

    class IocConfiguration {
      configDependencies(
          {AnalysisService analysisService}) {
        var loader = GetIt.I;
    
        loader
            .registerLazySingleton<LoggingService((() =SimpleLoggingService()));
    
        if (analysisService != null) {
          loader.registerLazySingleton<AnalysisService((() =analysisService));
        } else {
          loader.registerLazySingleton<AnalysisService(
              (() 
  • Flutter快速构建设置界面

    Flutter快速构建设置界面

    设置(settings)一般是指用于配置App相关内容,看图比较直观

    对于设置界面的子项目来说一般有几种常见的类型

    • 输入类型(如展示的用户名)
    • 勾选类型(如是否允许后台推送)
    • 滑动设置(如音量大小)
    • 选项(如缓冲策略等)

    shared_preferences_settings提供了常用的选项和UI,同时设置结果持久化在shared_prefrences中,可以快速构建设置页面。

    在依赖中加入

    shared_preferences_settings:
        git:
          url: https://github.com/BarthaBRW/shared_preferences_settings.git
          ref: 9857951c728bd23df27995ef92da4e489a072f8c
      shared_preferences: ^0.5.6

    这里有个比较坑的地方就是shared_preferences_settings目前只在pub.dev发布了一个旧版本,旧版本依赖的shared_preferences比较老,对于AndroidX支持有问题,所以只有直接用依赖git的方式加入依赖,这里指定ref防止一些不稳定问题。

    使用方式比较简单

    import 'package:fish_redux/fish_redux.dart';
    import 'package:flutter/material.dart';
    import 'package:kiwi/domain/constant/settings_key.dart';
    import 'package:kiwi/domain/enum/js_engine_type.dart';
    import 'package:shared_preferences_settings/shared_preferences_settings.dart';
    
    import 'state.dart';
    
    Widget buildView(
        SettingsState state, Dispatch dispatch, ViewService viewService) 
  • 使用Github Action自动merge pull request

    Github提供了pull request功能,有时候在小团队开发或者个人仓库的时候,基于git分支策略,可能依然需要在feature分支开发,但是需要经常合并到master。

    这种情况下更偏好于PR能够自动merge,而不是等CI等自动检查通过后再点击merge按钮。

    Github Action可以在创建pull request的时候触发,从而自动完成这个过程。相关配置如下:

    name: Automerge
    on:
      pull_request:
        types:
          - labeled
          - unlabeled
          - synchronize
          - opened
          - edited
          - ready_for_review
          - reopened
          - unlocked
      pull_request_review:
        types:
          - submitted
      status: {}
    jobs:
      automerge:
        runs-on: ubuntu-latest
        steps:
          - name: 
  • Flutter打包后闪退问题

    最近在搞Flutter,在模拟器调试一切正常,但是flutter build apk以后真机闪退,看了下日志,报错如下:

    E/flutter ( 5319): [ERROR:flutter/shell/platform/android/platform_view_android_jni.cc(39)] java.lang.NoClassDefFoundError: g.a.b.o3
    E/flutter ( 5319): 	at g.a.b.r.v(Unknown Source:0)
    E/flutter ( 5319): 	at com.huangyunkun.kiwi.a.a(Unknown Source:102)
    E/flutter ( 5319): 	at com.huangyunkun.kiwi.MainActivity$a.a(Unknown Source:153)
    E/flutter ( 5319): 	at c.a.c.a.j$a.a(Unknown Source:17)
    E/flutter ( 5319): 	at io.flutter.embedding.engine.e.b.a(Unknown Source:57)
    E/flutter 
  • 使用Github Action发布函数到阿里云serverless平台

    使用Github Action发布函数到阿里云serverless平台

    本文首发于:https://developer.aliyun.com/article/741408 修改后发于本博客

    阿里云提供了函数计算,即serverless支持。同时阿里云还提供了fun cli命令行工具方便项目验证、发布等。发布函数虽然只是一句命令行的事情,但是做到集成发布平台还是需要准备对应的环境,配置和工具的。

    travis-ci可以用shell脚本完成,但是要求nodejs环境。在从travis-ci切换到Github Action的时候还需要重新写shell脚本,但是Github Action支持Dockerfile模式,可以使用更简单的方式来实现,同时更有利于复用。

    Github Action支持自定义,主要有两个方法,第一种是javascript路线(nodejs环境),第二种是dockerfile路线,支持直接run docker镜像。第二种使用覆盖面更广和容易,特别是我对nodejs的调试一直比较困难。

    我们要构建的这个Github Action思路很简单,提供一个node环境,预安装fun的稳定版本,然后直接运行fun deploy就行了。所有需要的参数要么通过ENV传递,要么通过input传递。

    自定义Github Action

    自定义的几个主要步骤如下:

    • 创建action.yml文件
    • 创建Dockerfile和必要的其他文件,比如entrypoint.sh
    • 创建README (发布到marketplace必要)

    首先创建一个action.yml文件,这个文件的内容会展示到github action marketplace中。

    示例如下:

    name: "Aliyun Serverless Action"
    description: "GitHub Actions for Aliyun Serverless 🚀 Deploy function automatically."
    author: 
  • 阿里云智能视觉AI开放平台

    阿里云推出了智能视觉AI开放平台,对于云服务商提供的这一块应用蛮感兴趣的。

    因为如果遇到了类似图片识别等需求,虽然有很多开源库,也有很多教程快速入门,但是实际上手很清楚,这种东西自己半吊子的搞识别率低,出了问题也不会改进。

    阿里云推出的智能视觉AI开放平台目前在公测环节,价格未知,目前提供三个方面的功能

    • 车型识别
    • 动植物识别
    • 商品识别

    直接进入https://visionai.console.aliyun.com/overview申请开通对应服务即可,目前只要实名即可开通

    首先看下车型识别,随便从网上下载了几张

    byte[] fileContent = FileUtils.readFileToByteArray(new File("k3-1.jpg"));
            String encodedString = Base64.getEncoder().encodeToString(fileContent);
    
    
            DefaultProfile profile = DefaultProfile
                    .getProfile("cn-beijing", "lxjVzJS3", "AqUFTsWDjqkPKC");
            IAcsClient client = new DefaultAcsClient(profile);
            RecognizeVehicleRequest request = new RecognizeVehicleRequest();
            request.setImageContent(encodedString);
    
            try {
                RecognizeVehicleResponse 
  • 手动升级wordpress

    手动升级wordpress

    最近访问wordpess官网都是429,导致无法在线升级。

    手动升级的步骤也不是很复杂,首先下载最新的中文版本,地址https://cn.wordpress.org/latest-zh_CN.zip。这个地址要么用迅雷,或者用国外的IP下载。

    现在以后解压删除wp-content目录,然后把本机wordpress中的wp-admin和wp-includes删除,最后复制下载的目录内容到服务器的wordpress目录。

    最后访问后台,可能会提示要数据库升级,点击确认即可。…

  • 从Nginx迁移到Caddy

    之前博客使用的是Nginx,证书是从let’s encrypt申请的。Nginx配置是比较多,但是从各种参考参考,还是能够配置的。唯一的问题是let’s encrypt证书需要定时更新,更新以后需要Nginx重新加载一下,操作上始终有些繁琐。

    Caddy是一个综合解决方案,结合了防火墙、代理、证书等功能,最重要的是使用方便,配置简单。

    从Nginx迁移只需要几分钟,我之前使用的docker-compose管理,所以配置如下

    Caddy相关配置

    caddy:
      image: abiosoft/caddy:1.0.3
      restart: always
      container_name: caddy
      external_links:
      - blog
      environment:
        - CADDYPATH=/etc/caddycerts
      ports:
      - 80:80
      - 443:443
      volumes:
      - /alidata/data/caddy/Caddyfile:/etc/Caddyfile
      - /alidata/data/caddy/certs:/etc/caddycerts

    而最关键Caddy配置文件只有几行,主要就是代理一下,顺便强制跳转http到https

    huangyunkun.com {
        redir https://www.huangyunkun.com{uri}
    }
    
    www.huangyunkun.com {
      redir {
        if 
  • 开源软件文档管理与发布

    文档对于软件来说是非常重要的一部分,特别是对于开源软件来说,在接触源代码之前,一般会先接触文档。

    文档可以给新的使用者一个清晰的快速上手说明,也可以给已有使用者提供更多细节上的信息,帮助使用者更好的使用各种特性。

    我认为一个合格的文档应该满足以下几个要求:

    • 易于编写,由一种标准格式驱动,比如asciidoc或者markdown也可以
    • 支持文档版本化
    • 支持文档搜索
    • 对于多语言翻译友好
    • 支持多种格式用于离线浏览(比如pdf或者epub格式)

    常用的做法有以下几种:

    • 使用专用的网站/文档构建工具
    • 选定一种文本格式,并使用相应工具链处理
    • 文档直接附加在分发物中

    使用专用的网站/文档构建工具

    这是一种相对省心的方案,一般可以直接构建完整的网站,并附带对于文档的支持。

    比如react-native使用的docusaurus,这是一个全套解决方法。对于文档本身使用markdown书写,对于多语言翻译使用的是crowdin工具,搜索支持来源于algolia。对于不同语言还有版本的支持都是基于目录的。而多版本切换入口在页面顶部的logo旁。

    以react-native为例,版本切换在https://facebook.github.io/react-native/versions中,而不同版本路径如下:

    https://facebook.github.io/react-native/docs/getting-started

    https://facebook.github.io/react-native/docs/0.60/getting-started

    类似的工具还有docsite、vuepress、docsify等,但是对比与docusaurus多多少少有一些功能缺失。

    选定一种文本格式,并使用相应工具链处理

    上面一种其实是网站+文档解决方案,如果只是需要文档,那么方案可以更纯粹一些。

    可以参考spring-boot的方案,在spring-boot的项目中有一个spring-boot-docs文档,其中有adoc为后缀的文件。这些文件都是asciidoc格式的,通过asciidoc的maven插件生成对应的html、pdf、epub格式的文档,并上传到对应目录,而文档版本引导页面是自己独立编写。

    这种操作的优势在于文档输出格式多,且网站样式自由度高,理论上只需要加上不同版本的链接即可。

    文档直接附加在分发物中

    对于功能比较直接的,可以直接将文档附加在分发物中,比如放在readme中,或者作为软件的一部分,比如命令行工具的help指令。这种一般针对于功能直接的小型软件。

    Dubbo文档的管理

    Dubbo目前的文档基于docsite建设,语法使用markdown语法,支持多语言(目录模式)。唯一的缺少的主要是两个

    • 文档版本化
    • pdf、epub等格式导出

    版本化

    文档版本化可以考虑简单思路就是仿造docsite用docusaurus一样的方式支持版本化。

    目前Dubbo文档源文件目录如下:

    而支持版本化的目录结构如下:

    VersionTagURL
    1.0.01.0.0
  • 机器学习算法的部署

    算法工程师和业务开发工程师掌握的技术集和工具是不同的,特别是当两者运用的语言不同的时候更严重。算法辛苦作出的模型业务开发用不了会极大影响很多事情的落地。

    常见的合作模式如下算法负责模型训练和导出模型,业务开发导入模型并且做预测。一般算法使用python,R等,而业务开发使用java。可选的部署方法有以下几种:

    实时小规模

    可以简单点直接用Rserver或者python-httpserver,这种需要额外的服务,也存在调用问题,即引入了网络超时,重试等问题。性能上的话小数量可以保证95%在100ms返回,但是数据量大了就需要仔细控制。

    实时大规模

    这种情况考虑到基础设施的情况,特别是RPC框架等情况,同时要考虑水平扩展,最好使用PMML。这种额外依赖外部环境的方式可以提供较高的工程稳定性,但是PMML必然导致一些算法精度的损耗。

    离线计算

    对于T+1的计算和产出,部署上无疑最简单,直接使用脚本搭配一个监控和调度平台就可以获得较好的收益。

    对于PMML,java中的选择是https://github.com/jpmml,对于各种语言和模型都有较好的支持。当然由于较高的通用性,PMML会丧失特殊模型的特殊优化,例如上线XGBoost模型,也可以使用XGBoost4J,该包会链接一个本地环境编译的 .so 文件,C++实现的核心代码效率很高。不过PMML格式通用性,在效率要求不高的场景可以发挥很大作用。…