Flutter 嵌入安卓原生 View,以及与原生交互

在跨端开发里,有些场景是 Flutter 处理起来比较麻烦或者利用原生组件实现更高效。

这时候就得祭出 PlatformViewMethodChannel。不仅把一个 Android 原生 TextView 塞进了 Flutter 布局,还能实现Flutter和原生Android View的双向交互。

为了直观,我打算基于Flutter默认的计数器模板演示, 界面布局和悬浮按钮还是 Flutter 的,但中间显示的那个数字,换成安卓原生的TextView

阅读更多
Android 进阶:如何在安卓中实现像 LVGL 一样的"实体"Border?

Android 进阶:如何在安卓中实现像 LVGL 一样的"实体"Border?

做嵌入式的时候用过 LVGL,它的样式系统给我留下了深刻印象。LVGL 的 Border 是”实体”的——会占据布局空间,把内容往里挤。

安卓这边就没这么痛快了。ShapeDrawableMaterialCardView 的边框更像是”装饰品”,想让边框、圆角、内边距各自独立可控?原生组件做起来挺别扭。

所以我干脆手搓了一个 BorderFrameLayout,把 LVGL 那套逻辑搬过来。
BorderFrameLayout层级示意图
图中不同的颜色代表真实占用的空间。
绿色代表Border, 红色代表内部Padding, 蓝色代表Child可使用空间.

阅读更多

声明式 UI 架构下的生命周期演进:从内建属性到显式订阅

消失的“实体”: 从View到Composable/Widget

在原生Android开发的世界, 创建模版项目后就会得到一个MainActivity和activity_main.xml.
我们习惯了在MainActivity里去绑定ButtonText再设置各种属性. 他们都是内存中看得见,摸得着的View.
但是到了Flutter中, 得到的了却是main()函数和一堆StatelessWidgetStatefulWidget.
不仅仅是Flutter, 连Jetpack Compose也在向这种’声明式UI’靠拢.
Compose中同样找不到onResume(入口Activity除外),取而代之的而是层层嵌套的Composable函数

这种转变本质上是:我们不再持有 UI 的“句柄”,我们只持有“数据”。

正因为我们持有的只是数据,而数据本身是没有‘前后台’概念的(一个 String 字符串哪里知道自己是否在前台?)。所以,在声明式 UI 中寻找 onResume 本身就是一个伪命题。
只有当数据需要根据系统状态(如用户回来了)进行刷新时,我们才去主动询问系统。

生命周期演进图

阅读更多

移植FFMPEG到安卓

移植FFmpeg到Android上

Ffmpegonandroidp1

因为Mix Music解码的需求,所以得选择合适的解码工具.尝试了4种解码方式,最后还是FFmpeg的效果最好

  • MediaCodec配合MediaExtractor进行解码操作
  • MediaCodec不用MediaExtractor进行解码操作
    • 在给Bytebuffer填充数据后,MediaCodec处理数据的时候总出错,大概是因为没有跳过非帧数据的部分
  • 使用LAME进行解码操作
    • 不幸的是LAME中的hip_decode()也是只能处理帧数据,需要手动跳过非帧数据.当手动跳过非帧数据后,最终发现速度并没有提升多少(尽管已经设置了不同大小的buffer)
  • 使用FFmpeg进行解码操作
    • 编译的时候真的是各种错误,头文件明明就在那里呆的好好的,编译器还是报找不到函数的错误.好在最终效果令人非常满意,3秒钟解码一个音频文件.
阅读更多