xiaoyaocz 发布的文章

1. 下载 protoc

protocolbuffers/protobuf 项目的 Releases 中下载 protoc 文件,然后将其加入 PATH 环境变量中。

2. 安装 protoc-gen-dart 插件

可以通过 Pub 安装插件,也可以通过下载插件源码并手动编译,并将其添加到 PATH 环境变量中,或在运行 protoc 时指定插件路径。

通过 pub 安装:

dart pub global activate protoc_plugin

通过源码编译安装:

  1. 克隆源码
  2. 在 protoc_plugin 目录中运行 dart pub get 命令
  3. 将 protoc_plugin/bin 加入 PATH 环境变量中,或者在运行 protoc 时指定其路径。

生成 Dart 代码

在项目目录中运行以下命令来生成与 proto 文件对应的 Dart 代码:

protoc --proto_path=assets/proto --dart_out=lib/models/proto --plugin=$protoc-gen-dart xxx.proto
  • --proto_path 指定 proto 文件所在的目录。
  • --dart_out 指定 Dart 代码的输出路径。
  • --plugin 指定使用的插件。可以直接使用 $protoc-gen-dart,或指定其路径。
  • 最后指定需要生成 Dart 代码的 proto 文件。

今天将系统升级至Ventura后发现Flutter iOS项目上跑不起来,报一下错误

Ignoring ffi-1.15.5 because its extensions are not built. Try: gem pristine ffi --version 1.15.5

查资料说要卸载重新安装Cocoapods

sudo gem install cocoapods

然后又得到了以下错误:

You don't have write permissions for the /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0 directory.

又是谷歌一顿折腾后发现似乎是系统自带Ruby版本过旧的问题,使用Homebrew安装新版本的Ruby即可解决。

1、安装Ruby

brew install ruby

2、查看ruby版本

ruby -v

3、安装完成后发现依旧是2.6版本,需要设置环境变量

vim ~/.zshrc

ARM机型粘贴以下代码:

if [ -d "/opt/homebrew/opt/ruby/bin" ]; then
  export PATH=/opt/homebrew/opt/ruby/bin:$PATH
  export PATH=`gem environment gemdir`/bin:$PATH
fi

x86机型粘贴以下代码:


if [ -d "/usr/local/opt/ruby/bin" ]; then
  export PATH=/usr/local/opt/ruby/bin:$PATH
  export PATH=`gem environment gemdir`/bin:$PATH
fi

4、再次查看版本是否为安装的新版本

source ~/.zshrc
ruby -v
  1. 重新安装Cocoapods
sudo gem install cocoapods

然后进入运行flutter doctor,若没有错误项目应该就能跑起来了。

  1. 如果pod install出现权限问题
warning: Insecure world writable dir /opt/homebrew/bin in PATH, mode 040777

设置目录权限即可

sudo chmod -R go-w /opt/homebrew/bin
sudo chmod -R go-w /opt/homebrew

参考:
https://mac.install.guide/ruby/13.html
https://blog.csdn.net/liuwenchang1234/article/details/127635234

一眨眼的功夫就到了2023,随便写写记录下我的2022。

生活

想想上半年的生活是美好的,因为我在追一个女孩。
在这段时间里,体验了许多以前从没体验过的事情,感受到了现充的快乐。可惜,最后还是没能追到手,也许是我太笨、太木纳了吧。

下半年,过着平平淡淡、日复一日的枯燥生活。唯一让我感到快乐的点就是在家里人的支持下,提了辆新车:星越L。

下半年广州的疫情开始严重,好像都习惯了做核酸。再此期间,被赋黄码一次,被居家隔离了一周。

年末又突然毫无征兆的放开了,然后就中招了,躺了一个星期。

工作

5月份,我从上家公司辞职了。因为我受够了无意义的加班、日报、早会、周会;受够了“狼性文化”;受够了莫名其妙的互联网黑话。

6月份,我尝试开始搞电商卖衣服,结果已失败告终。算是休息了一个月吧,又开始了找工作之旅。

7月份入职现在的公司,平平淡淡没啥好说的,至少不需要加班,没有了日报这些让我恶心的玩意。

技术

技术上今年基本抛弃了 .NET,转向了Flutter及原生APP开发。

今年也把维护了多年的哔哩哔哩UWP给archive了,因为B站API的更新,每天都有一堆的反馈塞到我邮箱,让我感到烦躁。
我也没有精力继续维护下去了,每天下班我就只想躺着刷抖音、刷B站,根本就不想去写代码,干脆直接就停止维护了。

规划了几个项目,最后都没有完成,甚至都没有开始。例如:flutter_dmzj的重构、一个本地的弹幕播放器等等。

在年末倒是成功摸出来一个博客园的Flutter客户端,虽然也不完善就是了。

2023年尽量把2022年的坑给填了吧。

总结

2022,上半年的我算是开心、快乐的;下半年是不开心的,是非常枯燥、无趣的。

2023,希望能有多一点的快乐、多一点的开心、多一点写代码的动力。

最近在摸鱼时看到了一些博客园API文章,就想着摸鱼时写个APP练练手。

现阶段实现了以下功能模块:

  • 博客浏览、评论
  • 新闻浏览
  • 闪存浏览、发布、评论
  • 博问浏览
  • 用户登录

博问暂时只支持浏览,不支持回答提问等操作。

支持iOS、Android平台。

截图

浅色模式:

Light.jpg

深色模式:

Dark.jpg

API

开发前需要先到https://api.cnblogs.com/申请API KEY,申请通过才能使用博客园的API。

输入一下个人信息跟应用信息,提交后等待博客园的审核。通过审核后会收到一封包含ClientId和ClientSecret的邮件。

申请APIKEY.png

博客园API文档上的API不全,有些API需要到Github中查询。

开发

API申请完成就可以愉快的进行开发了。
Flutter版本这次选择了最新的3.3,基于GetX框架+Dio来开发,不得不说GetX一把梭的感觉是真的爽。

目录结构跟GetX框架差不多,按我自己的习惯进行了一些改动:

  • app 一些通用的类及样式
  • services 提供数据存储等服务
  • requests 请求的封装
  • generated 生成的国际化文件,使用 get generate locales生成
  • modules 模块,每个会有两个文件,view及controller
  • widgets 自定义的小组件
  • routes 路由定义
  • models 实体类

个人练手项目就加上了一些以前没用过包跟特性体验一下(如lottie、getx国际化)。

这个项目比较简单,技术上没什么好说的,主要说下博文的展示:

博文展示

博文由于是HTML富文本且有一些复杂样式,把文章内容转为Flutter Widget显示的体验挺差,所以还是使用WebView来展示。

在这里我选择了flutter_inappwebview包,这个包会比官方的webview_flutter功能更加丰富,更新也更频繁。

HTML加载流程如下:

  1. 在assets中添加HTML,预留内容、js、css槽位
  2. 在assets中添加两个css样式,分别对应浅色模式及深色模式;css内容可以从任意文章的Web页面抓取
  3. 在assets中添加JS,编写WebView与APP的交互
  4. 在assets中添加highlight.js,实现代码的高亮
  5. 将js、css填充至HTML,css需要根据APP主题选择
  6. 通过API读取博文内容,并填充到HTML中
  7. 通过webViewController.loadData(data: html)在APP中显示博文

具体实现可以看源代码。实现效果:

博文.jpg

由于项目依赖WebView(文章、登录),所以只支持iOS、Android平台。要支持其他平台也不难,只需要把文章内容转为Flutter Widget显示再更改下登录逻辑即可。

自动打包

使用Github Actions可以很简单的自动完成打包发布的步骤。

关于Github Actions的介绍,可以看下官方文档

在项目创建根目录创建一个.github/workflows,然后创建一个xxxx.yml,写入以下代码。

详细代码见:https://github.com/xiaoyaocz/flutter_cnblogs/blob/master/.github/workflows/publish_release.yml

运行脚本前,需要先到Github项目设置-Secrets-Actions中添加以下字段

CLIENT_ID 博客园API ClientId
CLIENT_SECRET 博客园API ClientSecret
KEYSTORE_BASE64 APK签名文件,转为BASE64
KEY_ALIAS APK签名keyAlias
KEY_PASSWORD APK签名keyPassword
STORE_PASSWORD APK签名storePassword
TOKEN Github Token

Github Token点这里添加,注意需要权限的设置。

secrets.png

设置完成后,当想要打包一个新版本时,只需要提交代码并打上Tag推送至Github,即可自动打包。

总结

这个项目没啥难度且博客园API文档还是比较全面,基本对着API做个UI就行了。

天冷变懒了,有些功能还没有写完,过段时间再慢慢完善了。

项目开源地址:https://github.com/xiaoyaocz/flutter_cnblogs,有兴趣可以到Release中下载安装包体验一下。

1. styled_widget

使用扩展方法提升开发效率,增强代码可读性

示例代码:

Icon(OMIcons.home, color: Colors.white)
  .padding(all: 10)
  .decorated(color: Color(0xff7AC1E7), shape: BoxShape.circle)
  .padding(all: 15)
  .decorated(color: Color(0xffE8F2F7), shape: BoxShape.circle)
  .padding(all: 20)
  .card(
    elevation: 10,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20),
    ),
  )
  .alignment(Alignment.center)
  .backgroundColor(Color(0xffEBECF1));

2. intl

提供国际化和本地化工具。可以用来格式化数字和日期

示例代码:

//格式化日期
var dateFormat = DateFormat("yyyy/MM/dd HH:mm:ss");
print(dateFormat.format(DateTime.now()));

3. logger

简单易用、美观的日志输出。

示例代码:

var logger = Logger();
logger.d("Logger is working!");

4. html_unescape

HTML特殊字符解码

实例代码:

var unescape = HtmlUnescape();
var text = unescape.convert("<strong>This "escaped" string");
print(text);

5. json_path

通过路径解析JSON

示例代码:

import 'dart:convert';

import 'package:json_path/json_path.dart';

void main() {
  final json = jsonDecode('''
{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}  
  ''');

  final prices = JsonPath(r'$..price');

  print('All prices in the store:');

  /// The following code will print:
  ///
  /// $['store']['book'][0]['price']:    8.95
  /// $['store']['book'][6]['price']:    12.99
  /// $['store']['book'][7]['price']:    8.99
  /// $['store']['book'][8]['price']:    22.99
  /// $['store']['bicycle']['price']:    19.95
  prices
      .read(json)
      .map((match) => '${match.path}:\t${match.value}')
      .forEach(print);
}

6. translator

封装谷歌翻译API,国内可用

示例代码:

final translator = GoogleTranslator();
final input = "Здравствуйте. Ты в порядке?";
translator.translate(input, from: 'ru', to: 'en').then(print);
// prints Hello. Are you okay?
var translation = await translator.translate("Dart is very cool!", to: 'pl');
print(translation);
// prints Dart jest bardzo fajny!
print(await "example".translate(to: 'pt'));
// prints exemplo

7. puppeteer

用于通过 DevTools 协议自动化 Chrome 浏览器(主要用于爬虫)