Android KTX | 官方 Kotlin-core 扩展库 方法大全

1.0 前言

Android KTXAndroid 中的一组 Kotlin 扩展程序,可以为Android开发提供简洁方便的 Kotlin 代码。
如果我们新建一个项目,可以发现,Core KTX默认是被依赖到项目里的,能够说明Google对其的重视程度。
KTX中的方法有很多,但平时都不知道哪些地方可以使用KTX,这两天特意罗列了一下,在此记载。

1.1 添加依赖

dependencies {
    
    
    implementation "androidx.core:core-ktx:1.9.0"
}

添加依赖后,我们可以在External Libraries中看到ktx-core中有这些包,下文会按照这些包的顺序进行罗列

在这里插入图片描述

1.2 animation

1.2.1 Animator.addListener

平时我们注册Animator监听的时候,需要去实现其每一个方法

animator.addListener(object : Animator.AnimatorListener{
    
    
    override fun onAnimationStart(animation: Animator?) {
    
    
		Log.i(TAG,"onAnimationStart")
    }

    override fun onAnimationEnd(animation: Animator?) {
    
    
		Log.i(TAG,"onAnimationEnd")
    }

    override fun onAnimationCancel(animation: Animator?) {
    
    
		Log.i(TAG,"onAnimationCancel")
    }

    override fun onAnimationRepeat(animation: Animator?) {
    
    
    	Log.i(TAG,"onAnimationRepeat")
    }
})

而使用KTX我们可以只实现自己所需要的方法

val animator = ValueAnimator.ofInt(0, 100)
animator.addListener(onStart = {
    
    
    Log.i(TAG,"onStart")
})

更多监听/回调的简化,详见我的另一篇文章 在Android中,简化冗长的监听/回调 写法

1.3 content

1.3.1 contentValuesOf

contentValuesOf用于将若干个Pair转化为ContentValues

val pair = Pair("key", true)
val pair2 = Pair("key2", "hello")
val contentValues = contentValuesOf(pair,pair2)
val result = contentValues.getAsBoolean("key")
val result2 = contentValues.getAsString("key2")
Log.i(TAG, "result:$result result2:$result2") //打印结果为result:true result2:heelo

ContentValues和Hash Table都是一种存储的机制。两者的区别在于,contentValues只能存储基本类型的数据,String,int之类的,不能存储对象,而Hash Table却可以存储对象。
把数据插入数据库中时,首先要有一个ContentValues的对象:
ContentValues contentValues = new ContentValues();
contentValues.put(key,values);
SQLiteDataBase sdb;
sdb.insert(database_name,null,initialValues);
成功插入则返回记录的id,否则返回-1。

1.3.2 ContextKt

1.3.2.1 Context.getSystemService()

可以不用再传入String,直接根据泛型返回Service,比如我们这里获取WindowManager
原本需要这样获取

val windowManager1 : WindowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager

现在可以这样获取

val windowManager = getSystemService<WindowManager>()

1.3.2.2 Context.withStyledAttributes

自定义View中获取自定义属性
原本要这么写

val ta = context.obtainStyledAttributes(attrs, R.styleable.MyView)
val color = ta.getColor(R.styleable.MyView_titleTextColor, defColor)
ta.recycle()

现在可以这样写

context.withStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, defStyleAttr) {
    
    
    val color = ta.getColor(R.styleable.MyView_titleTextColor,defColor)
}

1.3.3 SharedPreferencesKt

更简单的使用 SharedPreferences

val sharedPreferences = application.getSharedPreferences("sp", MODE_PRIVATE)
sharedPreferences.edit {
    
     putBoolean("key", value) }

1.3.4 content.res

1.3.4.1 TypedArray

TypedArrayKt定义了很多getXXXXOrThrow的扩展方法,我们看其内部代码,可以看到主要是在获取自定义属性之前,先去检查下这个属性是否存在,如果不存在,那就抛出异常。
我们以getBooleanOrThrow为例

val ta: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.Topbar)
ta.getBooleanOrThrow()
ta.recycle()

来看下它源码

public fun TypedArray.getBooleanOrThrow(@StyleableRes index: Int): Boolean {
    
    
    checkAttribute(index)
    return getBoolean(index, false)
}

private fun TypedArray.checkAttribute(@StyleableRes index: Int) {
    
    
    if (!hasValue(index)) {
    
    
        throw IllegalArgumentException("Attribute not defined in set.")
    }
}

可以看到,其获取自定义属性之前,都会先去调用hasValue判断该属性是否存在。

1.4 database

1.4.1 SQLiteDatabaseKt

这个是用来简化Sqlite数据库的,一般都直接用封装后的Room了,不会直接调用这个方法

1.4.2 CursorKt

提供了一些可为空的获取

cursor.getDouble() //不可为空
cursor.getDoubleOrNull() //可为空

1.5 graphics.drawable

1.5.1 BitmapDrawableKt

1.5.1.1 Bitmap.toDrawable

将Bitmap转化为Drawable

val drawable = bitmap.toDrawable(resources)

1.5.2 ColorDrawableKt

1.5.2.1 Color.toDrawable

Color转化为Drawable

val drawable = color.toDrawable()

1.5.2.2 @ColorInt Int…toDrawable

ColorInt转化为Drawable

val drawable = R.color.black.toDrawable()

1.5.3 DrawableKt

1.5.3.1 Drawable.toBitmap

Drawable转化为Bitmap

val bitmap = drawable.toBitmap() //不为空
val bitmap = drawable.toBitmapOrNull() //可为空

1.5.3.2 Drawable.updateBounds

设置这个可绘制对象的边界

drawable.setBounds(100, 50, 150, 200) //原方法
drawable.updateBounds(100,50,150,200) //使用Ktx

1.5.4 Iconkt

BitmapUriByteArray转化为Icon

Bitmap.toAdaptiveIcon(): Icon
Bitmap.toIcon(): Icon
Uri.toIcon(): Icon
ByteArray.toIcon(): Icon

1.6 graphics

1.6.1 BitmapKt

可以简化Bitmap的创建

val bitmap = createBitmap(...).applyCanvas {
    
    
    drawText(...)
    drawLine(...)
    drawRect(...)
}
val scaleBitmap = bitmap.scale(1280, 720) //创建缩放后的Bitmap
bitmap.contains(point)
bitmap.contains(pointF)
bitmap.get(10, 20) //获取指定位置的像素值
val color = resources.getColor(R.color.black)
bitmap.set(30, 50, color) //设置指定位置的像素颜色

1.6.2 CanvasKt

1.6.2.1 Canvas.withClip

使用闭包,无需自己再save() -> clip()后,重置画布restoreToCoun()

val rect = RectF(100F, 50F, 200F, 150F)
canvas?.withClip(rect) {
    
    
    this.drawArc()
    this.drawText()
}

其他也是类似的

canvas?.withScale {
    
    

}
canvas?.withRotation {
    
    

}
canvas?.withSave {
    
    

}
canvas?.withMatrix {
    
    

}
canvas?.withSkew{
    
    

}
canvas?.withTranslation{
    
    

}

1.6.2.2 ColorKt

val color = R.color.teal_700
val alphaInt = color.component1() //相当于Color.alpha(),获取color的透明度
val redInt = color.component2() //相当于Color.red(),获取color的red值
val greenInt = color.component3() //Color.green(),获取color的green值
val blueInt = color.component4() //Color.blue(),获取color的blue值

val (alphaInt, redInt, greenInt, blueInt) = color //解构color,解构为透明度、red值,green值,blue值

1.6.3 ImageDecoderKt

// 利用Android9.0新增的ImageDecoder读取图片
val source: ImageDecoder.Source = ImageDecoder.createSource(contentResolver, imageUri)
// 从数据源解码得到图形信息
//原本的方式
val drawable: Drawable =
    ImageDecoder.decodeDrawable(source, object : ImageDecoder.OnHeaderDecodedListener {
    
    
        override fun onHeaderDecoded(
            decoder: ImageDecoder,
            info: ImageDecoder.ImageInfo,
            source: ImageDecoder.Source
        ) {
    
    

        }
    })
//Ktx的方式
val drawable: Drawable = source.decodeDrawable {
    
     info, source -> }
ivPhoto.setImageDrawable(drawable) // 设置图像视图的图形对象

1.6.4 MatrixKt

Matrix的便捷操作

val rotationMatrix = rotationMatrix(...) //创建Matrix,并进行rotation操作
val scaleMatrix = scaleMatrix(...) //创建创建Matrix,并进行scale操作
val translationMatrix = translationMatrix(...) //创建创建Matrix,并进行translation操作

val newMatrix = rotationMatrix.times(scaleMatrix) //用这个矩阵乘以另一个矩阵并返回结果作为一个新矩阵
val matrixFloatArray = newMatrix.values() //获取矩阵的9个值,以长度为9的FloatArray数组表示

1.6.5 Pathkt

Path的便捷操作

val path1 = Path()
val path2 = Path()
val path3 = path1 + path2
val path4 = path1 - path2
val path5 = path1 or path2
val path6 = path1 xor path2
val path7 = path1 and path2
val flatten = path1.flatten(0.5F)

1.6.6 PointKt

Point的便捷操作

val point1 = Point()
val point2 = Point()
val point3 = point1 + point2
val point4 = point1 - point2
val pointF = point1.toPointF()
val point5 = pointF.toPoint()
val point6 = -point1 //unaryMinus
val x = point1.component1() //获取point1.X
val y = point1.component2() //获取point1.Y
val (x2, y2) = point2 //解构,获取X和Y

1.6.7 PorterDuff.Mode

图层混合模式PorterDuff.Mode便捷操作

val colorFilter = PorterDuff.Mode.SRC.toColorFilter(color)
val xferMode = PorterDuff.Mode.SRC.toXfermode()

1.6.8 RectKt

Rect的便捷操作

val rect1 = Rect()
val rect2 = Rect()
val rect3 = rect1 + rect2
val rect4 = rect1 - rect2
val rect5 = rect1 or rect2
val rect6 = rect1 xor rect2
val rect7 = rect1 and rect2
val contains = rect1.contains(rect2)
val rectF = rect1.toRectF()
val rect8 = rectF.toRect()
rect1.times(65) //等比例返回新Rect
rectF.times(0.12F)
val region99 = rect1.toRegion()
//rectF.transform(matrix) //根据matrix变化为新的RectF
val (left, top, right, bottom) = rect1 //解构,将rect拆分为left, top, right, bottom

1.6.9 RegionKt

Region的便捷操作

val region1 = Region()
val region2 = Region()
val region3 = region1 + region2
val region4 = region1 - region2
val region5 = region1 or region2
val region6 = region1 xor region2
val region7 = region1 and region2
val region8 = -region1 //unaryMinus
val region9 = !region1 //非运算
val iterator = region1.iterator()
region1.forEach {
    
      }
region1.contains(point1)

1.6.10 Shader

着色器

transform : 包装代码块之 Shader.getLocalMatrixShader.setLocalMatrix之间

val shader = Shader()
shader.transform {
    
    
        this.setSkew() //this : Matrix
}

看下其内部实现

public inline fun Shader.transform(block: Matrix.() -> Unit) {
    
    
    val matrix = Matrix()
    getLocalMatrix(matrix)
    block(matrix)
    setLocalMatrix(matrix)
}

1.7 location

1.7.1 LocationKt

将Location解构为经度和维度

val location : android.location.Location = Location("")
val (lat,lng) = location

1.8 net

1.8.1 UriKt

Uri便捷使用

val uri1 = Uri.parse("content://media/external/images/media/4")
val uri2 = "content://media/external/images/media/4".toUri()
val file1 = uri1.toFile()
val uri3 = file1.toUri()

1.9 os

1.9.1 Bundlekt

Pair转Bundle

val bundle = bundleOf(Pair("key1", "value1"), Pair("key2", "value2")) //Bundle
val bundle2 = persistableBundleOf(Pair("key1", "value1"), Pair("key2", "value2")) //PersistableBundle
val map = HashMap<String,String>()
val bundle3 = map.toPersistableBundle()

1.9.2 OutcomeReceiverKt

这个和协程有关,暂时还没用过

1.9.3 HandlerKt

Handler便捷操作

val WHAT = 0x01
val handler = Handler()
handler.postAtTime(SystemClock.uptimeMillis(),WHAT) {
    
    

}
handler.postDelayed(1000L,WHAT) {
    
     //回调放在最后

}

1.9.4 TraceKt

systrace 性能优化 : 结合Android内核的数据,生成Html报告
将代码块包装在TraceCompat.beginSection(sectionName)TraceCompat.endSection()之间

trace("sectionName") {
    
    
    //真正执行的代码,会统计这部分代码的执行时间等
}

1.9.5 CharSequenceKt

CharSequence的便捷使用

"hello".isDigitsOnly() //是否只包含数字,相当于 TextUtils.isDigitsOnly
"world".trimmedLength() //获取字符串去除头尾空格之后的长度,相当于 TextUtils.getTrimmedLength

1.9.6 HtmlKt

val spanned1 ="<html>....</html>".parseAsHtml()
val spanned : Spanned? = null
val html = spanned?.toHtml()

1.9.7 SpannableStringBuilder

便捷地创建富文本

val color = Global.getColor(R.color.teal_700)
val spannedString = buildSpannedString {
    
    
    bold {
    
    
        append("001")
    }
    color(color) {
    
    
        append("002")
    }
    underline {
    
    
        append("003")
    }
    backgroundColor(color) {
    
    
        append("004")
    }
    italic {
    
    
        append("005")
    }
    scale(1.5F) {
    
    
        underline {
    
     //可以多个组合一起使用
            append("006")
        }
    }
    strikeThrough {
    
     //删除线
        append("007")
    }
    subscript {
    
     //下标
        append("008")
    }
    superscript {
    
     //上标
        append("009")
    }
    append("010")
}
binding.tvInfo.text = spannedString

效果如下所示
在这里插入图片描述

1.9.8 SpannableStringKt

val spannable: Spannable? = null
spannable?.clearSpans()
spannable?.set(1, 5, StyleSpan(Typeface.BOLD_ITALIC))
val spannable1 = "qwerty".toSpannable()

1.9.9 SpannedStringKt

val spanned2: Spanned? = null
val spanned3 = spanned2?.getSpans<Spanned>(1, 6)
val spanned4 = "asdfgh".toSpanned()

1.9.10 StringKt

 "xxxxx".htmlEncode() //相当于 TextUtils.htmlEncode

1.10 transition

1.10.1 TransitionKt

动画监听便捷设置

val startScene = Scene.getSceneForLayout(group, R.layout.activity_main_start, this)
val changeBounds = ChangeBounds()
TransitionManager.go(startScene, changeBounds)
changeBounds.addListener(
    onStart = {
    
    
        Log.i(TAG,"onStart")
    },
    onEnd = {
    
    
        Log.i(TAG,"onEnd")
    },
    onCancel = {
    
    
        Log.i(TAG,"onCancel")
    },
    onResume = {
    
    
        Log.i(TAG,"onResume")
    },
    onPause = {
    
    
        Log.i(TAG,"onPause")
    })

也可以直接注册其某一个方法

changeBounds.doOnStart {
    
    
	Log.i(TAG, "onOnStart")
}
changeBounds.doOnEnd {
    
    
    Log.i(TAG, "onOnEnd")
}
changeBounds.doOnCancel {
    
    
    Log.i(TAG, "onOnCancel")
}
changeBounds.doOnResume {
    
    
    Log.i(TAG, "onOnResume")
}
changeBounds.doOnPause {
    
    
    Log.i(TAG, "doOnPause")
}

更多监听/回调的简化,详见我的另一篇文章 在Android中,简化冗长的监听/回调 写法

1.11 util

1.11.1 AndroidXConsumerKt

这个和协程有关,暂时还没用过

1.11.2 AtomicFileKt

方便AtomicFile的操作,AtomicFile这个大家一般很少见到过这个类,我查了一下,AtomicFile的作用 :
AtomicFile 保证文件的写入完成,并在写入之后删除备份文件。只要备份文件存在,那么原始文件之前遗留的操作是无效的。

1.11.3 ConsumerKt

这个和协程有关,暂时还没用过

1.11.4 HalfKt

方便转成Half类型,Half是个包装类型,可以进行浮点类型的转换

val half = 2.98F.toHalf()
val half2 = 3.926.toHalf()
val half3 = "5.9".toHalf()

1.11.5 LruCacheKt

可以用来便捷的创建LruCache

val lruCache = lruCache(...)

1.11.6 PairKt

使Pair可以快速的进行解构,获得KeyValue

val pair = Pair("key1", 1)
val (key, value) = pair

1.11.7 RangeKt

Range用于描述两个数值的范围,没用过这个

1.11.8 RunnableKt

用来协程转Runnable

1.11.9 SizeKt

用来对Size快速进行解构,获得widthheight

val size = Size(100,200)
val (width,height) = size

1.11.10 SparseArrayKt

包含SparseArrayKt / LongSparseArrayKt / SparseBooleanArrayKt / SparseIntArrayKt / SparseLongArrayKt,操作都差不多,以下以SparseArray为例

val sparseArray = SparseArray<String>()
sparseArray.append(1, "value1")
sparseArray.append(2, "value2")
sparseArray.append(3, "value3")

sparseArray.containsKey(1)
sparseArray.containsValue("value1")
sparseArray.forEach {
    
     key, value ->

}
sparseArray.getOrDefault(4, "00004")
sparseArray.getOrElse(5) {
    
    
    "00005"
}
sparseArray.isEmpty()
sparseArray.isNotEmpty()
val keyIterator = sparseArray.keyIterator()
val valueIterator = sparseArray.valueIterator()
val sparseArray2 = SparseArray<String>()
sparseArray2.set(9, "9999")
val sparseArray3 = sparseArray + sparseArray2
sparseArray3.remove(3, "value") //当值相等的之后执行remove
sparseArray.putAll(sparseArray2)

1.12 view

1.12.1 MenuKt

Menu便捷使用

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    
    
   menuInflater.inflate(com.heiko.mytest0930.R.menu.menu_main,menu)
    val menuItem = menu?.get(0)
    menu?.contains(menuItem!!)
    menu?.forEach {
    
      } //遍历Menu
    menu?.forEachIndexed {
    
     index, item ->  }
    menu?.isEmpty()
    menu?.isNotEmpty()
    val iterator = menu?.iterator()
    menu?.removeItemAt(1)

    return true
}

1.12.2 ViewGroupKt

val group = LinearLayout(this)
val childView = TextView(this)
group.contains(childView)
group.forEach {
    
     }
group.forEachIndexed {
    
     index, view -> }
group.get(1)
group.isEmpty()
group.isNotEmpty()
val iterator = group.iterator()
group.plusAssign(childView) //添加View,相当于 addView
group.minusAssign(childView) //删除View,相当于 removeView
val marginLayoutParams = group.layoutParams as MarginLayoutParams
marginLayoutParams.setMargins(10, 5, 10, 5)
marginLayoutParams.updateMargins(20, 0, 20, 0) //left、right
marginLayoutParams.updateMarginsRelative(30, 10, 30, 10) //start、end

1.12.3 ViewKt

val view = View(this)
view.doOnAttach {
    
    

}
view.doOnDetach {
    
    

}
view.doOnLayout {
    
    

}
view.doOnNextLayout {
    
    

}
view.doOnPreDraw {
    
    

}
view.setPadding(10,5,10,5)
val bitmap = view.drawToBitmap()
view.postDelayed(1000L) {
    
     //回调放在最后

}
view.postOnAnimationDelayed(1000L){
    
    

}
view.updateLayoutParams<MarginLayoutParams> {
    
    
    this.marginStart = 20
    this.width = 200
}
view.updatePadding(20,10,20,10) //left、right
view.updatePaddingRelative(30,5,30,5) //start、end

1.13 widget

1.13.1 TextViewKt

TextView监听便捷设置

textView.addTextChangedListener(onTextChanged = {
    
     text, start, before, count ->
	Log.i(TAG,"onTextChanged:$text")
})

还可以直接注册其某一个方法

textView.doBeforeTextChanged {
    
     text, start, count, after ->
   Log.i(TAG, "onBeforeTextChanged:$text")
}
textView.doOnTextChanged {
    
     text, start, before, count ->
   Log.i(TAG, "onTextChange:$text")
}
textView.doAfterTextChanged {
    
    
   Log.i(TAG, "onAfterTextChanged")
}

更多监听/回调的简化,详见我的另一篇文章 在Android中,简化冗长的监听/回调 写法

1.14 官方文档

附上官方文档链接 : Android KTX 官方文档

猜你喜欢

转载自blog.csdn.net/EthanCo/article/details/127227004