10 个对 Android 开发者有用的 Kotlin 扩展函数 #2
通过出色的 Kotlin 扩展提高您的工作效率
EditText
通过EditText的“text”属性,您可以快速获取EditText中的文本。但是,这个文本是“可编辑”的,因此每次都需要将其转换为字符串才能获得EditText的准确值。但好消息是,您可以使用下面列出的扩展属性轻松获取EditText的值。
import android.widget.EditText
val EditText.value
get() = text?.toString() ?: ""
用法
val name = etName.value
startActivity
Start Activity 是转换到另一个 Activity 的常用方法。您必须首先解决目标活动的意图。但是,通过使用此扩展功能,您可以消除意图创建部分。
您还可以自定义传递一些数据和其他内容的意图。如果需要,它还可以终止当前的呼叫活动。看看下面的例子。
import android.app.Activity
import android.content.Intent
fun Activity.startActivity(
cls: Class<*>,
finishCallingActivity: Boolean = true,
block: (Intent.() -> Unit)? = null
) {
val intent = Intent(this, cls)
block?.invoke(intent)
startActivity(intent)
if (finishCallingActivity) finish()
}
用法
startActivity(MainActivity::class.java) // Without Intent modification
startActivity(MainActivity::class.java) {
// You can access the intent object in this block
putExtra("key", "value")
}
Check Network
如今,根据我们的要求、特性和功能,我们所有的应用程序都具有互联网连接。因此,您可能需要检查互联网连接是否可用。
因此,此扩展功能对于检查活动和片段中的互联网连接很有用。它很容易在 if 语句和范围内的其他位置使用。
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import androidx.fragment.app.Fragment
fun Context.isNetworkAvailable(): Boolean {
val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val capabilities = manager.getNetworkCapabilities(manager.activeNetwork)
return if (capabilities != null) {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
} else false
}
fun Fragment.isNetworkAvailable() = requireContext().isNetworkAvailable()
用法
if (isNetworkAvailable()) {
// Called when network is available
} else {
// Called when network not available
}
Check Permission
为了完成我们的用例,您有时可能需要获得任何许可才能玩游戏。因此,我们可能必须验证是否为我们的应用程序授予了权限。因此,下面的扩展函数对于确定是否已授予权限很有用。
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
fun Context.isPermissionGranted(permission: String) = run {
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
用法
if (isPermissionGranted(Manifest.permission.ACCESS_FINE_LOCATION)) {
// Block runs if permission is granted
} else {
// Ask for permission
}
用法
if (isPermissionGranted(Manifest.permission.ACCESS_FINE_LOCATION)) {
// Block runs if permission is granted
} else {
// Ask for permission
}
delete whitespaces
有时我们可能会从 Rest API 或其他一些数据源获得不切实际的文本数据。所以,如果你有多个空格并且你想删除它,那么我们可以使用removeDuplicateWhitespaces()
,或者如果你想完全删除它,那么你可以使用removeAllWhitespaces()
扩展函数。
fun String.removeAllWhitespaces(): String {
return this.replace("\\s+".toRegex(), "")
}
fun String.removeDuplicateWhitespaces(): String {
return this.replace("\\s+".toRegex(), " ")
}
用法
"Hello, world!!!".removeAllWhitespaces() // Output: Hello,world!!!
"Hello, world!!!".removeDuplicateWhitespaces() // Output: Hello, world!!!
toEditable()
可编辑是文本的界面,其内容和标记可以更改。如果你想将字符串转换为可编辑的,那么你必须处理一个可编辑的工厂实例。
现在,使用以下功能,您可以轻松删除样板代码。您可以在任何字符串函数中使用 toEditable()。并且,您可以使用它将文本分配给 EditText 字段。
import android.text.Editable
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
用法
etName.text = "First name".toEditable()
Screen Size
如果您正在处理基于某些状态或数据的动态视图布局,则可能需要使用设备屏幕尺寸。因此,将为此使用此扩展属性。它会给出设备的高度和宽度。您可以在活动范围内使用它或在其他地方使用上下文对象。
import android.content.Context
import android.graphics.Insets
import android.graphics.Rect
import android.os.Build
import android.util.DisplayMetrics
import android.util.Size
import android.view.WindowInsets
import android.view.WindowManager
val Context.screenSize: Size
get() {
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val size = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val metrics = windowManager.currentWindowMetrics
val windowInsets = metrics.windowInsets
val insets: Insets = windowInsets.getInsetsIgnoringVisibility(
WindowInsets.Type.navigationBars()
or WindowInsets.Type.displayCutout()
)
val insetsWidth: Int = insets.right + insets.left
val insetsHeight: Int = insets.top + insets.bottom
val bounds: Rect = metrics.bounds
Size(
bounds.width() - insetsWidth,
bounds.height() - insetsHeight
)
} else {
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay?.getMetrics(displayMetrics)
val height = displayMetrics.heightPixels
val width = displayMetrics.widthPixels
Size(width, height)
}
return size
}
用法
val size = screenSize
val deviceHeight = size.height
val deviceWidth = size.width
System Service Managers
这些属性用于直接访问system manager而无需创建它的对象。您可以直接在活动中使用它,对于必须使用上下文的片段。请注意,下面列出的属性并非全部。但如果需要更多,您可以添加更多。
import android.app.DownloadManager
import android.app.NotificationManager
import android.content.Context
import android.net.ConnectivityManager
import android.view.WindowManager
import androidx.core.content.ContextCompat
val Context.windowManager
get() = ContextCompat.getSystemService(this, WindowManager::class.java)
val Context.connectivityManager
get() = ContextCompat.getSystemService(this, ConnectivityManager::class.java)
val Context.notificationManager
get() = ContextCompat.getSystemService(this, NotificationManager::class.java)
val Context.downloadManager
get() = ContextCompat.getSystemService(this, DownloadManager::class.java)
用法
val manager = downloadManager // In Activity
val manager = requireContext().downloadManager// In Fragment
Copy to clipboard
您可能偶尔需要将文本复制到剪贴板,以允许用户与其他应用共享文本。因此,您可以在字符串对象上使用下面列出的扩展属性,一切顺利。
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import androidx.core.content.ContextCompat
fun String.copyToClipboard(context: Context) {
val clipboardManager = ContextCompat.getSystemService(context, ClipboardManager::class.java)
val clip = ClipData.newPlainText("clipboard", this)
clipboardManager?.setPrimaryClip(clip)
}
用法
"This is clipboard".copyToClipboard(context)
Boolean Expressions
布尔值,是每个程序员的必备需求。在您的编程生活中,您每天都必须使用布尔值。在 kotlin 中,您可能必须同时处理可空性和布尔值,在这种情况下您可以利用这些扩展。在这里,我们也使用了合约的概念来实现智能铸造。
@file:OptIn(ExperimentalContracts::class)
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
fun Boolean?.isTrue(): Boolean {
contract {
returns(true) implies (this@isTrue != null)
}
return this == true
}
fun Boolean?.isFalse(): Boolean {
contract {
returns(true) implies (this@isFalse != null)
}
return this == false
}
val Boolean?.orTrue: Boolean
get() = this ?: true
val Boolean?.orFalse: Boolean
get() = this ?: false
用法
lateinit var any: Boolean? // Assume that, this property is already assigned
if (any.isTrue()) {
// Run when any is true only
}
if (any.isFalse()) {
// Run when any is false only
}
val any1: Boolean = any.orTrue // If any is null then any1 = true otherwise any1 = any
val any2: Boolean = any.orFalse // If any is null then any1 = false otherwise any1 = any
结论
在这篇博文中,我们探索了适用于 Android 开发人员的 Kotlin 扩展功能。这些扩展可以简化常见任务,例如处理字符串、处理日期和时间、管理网络等。它们可以节省时间和精力、减少错误并提高代码的整体质量。