当前位置: 首页 > news >正文

五天自学 Compose 从 0 到 1 构建一个 WanAndroid 客户端

五天自学 Compose 从 0 到 1 构建一个 WanAndroid 客户端

这边文章主要分享下如何自学 Compose ,五天时间内从 0 到 1 构建一个 WanAndroid 客户端。

先来看看效果图

黑夜模式明亮模式

这篇文章主要是针对初学者如何自学 ComposeMVI

Day 1

学习 Compose 最重要的是要掌握重组概念,也就说 Compose 没有原来 Android 测绘机制,Compose 中控件的显示及状态描述,都是通过 state 状态机一样的机制来决定,譬如闪屏页跳转到首页显示。

其次需要掌握:modifi, 黑夜模式与明亮模式下的切换适配

@Composable
fun KTAndroidComposeSimpleTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    //利用监听黑夜模式切换状态动态设置 App 主题
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }

        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    val systemUiCtrl = rememberSystemUiController()

    SideEffect {

        systemUiCtrl.setSystemBarsColor(
            color = Color.Transparent,
            isNavigationBarContrastEnforced = false
        )
    }
    
    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography,
        content = { ProvideWindowInsets(content = content) }
    )


}

熟悉 Modifier 掌握控件形状的描述譬如实现闪屏页面:

黑夜模式明亮模式

Day 2

关注 Composenavigation 的使用掌握所有页面的跳转控制,注意一点的 NavHostController 作为控制整个导航动作的时候,声明使用的过程中最好不要一层层嵌套下去注册路由避免出现利用 hint 初始化 model 的时候出现奔溃。

掌握 Scaffold 脚本架这个超级布局的使用,如何利用他实现侧滑、添加悬浮按钮、底部导航栏等。譬如实现一下页面:

Day 3

学习 Compose 下的pandingLay 相关布局,是如何能够做到类似 RecycleVIew 列表效果,以及如何封装一个通用的分页请求工具

fun <T : Any> ViewModel.easyPager(
    config: BasePagingConfig = BasePagingConfig(),
    callAction: suspend (page: Int) -> BasicBean<ListWrapper<T>>
): Flow<PagingData<T>> {
    return basePager(config, 0) {
        val page = it.key ?: 0
        val response = try {
            HttpResult.Success(callAction.invoke(page))
        } catch (e: Exception) {
            if (NetTools.checkNetUsefull(LearnAndroidApp.CONTEXT).not()) {
                showToast("没有网络,请重试")
            } else {
                showToast("请求失败,请重试")
            }
            HttpResult.Error(e)
        }
        when (response) {
            is HttpResult.Success -> {

                val data = response.result.data

                val hasNotNext = (data!=null)&&(data.size< it.loadSize) && (data.over)

                PagingSource.LoadResult.Page(
                    data = data?.datas?: emptyList(),
                    prevKey = if (page - 1 > 0) page - 1 else null,
                    nextKey = if (hasNotNext) null else page + 1
                )
            }
            is HttpResult.Error -> {
                PagingSource.LoadResult.Error(response.exception)
            }
        }
    }
}

譬如在广场这个选项卡页面的 viewModule 我们就可以这样子写完整个分页请求:

@HiltViewModel
class WanAndroidSquareViewModule @Inject constructor(
    private var service: WanAndroidNetService,
) : ViewModel() {
    private val pager by lazy {
        easyPager {
            delay(2000)
            service.getSquareData(it)
        }.cachedIn(viewModelScope)
    }
    var viewStates by mutableStateOf(SquareViewState(pagingData = pager))
        private set
}
//描述当前的分页状态并告知页面显示
data class SquareViewState(
    val isRefreshing: Boolean = false,
    val listState: LazyListState = LazyListState(),
    val pagingData: PagingArticle
)

sealed class SquareViewAction {
    object Refresh : SquareViewAction()
}

基于 lottie 动画库结合 SwipeRefresh 实现刷新及加载更多的封装。核心代码如下:

@Composable
fun <T : Any> RefreshWidget(
    lazyPagingItems: LazyPagingItems<T>,
    isRefreshing: Boolean = false,
    modifier: Modifier = Modifier,
    onRefresh: (() -> Unit) = {},
    listState: LazyListState = rememberLazyListState(),
    itemContent: LazyListScope.() -> Unit,
) {
    val rememberSwipeRefreshState = rememberSwipeRefreshState(isRefreshing = false)
    //错误页
    val err = lazyPagingItems.loadState.refresh is LoadState.Error
    if (err) {
        ErrorContent { lazyPagingItems.retry() }
        return
    }
    SwipeRefresh(
        state = rememberSwipeRefreshState,
        onRefresh = {
            onRefresh.invoke()
            lazyPagingItems.refresh()
        },
        modifier = modifier,
        indicator = {state, refreshTrigger ->RefreshWidgetIndicator(state, refreshTrigger)  }
    ) {
        //刷新状态
        rememberSwipeRefreshState.isRefreshing =
            ((lazyPagingItems.loadState.refresh is LoadState.Loading) || isRefreshing)
        //列表
        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
            state = listState
        ) {
            //条目布局
            itemContent()
            //加载更多状态:加载中和加载错误,没有更多
            if (!rememberSwipeRefreshState.isRefreshing) {
                item {
                    lazyPagingItems.apply {
                        when (loadState.append) {
                            is LoadState.Loading -> LoadingItem()
                            is LoadState.Error -> ErrorItem { retry() }
                            is LoadState.NotLoading -> {
                                if (loadState.append.endOfPaginationReached) {
                                    NoMoreItem()
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

最终可实现到以下效果:

Day 4

掌握一些开库库譬如:coilsystemuicontrollerdatastore 等使用,基于这样譬如是实现一个登录页面的核心逻辑及个人中心页面逻辑

Day 5

其实到这里也就是串联整个 App 页面跳转及样式调整等较为简单的工作。至此整个 App 基于 MVICompose 的实现就已完工,其实在整个过程中并不是很难,单存在不少的痛点譬如 constraintlayout 的铰链有区别、利用constraintlayout 布局特性控制控件填充效果、旧的 UI 观念转换。

最后插入一句题外话,最近求职中,总是有遇到一些公司觉得做硬件交互 App 类型的人就不能 App 做得很好看,我只能说见仁见智,五天我能够从一个新的知识点重新写一个 material 类型 App 进行一个的默默发声。相反我觉得如果做硬件交互类型出身的工程师会比传统纯写页面的工程师更为优势,因为他们更懂性能优化,往往一个行业级别应用 App ,特别与硬件通信打交道 App 性能要求更为严格因为我们无法要求客户使用性能好的手机还是差的手机,只能尽最大程度的压测反复验证才能得出一份较好的答卷。更特别点的在定制化系统上开发由于系统被阉割还需要做一些特殊操作才能实现常见的功能等困难。

目前本人正在观望机会中如果有兴趣的话可以找我联系;

Emial:luckyrookie.ypz@qq.com

项目地址如下:https://github.com/KilleTom/KTAndroidComposeSImple

相关文章:

  • 做外贸网站有哪些/百度移动端优化
  • 做那个的视频网站/在线看seo网站
  • 网站中文域名到期/公司seo是指什么意思
  • 淘宝客网站做百度竞价/刚刚传来最新消息
  • 类似中企动力的做网站的/网站建设网络推广seo
  • android系统下载官网/seo排名的方法
  • 【C++】类和对象要点汇总
  • Pr 案例:制作进度条
  • 记账最简单的方法 教你分析收支类别
  • STM32新建工程
  • 基于PCNN脉冲耦合神经网络的图像分割
  • 使用G2O解决优化问题的简单例子
  • 24.一文理解Python函数装饰器
  • 数据结构四:队
  • 【Redis】实战篇:结合Redis实现发送短信验证码登录功能
  • kubernetes_13_普通Service和无头Service
  • 宝藏命令行工具整理
  • app逆向(10)| APP的加固与脱壳