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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
#algorithm #bing 二分查找 spiral sorted ndarray
最好把它转换为1d,再转换回来以获取 '1'的位置
#py #code
def unrot(a, out):
while a.size:
out.extend(a[0]); a=np.rot90(a[1:])

#难以用concat矩阵滚出螺旋
def rot(a, m):
ia=np.reshape(range(len(a)), (m,-1))
unrot(ia, ord:=[])
return np.vectorize(lambda i:a[ord.index(i)] )(ia)

#make range(0,9) a spiral(cols=3)
[[0 1 2]
[7 8 3]
[6 5 4]]
a=rot([*range(0,9)], 3)
unrot(a, na:=[])

na[na.index(4)]=-1
print(a)
np.where(rot(na,3)==-1) #'4'=>[2,2]


def binary_search_matrix(matrix, target): 同理,可以是2d转1d
def binary_search_first_last(*a):
import bisect
left,right = (f(*a)for f in [bisect.bisect_left, bisect.bisect_right])
# 如果右边界超出了数组范围,说明目标出现1次
return (left, left if right == len(nums) else right - 1)


感觉很无语,居然为了无意义的“高性能”算法浪费2h ,还不如直接就用自己本来会的 a[ord.index(i)] 序号对应..

我发现2d.bisect 是以 (row=a[i])[0] 为线索再去 row.bisect ,这就更无聊了。Trie 前缀树至少还有 AC 的优化版(窄化为 KMP ),kD/quad 树至少还有切割公式 ,RB树有 std::(orderd_)map,但bisect 对Nd都只是Trie那样剪枝..
我觉得放在现实语境下就理所当然的策略,根本不该叫算法…


我很好奇除了用等价关系导入list里的算法,螺旋矩阵能怎么bisect,毕竟这东西本质就是list的重排序,它没啥性质可言

搜索发现这个螺旋数组 是 [4,5,6,7,0,1,2] 这种螺旋(shift..) 好奇怪的条件啊:
左右两段中,一定是有一段有序的,另一段可能有序可能无序(有序,则一定有段首值<段尾值)
需要 if nums[mid] >= nums[start] 判断左面是否有序
看的我都糊涂了,它是说 '//'状数组二分会产生 '/ _/'状无序右侧 ;算法是相当于只优化了“左侧”,对另一侧继续拆.. 这过度解读题意了。还不如直接拿拐点切分list,各自bisect()

螺旋数组 LC#54 不知为何大家用的都是Excel式四向法.. 虽然我写2048.js 时也是用了4向线性扫描了
括号匹配 LC#20 可以用调用栈,我又试了2h. bing反而误导我 😭
测试
pairs = {'(':')', '[':']', '{':'}'}
def eat(s,c0):
for c in s:
# 如果是左括号,就把它压入栈中
if c in pairs: eat(s,pairs[c])
elif c==c0:return # 如果是右括号,左括号便与之匹配
else: assert'','多余项而栈空'
assert c0=='eof','栈尚不为空'


#394 字串“编码” ,晕了,这标题为何如此民科啊!我还以为是词表替换
decodeString('hello,2[wo]rld')
'hello,woworld'

decodeString=(s)=>s.replace(/(\d+)\[(\w+)\]/,
(m,n,s)=>s.repeat(+n) )
本意是让你用 char 去累积 \d+[ ,累积[]里的字符,然后在 ']' 的时候输出repeat的文本,但这就是文本解析而已..

如你们所见,解法越简洁,我敲键盘的时间越少、敲脑门的时间越多……
#learn #FP 从“面向运气编程”到“设计程序”,「编程是什么」有许多天差地别的答案。

编程语言的范式。以社区的主流写法而定(FP之前后:统称过程式 vs. 定义式):

PP结构化- C,Go,Perl,Lua

C是会计算(跳转)栈、整数/struct* 类型到成员地址的汇编,它的对象检查很弱,也没有规范的List,KV数据类型(SDL,linux,qemu 这些都有自己的"utils")

GC需要定期"stop THE WORLD"并自 static/调用栈变量遍历对象图,连[]{} 都没有的C当然找不出“0引用”指针,更多人使用shared_ptr<T> 引用计数实现Pair<AB>等数据

OOP面向对象- C++, Java~, .NET~

FP函数式- JS,Py, Rust

若对象用 函数值参数/监听器字典,取代override 那就叫“闭包closure” (其可见/可定性同interface,都为 public open)

类比,AbstractAnimal=(T={eat,say})=>“构造器”(name)=>{name, __proto__:T“类型T也有proto”}

“弱结构强脚本”轻松于万物class{}。fn=a=>(b=>a+b) 能从词法上文捕获a,不用 new fn$1(fn.arg[1]) 手动把a放入匿名对象

PF纯函数- Haskell Scala Lisp~

冷门:
FRP响应式- Rx,React

- x86 wasm
在 .data 段加个字符常量, 再在 .text push bp;sub sp,N 栈分配调用 libc:printf
甚至需要关心 nasm; ld 仅仅来让print() 能跳转到dll的“地址”,不会SEGV

LP逻辑式- SQL Prolog #relational #types

逻辑问题也有函数域和'=',只是'a=b' 的含义是“解构赋值” 出解集。b能含变量: [1 x]=[y 2]
a=b, b=1 应求出a=1 ,因此执行流程是 cut(=) 深解构, ',|'and or 靠约束过滤解集, 最后 cat 深建构

若等号右边必须已知,在 ([1]+x)=[1 2] 的求解中
(+) A B
|A=[], B
|A=[x a], [x (a+B)]

appendo A B O
|A=[], O=B
|A=[x a], O=[x appendo(a B)]
里,O=[x 递归] 就无法匹配出 A=[$x ] 这些输入参数了

当然,变量是值。“解”可以是 [List T] 这样的含“类型”变量,<T> 一定是“类型函数”加过的变量,所以:[List T]就是函数签名
可以取各处T的成员(接口)交来infer调用、单独查找fun重载,但本质上都是这样:

fun Box<T>.let(f:(T)->R)=listOf(f(item))
let A B
|A=[Box T],B=[Fn T R], listOf(B.invoke(A.item))
|重载,.
listOf T..|[List T]

阮一峰 体验 👉 swish.swi-prolog.org/example/grammar.pl //在左边粘贴关系, 右边查询,如 murderer(X)
tomstu.art/hello-declarative-world
duangsuse::Echo
#algorithm #bing 二分查找 spiral sorted ndarray 最好把它转换为1d,再转换回来以获取 '1'的位置 #py #code def unrot(a, out): while a.size: out.extend(a[0]); a=np.rot90(a[1:]) #难以用concat矩阵滚出螺旋 def rot(a, m): ia=np.reshape(range(len(a)), (m,-1)) unrot(ia, ord:=[]) return…
#FP #sql #code 真正的 relational 笔记本👏
那种能 x+2=5 的。SQL做不到呢(预先 insert values (3,2,5)? )

花了一大把时间用来学习在逻辑式里写DFS搜索..

今天终于把序列化(/解析)器项目前堆积的事项完成了, 虽然这质量,怎么看都是很失败..

也就主要是for loop 的功能,但确实简洁了点。 学了关系式 constraint (注意不是sympy线代)后,觉得能更好的理解类型系统了
#life “你们在美国敢拿军人开玩笑么 ”。油管上随便一翻,一大堆。 这些粉红总喜欢以己度人,总以为世界上其他国家的人,也是每个人内心都装有一个中宣部。

🧐一些种族主义新纳粹,竟然会成为「政治正确」和懂王,也是让人感叹集权政体的轮回性。 东亚和犹太都是很爱考试的“资本主义”民族,也都有战乱史。同行相见,分外眼红?
https://m.youtube.com/watch?v=QRQvXScDzXc&t=9m
Forwarded from 科技圈🎗在花频道📮 (❤️)
AI 公司承诺将为 AI 生成内容打上水印

拜登政府周五表示,美国主要 AI 公司如 OpenAI、Alphabet、Meta Platform、亚马逊、Anthropic、Inflection 和微软已经向白宫承诺将自愿为 AI 生成内容实现水印等措施,以帮助提高 AI 技术的安全性。主要 AI 公司还承诺在发布新 AI 系统前进行彻底地测试,并分享诸如如何降低风险等信息。随着 OpenAI 的聊天机器人 ChatGPT 风靡世界,世界各国的立法者开始考虑如何缓解这项新兴技术对国家安全和经济的危险。(slashdot)

投稿:@ZaiHuaBot
频道:@TestFlightCN
Forwarded from 科技圈🎗在花频道📮 (在花⭐️投稿📮Bot)
安兔兔官方称“安兔兔车机版”将于下周一上线(7月24日)

来源微博(@安兔兔 )

投稿:@ZaiHuaBot
频道:@TestFlightCN
Forwarded from Solidot
Stability AI 发布 CC-BY-NC 4.0 授权的大模型 Free Willy 1 和 2

2023-07-22 18:18 by 火星战将

AI 创业公司 Stability AI 发布了在 CC-BY-NC 4.0 下授权的大模型 Free Willy 1 和 2,也就是商业使用受限制。FreeWilly1 是基于 LLaMA 65B 模型,FreeWilly2 是基于 LLaMA 2 70B 模型,Stability AI 称两个模型在不同基准测试中展现了出色的推理能力,其中 FreeWilly2 在部分任务中的表现超过了 GPT-3.5。公布这两个模型旨在促进开放研究,因此都是非商业使用授权。Stability AI 此前发布了一种可商业使用的开源大模型 StableLM。

https://stability.ai/blog/freewilly-large-instruction-fine-tuned-models

#人工智能
Forwarded from 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调用) 的参数,
CP.query(Uri(数据库等来源)) 是Cursor表格迭代器,它指向共享内存里被塞入的媒体数据
CursorWindow.getInt 只是表格的共享内存实现。Binder使用ptrFD+size 来传递mmap(shared mem, <2MB)
  CP.call("add",Bundle)
可调用对方

好的,我尝试用列表的形式来条理化这个过程:
app获取 CP
AMS 充当中间人,(拉起进程,若已启动但未缓存则仍 scheduleInstallProvider):
请求 Provider 回调,存到 ContentProviderRecord,让app线程停止sleep并创建 interface Provider (的Proxy)
它用Binder转发call()给CP.Transport(: IContentProvider) ,后者会解包计算并打包回调。同进程的CP不涉及AMS

总结:幸好我学的是DOM,py,cFFI 请求模型而不是java,不然世界观都被 android.xx 带崩塌了。没人想把Android当服务端来写,甚至服务端也越来越弱化,js化
心智模型不健康是设计不出易用的功能的,不愧是咕狗

#code 使用 makeRpc<接口InAIDL> 调用其他apk的函数
Forwarded from 科技圈🎗在花频道📮 (在花⭐️投稿📮Bot)
华为Harmony OS 4.0版本将于8月正式发布

来源:新浪微博

投稿人:Arkansas State Police

投稿:@ZaiHuaBot
频道:@TestFlightCN
#algorithm #FP 版的 list 累加法杨辉三角
ps. 也可以用DP和代数式推算
P2:垃圾 itertools

#py #code
from itertools import accumulate,islice,chain

fib=iself(2,lambda x0,x1: chain([1,1], (x+y for x,y in zip(x0,x1)) ))
def 杨辉(): #pascal_triangle
row = [1]
while True:
yield row; row = [1,*(x+y for x,y in zip(row, row[1:])),1] #上行+上左


def iself(n,fn):
a=[]
def _(i):
while True:yield(a[-i])
for x in fn(*[_(i+1) for i in range(n)]): a.append(x);yield x

ctrlM=lambda a: (lambda n:'\n'.join(f'{s}'.center(n)for s in a)) (max(len(str(s))for s in a))
N=20
print(ctrlM([*islice(杨辉(),N)]),'\n\nfib', [*islice(fib,N)])
#sql DFS搜索 像素图填色 in Prolog

btw. fill(_,X) 是 “从任意一点探索区域X , 一共能收集到多少X”
v(P,0) : 查询颜色是0的P=[X,Y]
conn([2,1], P1) : (2,1)=0 四邻里 0值格的座标们

不知为何很慢
看起来好像简短了,实际只是省掉 if 和解构的代码量 😒


有趣的是,conn(四邻) 是基于 |X-x|+|Y-y|=1 的参数方程(GL常用),而非 x+1,y+1 直接迭代,所以 dfs :- C=conn(A),dfs(C) 就必须写成 conn(A,C) 的约束,尽管C只是A的“过滤结果”, 对C的穷举确实不像“返回值”能做到的

https://www.swi-prolog.org/pldoc/doc/_SWI_/library/lists.pl
关系式和SQL一样支持查询结果 distinct(unique)
之前用 findall(X, Func,R) 莫名出问题,也用不了lambda ,累死了
Forwarded from 科技圈🎗在花频道📮 (在花⭐️投稿📮Bot)
微软不再对Chrome 和 Safari 以及其他浏览器中屏蔽 Bing Chat 的使用。

然而,在其他浏览器上使用 Bing Chat 存在一些限制。比如,相比在 Edge 上使用 Bing Chat 的 4000 字上限来说,你只能输入 2000 字。对话在进行5轮后也会重置,而在 Edge 中是30轮。并且你会看到一些烦人的弹出提示,建议你下载 Edge。

https://www.theverge.com/2023/7/24/23805493/bing-ai-chat-google-chrome-safari

投稿:@ZaiHuaBot
频道:@TestFlightCN
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() 的步骤。
duangsuse::Echo
#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){} 或监听 sen…
#android #dev 面试题。上条则是简化版的答案 🧐

仅供参考,可能我解释的太抽象了,涉及一些淘汰的远古技术, 不符合标准答案。

- Handler 基础,Looper 怎么和 Thread 绑定,怎样提高 MessageQueue 优先级
- 进程间通讯的方法,对 AIDL 的了解,对 ContentProvider 的了解
- (根据项目) 自定义 View 的方法和注意事项、事件分发、View 复用
- 写过 demo 吗,什么时候会写 demo
- 对 MVVM 的了解,对 Jetpack 的认识,除了 data binding 还知道哪些 Jetpack 的东西
- 对 HTTP 的了解,HTTP 协议是什么
- 对 Kotlin 的了解,如何使用协程,什么是高阶函数、内联函数、扩展函数
- 写一个将数组里所有 0 移动到末尾的算法(简单粗暴选排)