跳至主要內容
Jetpack Compose Chat app

开始

总算是大致地学好了 Compose,现在终于新建文件夹了...... 这其实是安卓期末课设来着的,但队友不学安卓,他们整后端去了,那我就可以自由开发了 hhh

先大概地过了 XML 部分,RecycleView、Fragment 什么的一通嗦了,然后新建项目的时候被 AS 用 DataBinding 给吸引过去了。了解到是属于 Jetpack 的一部分后,以及顺便用 AS 迁移到了 Kotlin,补了点语法(一堆 api 和用法真完全是为了实用而开发的了),然后就正式地换用 Compose 来写了


Chilfish大约 5 分钟bloglogsAndroid
数据层

介绍

为什么要使用不同的层

将代码拆分为不同的层可让应用具备更高的可伸缩性、更加稳定可靠、更易于测试。为不同的层定义清晰的边界还有助于多个开发者更轻松地开发同一应用,而不会对彼此产生负面影响

Android 的推荐应用架构 指出,应用应至少具有一个界面层和一个数据层


Chilfish大约 8 分钟Android
DataStore

介绍

Preferences DataStore 是一个轻量级的数据存储解决方案,用于存储和读取应用程序的偏好设置数据

与 SharedPreferences 不同,Preferences DataStore 是基于协程和流的 API,可以在异步上下文中使用,而不会阻塞主线程。SPref 存的是 xml,而 DataStore 存的是二进制文件,所以会快很多

而且 SPrf 可能阻塞 UI 线程,导致 ANR 异常(需要等等 sp 文件加载完成,而且存储数据越多,文件越大,加载越慢,所有之前使用时都会分类存储在不同的 sp 文件中,如用户信息,业务信息,统计信息等)且不能用于跨进程通信


Chilfish大约 2 分钟Android
DataBinding

文档

主要为了解决繁琐的 findViewById 及其 null 的问题,更方便地将数据绑定到 xml View 上

更多还是看与 GPT 的 Logs 吧)

BaseAdapter

abstract class BaseAdapter<T, VB : ViewDataBinding>:
    RecyclerView.Adapter<BaseAdapter.ViewHolder<VB>>() {

    private var onItemClickListener: ((T) -> Unit)? = null
    protected var items: List<T> = listOf()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<VB> {
        val inflater = LayoutInflater.from(parent.context)
        val binding = DataBindingUtil.inflate<VB>(inflater, getLayoutId(), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder<VB>, position: Int) {
        val item = items[position]
        holder.bind(item)
        holder.itemView.setOnClickListener {
            onItemClicked(item, holder.itemView)
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun updateItems(newItems: List<T>) {
        items = newItems
        notifyDataSetChanged()
    }

    protected abstract val getLayoutId: Int

    open fun onItemClicked(item: T, view: View) {
        onItemClickListener?.invoke(item)
    }

    class ViewHolder<VB : ViewDataBinding>(val binding: VB) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Any?) {
            binding.executePendingBindings()
        }
    }
}

Chilfish小于 1 分钟Android
组件们以及组件化

组件主题

简便点就直接使用 Material3 就好,组件什么的查 文档 就行

通常,应用的主题会在软件包根目录 /Theme/Theme.kt 中,里面会有一个 Composable 函数 软件名Theme,只要在 Activity 的 setContent 中套用这个 Theme 就行了。颜色可以在上面的 ColorScheme 中语义化地定义,一般就不用 color.xml 里的了


Chilfish大约 2 分钟Android
ViewModel

ViewModel

ViewModel 是一个与 UI 无关的类,它负责管理应用程序的数据和业务逻辑,同时与 UI 层进行通信

ViewModel 的主要作用是将 UI 和数据层分离,避免了在 UI 层中进行数据操作和业务逻辑处理的情况。这样可以使得 UI 层更加专注于显示数据和处理用户交互,而将数据和业务逻辑的处理交给 ViewModel 处理。这种分离可以使得代码更加清晰、易于维护和测试

像是表单验证、路由跳转等逻辑应该交由 ViewModel 来处理,而不是 Composable 函数

在 Jetpack Compose 中,ViewModel 通常与 LiveData 或 Flow 一起使用,以实现数据的响应式更新。当 ViewModel 中的数据发生变化时,LiveData 或 Flow 会通知 UI 层进行更新。这种方式可以使得 UI 层与数据层之间的通信更加简单和高效


Chilfish大约 7 分钟Android
文件 IO 流

读取项目 assets 的文本文件

assets 文件夹用来放一些静态文件,与 res/raw 类似吧,与 res 和 java 同级,都在 \app\src\main\

现假设要读取 assets 下的一个 json 文件,并转为字符串。把 IS 写进 try 里,可以自动地关闭文件流,就和 py 的 with open 一样

JsonParser jsonParser = new JsonParser();
StringBuilder json = new StringBuilder();

try (InputStream inputStream = getApplicationContext().getAssets().open("messages.json")) {
  BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
  String line;
  while ((line = reader.readLine()) != null) {
    json.append(line);
  }

  ans = json.toString();
} catch (Exception e) {
  e.printStackTrace();
}

Chilfish小于 1 分钟Android
控制 View 属性的 Java 代码

旨在用 Java 动态控制 xml 中的属性)这不 js 嘛)

LayoutParams

控制 android:layout_xx

LayoutParams 通常在代码中用于动态地设置一个 View 的布局参数,以便在运行时改变 View 的位置、大小、对齐方式等属性

除了常见的 margin、width 等,在 RelativeLayout 中,LayoutParams 还可以定义 View 与其它 View 的相对位置关系,如 alignParentTopalignLeft 等属性


Chilfish大约 1 分钟Android
Fragment 组件

Fragment in XML View

概念

安卓的 Fragment 是一种可以嵌入在 Activity 中的 UI 组件,它可以帮助开发者更加灵活地管理应用的 UI 界面,实现动态添加、移除和替换 UI 组件等功能

Fragment 的主要作用包括:

  • 实现灵活的 UI 布局:通过将 UI 界面划分为多个 Fragment,可以更加灵活地组合和管理 UI 布局,适应不同屏幕尺寸和设备方向的变化

  • 实现模块化开发:将应用的不同模块拆分为多个 Fragment,可以更加方便地进行模块化开发和维护,提高代码的复用性和可维护性

  • 实现动态添加和替换 UI 组件:通过 Fragment 的生命周期和管理方法,可以方便地动态添加、替换和移除 UI 组件,实现动态 UI 效果和交互效果


Chilfish大约 4 分钟Android