duangsuse::Echo
583 subscribers
4.12K photos
118 videos
579 files
6.13K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
web 支持动画是一个很有魅力的事情,毕竟 DOM/CSS 可以说是集 UI 之大成(明明它没有任何完整 data model 的概念呵呵😒

如果能做滚动平滑和背景色、缩放我会很高兴的。

明明就只是 tagName attributes children ,却能描述出那么多视图结构

我们这些人可能就是喜欢它的赤裸吧,正因简单,才有足够的空间展现自己对程序本身的理解。

或许 HTML 的简单就在于它只是纯纯的想描述「展现方式」,没有多余的思想和牵连吧。从世界上第一个网站到至今 Rust 新兴,DOM 的模式都被许多 GUI 借鉴,虽然它门中大多数不能做到web应用的如此易用易调试。

HTML 只有 paired,single,collapse 几种 tag,再深一点,内联 SVG namespace 描述矢量图
CSS 最主要的是 #id, .class, tagName, * 四种选择器和 :nth(1) 这种伪选择器;并列方式,空格是按层次、> 号是直接属从

这么简单的十几个基元,不需要多余的术语名词,描述出了成千上万个色彩缤纷的 www 网站页面资源,这是复用性的真谛啊!
https://caniuse.com/css-snappoints #web
#dontknow #CSS Scroll Snap

可以替换 splide.com 用js模拟的拖拽轮播图,可grid化,配合 anim-timeline:scroll(#id) 可实现滚轮ppt驱动动画 🌚👍

CSS 相比 YAML 把 03:01 解析为24小时制秒数😅就好得多https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell

另外,DOM的resize和visible(Intersect) 也是有Observer 的
DOM和CSS就是多元化 #UI 实际上的标准
dnaugsuz
#android IPC机制 contentResolver.query(uri, projection, selection/*where*/,selectionArgs, sortOrder) //C#LINQ的拙劣模仿者.. 不自动反序列化(Parcel-able)吗 url=parse("content://demo权限/user"), 会进行 resolver.acquireProvider("demo")? ,较耗时: ContentProvider增删改的底层是 Binder(RPC调用)…
#learn #android #code 以下kt代码里 (o: 缩进) 等于 o.apply{}

Looper 是按时间点排序的Channel<T>(阻塞add,回调pop)
触发“消息T”为Event(what,a1,a2,obj, when)时这叫send-handle,为函数时叫post-dispatch

Handler(main).post{} 实现 (休眠函数值).withContext{} 切换线程
又如 setTimeout 靠 h.postDelayed(ms){} 或监听 sendMessageDelayed(监听器ID, ms)

它占用某线程的调用栈。prepare队列,再靠 new Handler(默认本线程或mainLooper): handleMsg={按it.what 触发click等监听器}

Thread {
Looper:
prepare()
sub=Handler: //handleMessage
"sub收到: ${it.obj}"
loop()
}.start

main=Handler()
main.sendMessage(Message.obtain: obj="如何让sub收到?"; what=时间点)


ContentProvider 是对C#LINQ的拙劣模仿,让SQL执行filter{} 以避免在system等框架(联系人、日历、短信)和app间传输完整的表格

//日历=get(name,title,dt0,dt1) Calendar(dt0>=$0&$1<=dt1) minAt0 dt0

fun 日历(date:Range) = CalendarContract.Events.let:
ctx.getContentResolver().query(CONTENT_URI, //Uri()会 acquireProvider
["display_name" TITLE DTSTART DTEND],
"$DTSTART >= ? AND $DTEND <= ?", date.let: [first last],
"$DTSTART Asc"
).let: // 接着,从表格cursor里“反序列化”出数据
while(moveToNext()): 事件(getString(nameIndex), )
最好用 new CursorMapper<>(事件.class).convert(this) 的 @Column

CursorWindow.getInt,. 是表格的共享内存实现
resolver.增删改查基于 Binder RPC 和 Parcel-able序列化。

跨进程的 acquire 由 AMS 充当中间人,(已缓存或)拉起进程请求Provider, 等待后提供 Proxy实现的(interface Provider)
它用Binder转发调用给 class CP.Transport: IContentProvider ,后者会解包计算并打包回调。

等同 AIDL:
// src/main/aidl/ISvc.aidl
interface ISvc {
int getN();
List<Str> getUsers();// 对象参数要前置 in
}

// src/main/kotlin/ISvc.kt
class ISvc: Service(), ISvc.Stub {
var n=0
onBind(intent)=this
}

class MyActivity : RpcActivity() {
onCreate()=makeRpc<ISvc>()

inline fun<reified T> makeRpc() {
val conn=object : ServiceConnection { //v 创建接口
onServiceConnected(id, :IBinder?) {rpc = T.Stub.asInterface(binder)}
onServiceDisconnected(id) {rpc=null}
}
bindService(Intent.at(T::class.java), conn, BIND_AUTO_CREATE)
onDestroy={unbindService(conn)}
}
fun Intent.Companion.at(T:Class<*>) = Intent(T.name).apply {setPackage(T.`package`.name)}
}



自定义 View: 重点是布局尺寸、交互动画
type UI=({dataVars,.})=>HTMLvar
自定义属性=data class
子UI=函数
ViewHolder= 一个本不该由开发者负责的React式对象缓存
onTouchEvent 可实现简单拖拽(通过冒泡实现多级Tabs), ViewGroup里可以Intercept(全局手势,.)

写 demo。最初是能来演示和说明、比较解决方案的优缺点,但也要注重扩展性。

MVVM(Model-View-ViewModel)是一种软件架构模式,可以实现视图和数据的双向绑定
data class Model { fun 业务逻辑 }
View 是负责展示用户界面的层
ViewModel 是负责连接 Model 和 View 的缓存层,它可以在视图变化时更新数据,并且能够感知生命周期,避免内存泄漏和不必要的数据请求。

LiveData: 可观察的数据,暴露为 reactive Flow
Room: 提供强类型的 SQLite 语句,以及Flow查询流
WorkManager: 据前提(网络状态,电量状态等)来安排后台任务起停,重启后仍然能够执行。
Navigation: 通过统一的资源文件来定义应用内(单页)导航。
Paging: 与 RecyclerView 结合使用,实现分页加载网络数据的库
Hilt: Dagger 依赖注入库的kt版,支持 Android 生命周期和组件

请求 动词 http(s)://Host/ObjPath?Param#ID '\n'Head Body
动词 GET|POST/PUT|DELETE
Head ContentType|UA|SetCookie 等浏览器BOM调用
ObjPath 是静态页,json api,或数据的默认界面(可爬虫)

map, filter, reduce 等列表处理都是高阶函数,只有接受{}参数才可以加 inline fun ,内联 forEach{可含非局部return}
toInt, let{it+1}, apply{xx=1} 是带 context(如Str) 隐式.参数的函数。需要用 "1".let(Str::toInt) 来引用

Kt 最令人称道的是 ?.let{}, 可变性listOf DSL, when{is} 和 if 表达式, try与OOP的改良: runCatching{}, compaion object, sealed-data class , context(T) infix fun, Array<out Str>, 不钦定int和'+'等数据和运算

import kotlinx.coroutines 是对“在函数队列”执行回调的封装,或者说调度“函数级线程”
协程 +隔离调用栈=线程 +隔离内存=进程

任何 suspend (T)->R 都可以 suspendCoroutine { cc-> cc.resume(异步r) },以此实现await
cc,如delay(1_000/*, 回调cc*/) 能够被 dispatch(context: CoroutineContext, cont: Runnable)

coroutineScope/runBlocking {} 都会建立新的cancel/join域,二者的区别在调度器是否继承自旧的
launch(Dispatchers.Main) 同理
Forwarded from dnaugsuz
#bing #code
Hackr/2023 列出了 40 多个常见的 Android 面试问题和答案,涵盖了 Android 的构建过程、IDE工具、AIDL、Fragment(单页历史栈PJAX)、Activity
GH 仓库收集了更多,如协程、Flow API、Retrofit、Room
javapoint - 架构、四大组件、通知、WebView、布局、动画、广播接收器、数据存储等主题

Looper是按时间点排序的Channel<T>(任意线程add,回调pop)
触发“消息T”为Event(what,a1,a2,obj, when_ms)时,这叫send-handle,为函数时叫post-dispatch
Thread("httper"):
Looper: prepare(); h=注册Handler(可选); loop()
h.send__AtFront(msg)

IPC 常用方法:Bundle(Map), 文件Intent, Socket, Messenger(Loop); AIDL, ContentProvider(都基于 Binder)
AIDL 的定义-使用侧:
// src/main/{kotlin,aidl}/ISvc.{kt,aidl}
class ISvc: Service(), ISvc.Stub {
fun getN():Int
fun getUsers(): List<Str> //.aidl 只支持interface{},对象参数需前置in
var n=0
onBind(intent)=this
}
XML清单IDE会自动填写, .aidl 请AI生成吧

class MyActivity : RpcActivity() {
onCreate()=makeRpc<ISvc>()

makeRpc() {
val on=object : ServiceConnection { //v 把Binder连接,转化为接口
onServiceConnected {rpc = T.Stub.asInterface(binder)}
onServiceDisconnected(id) {rpc=null}
}
bindService(Intent(T.name).apply {setPackage(T.`package`.name)}, on, BIND_AUTO_CREATE)
onDestroy={unbindService(on)}
}

}//本来1行的事还写样板代码。 你玩不了开发,是 android.xx 开发者们玩你

ContentProvider 是对C#LINQ的拙劣模仿,让system(联系人、日历、短信)等框架的SQL执行filter{} 来避免传输完整的表格给app
Binder 提供了 CursorWindow.getInt 的共享内存的封送
// contacts.filter{str in it.name}.sortBy{it.startDate}
CalendarContract.Events.run:
getContentResolver().query(CONTENT_URI, 相关@Column, "id=?",[id], "$DT_START Asc").mapRows {
new CursorMapper<>(日历事件.class).convert(it)
}

自定义 View: 重点是布局尺寸、交互动画
type UI=({dataVars,.})=>HTMLvar
事件分发和(Object)View 的复用靠MVVM就好了

写 demo。最初是能来演示和说明、比较解决方案的优缺点,但也要注重扩展性和复用。 我说的不是“缓存复用”等样板化的代码

MVVM是一种软件架构模式,可以实现视图和数据的双向绑定
data class Model { fun 业务逻辑 }
View 是负责展示用户界面的层
ViewModel 是负责连接 Model 和 View 的缓存和编辑层
Jetpack 还有 LiveData(reactive Flow), Room(强类型SQL), Navigation(& data Paging)

请求 动词 http(s)://Host/ObjPath?Param#ID '\n'Head Body
动词 GET|POST/PUT|DELETE

Kotlin 最令人称道的是 ?.let{}, 可变性listOf DSL, when{is} , try与OOP的改良

map, filter 等列表处理都是高阶函数, 内联的 forEach{可含非局部return}
toInt, let{it+1}, apply{xx=1} 是带隐式this参数的扩充函数

import kotlinx.coroutines 是对“在函数队列”执行回调的封装,或者说调度“函数级线程”
协程 +隔离调用栈=线程 +隔离内存=进程
delay() 等协程以回调,而非调用栈保存返回地址;因此调用者也以 async { } 内 suspendCoroutine{it.resume} 自动传入delay.then(成功).catch(报错)

Scope{} 能创建 cancel/join(wait)域,而 launch(withContext){} 可切换调度器

//a.partition{it==0}
a=[1,0,0,2,3], b=[]; a.filter(x=>x==0?(b.push(x),0) : 1).concat(b)
代码烂 但单次迭代快(就像单行filterMap只好用map.flat)

用读写指针(朝右读,遇到非0: 交换)更快 ,或者朝左读(遇到0: 交换) ,如果0的占比少
这是qsort() 的步骤。