V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  murmurkerman  ›  全部回复第 3 页 / 共 3 页
回复总数  54
1  2  3  
挺好的,就是一些 ui 组件可能不符合你们自己的要去,要复制官方代码修改。包括 switch ,menu ,tab 之类的。导航组件目前支持了 safeargs ,对话框存在一些显示问题。其它都挺好的包括与 view 系统的集成,嵌套滚动之类的。
207 天前
回复了 cx2ex 创建的主题 Android 如何说服老板使用原生而不是混合开发 APP
取决于有多少资源,和收益。首先要明确原生和混合方案的优缺点,显然原生之后可以迭代混合方案进来。至于 cordova ,你得评估下社区支持程度,比较流行的是 flutter 和 react native 。然后原生也需要选择 view 还是 compose 新架构意味着新的挑战。
评估好了之后再去招老板商讨人力资源能够协调多少,如果原生腾不出来你就只能选择混合了。其次鉴于是一个贷款类重营销的应用,我觉得迟早有部分 ui 需要动态下发,和如家国内的电商应用一样会需要嵌入混合开发
最重要的是数据要和 UI 解耦,无论你用 Android Service 还是普通类。和后端的 MVC 类似,Dao 、Connection Pool 是全局对象,Controller 只是用于处理用户交互,更新用户 UI 状态。你需要将自己的 ws 业务逻辑抽象到服务层中,viewmodel 负责从服务层获取数据,处理交互事件,service 层管理连接,发送接收处理消息。

至于是否使用 Android Service ,取决于你的应用是否需要在应用界面后继续运行,你还希望服务继续运行直到系统终止服务。一般情况下,例如媒体播放、录音、推送等及时性要起高的需要放到服务中。

一般只需要用普通的类来管理,

至于 ws 数据传输,ws 一般只用于同步状态:
1. 例如多人协作文档,需要同步输入位置,锁定编辑区域。
2. 大型二进制,例如文件、图片、音频,建议分开。
3. 实时翻译等,短时低延迟要求等,使用 ws 传输数据。

下面的示例中将没有处理消息放到了一个 ShardFlow 中,UI 收集这些数据,YourService 负责管理连接创建、关闭,ServiceConnection 处理消息通讯。

class YourApplication : Application() {

lateinit var yourService: YourService

override fun onCreate() {
super.onCreate()
yourService = YourService()
}
}

// 这里用 Application 类管理全局依赖
val Context.application: YourApplication
get() = applicationContext as YourApplication

val Context.yourService: YourService
get() = application.yourService

// 服务层,用于管理链接和处理数据
class YourService {

/**
* 一个简单的没有任何附加逻辑的 WebSocket 连接 Handler ,只是把消息缓存到一个 Flow 中
* 你可以加上你自己的逻辑,比如消息解析,消息处理等,链接重试之类的
*/
class ServiceConnection {

internal var websocket: WebSocket? = null
private val messageBuffer = MutableSharedFlow<String>(
replay = 0,
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
val receivedMessages = messageBuffer.asSharedFlow()

fun onConnected(websocket: WebSocket) {
// ...
}

fun onMessageReceived(message: String) {
// ...
}

fun disconnect(code: Int, reason: String, cause: Throwable? = null) {
// ...
}

fun sendMessage(message: String) {
// ...
}

}

private val client = OkHttpClient()

// 一个简单的 WebSocket 连接缓存,只保留一个连接
private var activeConnection: ServiceConnection? = null

@Synchronized
fun connect(): Result<ServiceConnection> {
if (activeConnection != null) {
Result.success(activeConnection!!)
}
return connectChecked().onSuccess {
activeConnection = it
}
}

private fun connectChecked(): Result<ServiceConnection> {
val request = Request.Builder()
.url("wss://echo.websocket.org")
.build()
val connection = ServiceConnection()
return kotlin.runCatching {
client.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
connection.onConnected(webSocket)
}

override fun onMessage(webSocket: WebSocket, text: String) {
connection.onMessageReceived(text)
}

override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
connection.disconnect(code, reason)
}

override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
connection.disconnect(0, t.message ?: "Unknown error", t)
}
})
.apply {
connection.websocket = this
}
connection
}
}

}

// 处理 UI 状态、用户事件,和与服务层拉取数据
class YourViewModel(
application: Application,
) : AndroidViewModel(application) {

private val yourService: YourService
get() = getApplication<Application>().yourService

private var connection: YourService.ServiceConnection? = null

fun connect() {
viewModelScope.launch {
connection = yourService.connect()
.onSuccess {
it.receivedMessages.collect(::onReceiveMessage)
}.onFailure {
// handle error

}.getOrNull()
}
}

private fun onReceiveMessage(
message: String
) {
// update ui state
}

}

class YourUi: Fragment() {

private val viewModel: YourViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}

override fun onStart() {
super.onStart()
viewModel.connect() // connect to service
}

}
我现在用 Compose 和 Navigation 写应用,现在好多地方需要复制 Compose 官方的代码,比如对话框和上下文菜单,甚至 Navigation 也要复制修改。
@yuhuazhu 据说车载还在用 Java
@debuggeeker 老项目当然不动,总会写与历史代码关联不大的新功能,然后你就会面临是继续用历史代码搞,还是推倒重来。
214 天前
回复了 eyeshuaji 创建的主题 Android 自家安卓电视没有/storage/emulated/0/这个目录
@eyeshuaji 能装第三方应用么,文件管理器之类的,看下路径,电视厂商可能改了东西,有可能是放到了 USB 上。我之前维护过一段时间的 wps 投影宝,主要支持小米电视。
214 天前
回复了 eyeshuaji 创建的主题 Android 自家安卓电视没有/storage/emulated/0/这个目录
应该还挂载/sdcard 吧,一般来说 emulated 表示存储空间是经过加密的,区分了多用户。老设备先看看/sdcard 一般等同于/storage/emulated/0
可能有个加载框,加载框每消失就不能打开菜单。
这个还不严重,严重的是调试器在调试第三方库的 supend 调用是无法 step over 的,会卡住。
搞一个帧队列,丢掉来不及处理的视屏帧。背压肯定会有的,选择丢帧或者提升模型处理性能。
259 天前
回复了 bojue 创建的主题 教育 高考数学 145 左右很高吗
现在 985 分数要基本考到总分的 85%左右,145/150 可能只错了一个选择题或者填空题,考上普通 985 肯定没问题,top10 有点悬。
现在 WPS 已经全面运营了,不务正业。
1  2  3  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3293 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 22ms · UTC 12:09 · PVG 20:09 · LAX 05:09 · JFK 08:09
Developed with CodeLauncher
♥ Do have faith in what you're doing.