细碎的玩意·其一
在Kotlin中有十分熟悉的for-in循环,终于不和while功能重复了
可是Kotlin不像py那样直接用range生成range
比如下边这样能得到一个的范围
val range = 0..10还有这样能得到的范围
val range = 0 until 10后面加个step就可以一次想加几次就加几次
val range = 0 until 10 step 2如果想倒过来就可以像下面这样得到一个的区间
val range = 10 downTo 1怎么说呢,挺好的,就是要适应
let是个作用域函数……
一般用于给某个对象判空,如果为空就不做那些事了不然会崩,比如
obj?.let { println(it.toString())}和其它作用域函数一样,it在这个大括号里边表示对象本身
try是用来看看一段代码在运行时会不会崩掉的,如果真的崩了也不会把整个程序带走
它的完整结构包含try、catch和finally
GPT总结得很好
try { // 可能会引发异常的代码} catch (e: ExceptionType) { // 处理异常的代码} finally { // 可选的代码块,不管是否发生异常都会执行}一般的e: Exception基本代表所有类型的异常
可以有很多个catch来捕获各种各样的异常,然后做出各种各样的应对方案
你可能需要:有关Lambda表达式
kt中初始化列表似乎和别的语言不太一样?
比如我要一个有20个元素的列表,其值均为5,可以这么写
val list = List(20) {5}有点太神奇了说实话
对可变列表也是一样的
如果想要元素按一定规律变化,可以这么写
val mutableList = MutableList(20) { "Element $it" }元素的值分别为"Element 0", "Element 1"……
然后当然也可以
val mutableList = MutableList(20) { it * 3 }这样它就是[0, 3, 6, ..., 57]了
这就是21世纪的语言吗太强悍了
唯一的问题是,如果想像其他语言一样已知元素创建列表时不能像上面那样
list = [233, 555, 114] # 人家py多方便啊kt要用listof来创建
val list = listof(233, 555, 114)这大抵是因为kt里{}的作用太多了罢
说的就是你,Lambda 表达式!
2025 年 11 月 18 日……
孩子们,一年之后我终于回来了,直接肘赢这一坨东西
事实上,上面那几个List的初始化都省略了一个传入的参数,即元素索引
这是初始化不省略的样子:
// val mutableList = MutableList(20) { "Element $it" }
val mutableList = MutableList(20) { index: Int -> "Element $index"}由于这个 lambda 表达式只有一个参数,于是我们可以把参数列表全部省略,然后用it来指代这个唯一的参数
replace接收两个参数,将字符串中的对应字符替换成你想要的,比如
val result = text.replace(Regex("[ /\\\\:*?\"<>|]+"), "_")方括号中的所有字符都会被替换为下划线,+代表无论几个这些字符连在一起都通通变成一个下划线
如果变成这样,代表这些字符连在一起大于等于两个才会被替换
val result = text.replace(Regex("[ /\\\\:*?\"<>|]{2,}"), "_")既然能调下限,那也一定能改上限
这种比较新的语言都是这样轮子特别多的吗
其实都是 Java 的类啦
可以用Java的TimeUnit对时间进行方便的转换
获取现在时间只需要System.currentTimeMillis()获取现在的毫秒时间
通过TimeUnit.原单位.to新单位(数值)就可以方便地得到一个新的单位的时间辣
如果要处理日程之类的东西……说实话用Java的Calendar会比较方便
有关 vararg
Section titled “有关 vararg”vararg意为 var-arg,即可变长度参数,它的用法长下面这样
fun sumNumbers(vararg numbers: Int): Int = numbers.sum()
sumNumbers(1, 2, 3, 4, 5) // 15一般来讲,这个vararg都要放在最后一个,不然就得变成命名参数了
像 Dart 一样,Kotlin 也是有展开操作符的,也就是把列表里面的元素全部展开,也就是下面这样
val numbers = intArrayOf(1, 22, 4)
sumNumbers(*n)为了不发生奇怪的情况,一个函数最多只能有一个vararg参数
顺带一提,在 Java 中,可变长度参数长这样:
public int sunNumbers(int... numbers) { return Arrays.stream(numbers).sum();}其它语言特性
Section titled “其它语言特性”kt:孩子们,我也有三引号
超多控件,芝士雪豹,并不深但是广
其实就是属性超多啦
如果某个属性拥有多个值,可以在不同的值之间加上|,比如android:layout_gravity="end|bottom"
如果没有特别指定,那在xml中下面的控件会把上面的盖住
还有个东西大大简化了控件的使用,详见有关Binding
有关TextView
Section titled “有关TextView”textStyle可以决定文字是否加粗或者斜体
typeface可以决定文字的类型(只有一些简单的属性
fontFamily可以决定文字的字体——和上一个属性有些相似呢,不过基本什么字体都能支持
paintFlags可以给文字设置下划线和删除线,但只能在代码里边赋值,为什么?
像这样就是给它加一条下划线
tipTextView.paintFlags = android.graphics.Paint.UNDERLINE_TEXT_FLAGSTRIKE_THRU_TEXT_FLAG则是添加删除线可是似乎只能同时应用一个属性
我有预感这些属性在别的有文字的控件里边也可以用
类似语言,在不同的values文件夹里能设置它的字体颜色之类的属性,这样就能支持深色模式了
有关EditText
Section titled “有关EditText”hint是设置提示文本
android:background="@android:color/transparent"可以让下划线滚蛋
有关Button
Section titled “有关Button”使用MaterialButton,更现代化且更易配置!
可以轻松设置边框
有关ImageView
Section titled “有关ImageView”可以用scaleType这个属性来控制图片的缩放方式
比如fitXY是拉伸,centerCrop是保持比例使图片越界填充整个ImageView,centerInside则不会让图片越界,只会尽可能填满
有关SearchView
Section titled “有关SearchView”iconifiedByDefault="false"表示默认情况下展开搜索框
如果想在菜单里面加上搜索,可以添加一个这样的item
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_search" android:icon="@drawable/ic_search" android:title="Search" android:showAsAction="ifRoom|collapseActionView" android:actionViewClass="androidx.appcompat.widget.SearchView" /></menu>在代码中可以用setOnQueryTextListener来监听搜索输入,像下面一样
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { // 用户提交搜索时触发 if (query != null) { performSearch(query) // 执行搜索逻辑 } return true }
override fun onQueryTextChange(newText: String?): Boolean { // 用户每次输入变化时触发 if (newText != null) { updateSearchResults(newText) // 实时更新搜索结果 } return true }})GPT总结得真好是吧
如果是在菜单里面,就要在 onCreateOptionsMenu 里边初始化了
这玩意还能和 RecyclerView 一起用,实现有趣的效果
有关RecyclerView
Section titled “有关RecyclerView”需要写适配器的神奇东西
有关Adapter
Section titled “有关Adapter”有关notifyItemChanged
Section titled “有关notifyItemChanged”它是Adapter里面的一个方法,可以更新某个项的数据
notifyItemChanged(adapterPosition)这行代码的意思是更新当前位置的项
执行了这行代码就会让这一项重新绑定一次ViewHolder,从而防止一些奇奇怪怪的bug(比如很多个项共用一个变量)
这样做还能获赠动画效果
有关ViewPager
Section titled “有关ViewPager”同样要写适配器的神奇东西,可以实现不同页面之间的滑动切换
现已全面升级为ViewPager2
有关Adapter
Section titled “有关Adapter”下面就是一个GPT写的有关Adapter的示例
class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
private val fragments = listOf( HomepageFragment(), StatsFragment(), SettingsFragment() )
override fun getItemCount() = fragments.size
override fun createFragment(position: Int): Fragment = fragments[position]
}在那些并不智能的布局里(也就是除了ConstraintLayout)都要用一大串layout来决定控件的位置
layout_gravity是用来决定这个控件以哪条边为基准,比如
android:layout_gravity="end|bottom"这样能让这个控件以右下角为原点
有关ConstraintLayout
Section titled “有关ConstraintLayout”这玩意简直是超级神器,太好使了
如果要使一个控件的尺寸随别的控件变化,只要把它的尺寸设为0dp,然后设置这个方向上对其哪个控件(的两条边)就好
有关MediaPlayer
Section titled “有关MediaPlayer”这玩意有个神奇的特性那就是即使所处的界面关闭了还会继续播放
所以比较方便的做法就是在界面关闭时把播放一起关了
如果播放操作是在ViewModel中写的,那就可以专门准备个MediaPlayer然后每次播放都重新初始化一次,界面关闭也别忘了释放资源
有关Bitmap
Section titled “有关Bitmap”Bitmap是个保存了图像信息的对象
可以通过很多方式创建
比如从资源文件
val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.image) // decode,意为解码从文件
val file = File("/path/to/image.jpg")val bitmap = BitmapFactory.decodeFile(file.absolutePath)从输入流
val inputStream = FileInputStream("image.jpg")val bitmap = BitmapFactory.decodeStream(inputStream)还可以生成空白的来画画
Bitmap可以用compress()来把图像压缩成别的格式的文件
有关语言(平时说的那个
Section titled “有关语言(平时说的那个”一般的语言文件夹格式是
values-zh-CN这样,有language和region两部分
当然region省略也是可以的
如果是自定义语言,可以这样
values-b+zh+ME
有关attachBaseContext
Section titled “有关attachBaseContext”这玩意是更新资源文件的一个方法,接收一个Context然后更新现在的页面
可以用来更新页面语言
有关ContextCompat
Section titled “有关ContextCompat”这玩意可以获取一个资源的示例,用法是ContextCompat.get啥啥啥(context, id)
这样就能在代码中一遍应用多种不同模式下的资源
不知道该放到哪里的东西
Section titled “不知道该放到哪里的东西”lifecycleScope.launch { while (true) { delay(10000) lifecycleScope.launch(Dispatchers.Main) { reloadFragment(this@HomepageFragment) } } }this还能这么用?!
好吧其实就是指定是哪个this
一定,一定要记得初始化啊!