Kotlin for Android - 0x01 有趣的扩展

在 Kotlin 中, 提供了一个很方便的功能,可以在不继承父类,也不使用类似装饰器这样的设计模式的情况下对指定类进行扩展,扩展新的方法、属性。

扩展方法

用法:类名.方法名

例子

1
2
3
4
fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}

然后 Context 及其子类 都可以使用 toast 方法了,duration 是默认参数,不传值的话默认为 Toast.LENGTH_SHORT

1
2
3
toast("Hello world!")
toast("Hello world!", Toast.LENGTH_LONG)

给一个类扩展方法并 不会修改原来的类 ,Kotlin 只不过让类的实例可以通过 . 来调用这个方法
这个方法是 静态添加上的,并不会在运行时改变。什么意思呢,看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
open class C
class D: C()

fun C.foo() = "c"
fun D.foo() = "d"

fun printFoo(c: C) {
println(c.foo()) //这里调用的是C类的foo()
}

printFoo(D()) // 打印出 c

我们声明了参数类型为 C ,那么 printFoo 方法内直接调用的就是 C 类的 **foo()**。而 D() 是具体运行时传入的,扩展函数内调用的还是 C 的方法。

当定义的扩展方法这个类已经存在了同名的扩展方法,这时候是怎么运行的呢? 看下面的例子:

1
2
3
4
5
class C {
fun foo() { println("member") }
}

fun C.foo() { println("extension") }

当我们调用 c.foo() , 将会输出 “member”, 而不是 “extension”, 很明显,类内部定义的方法优先

扩展属性

用法:类名.属性名

例如

1
2
val View.ctx: Context
get() = context

这样 View及其子类 都拥有了 ctx属性。

Kotlin for Android 常用的扩展

下面总结一些 Android 中比较常用的扩展。注意是对哪些类进行的扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

// 调用 toast 方法
fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}

// 获取颜色
fun Context.color(res: Int): Int = ContextCompat.getColor(this, res) // 注意 getResource().getColor 已经不建议使用了

// 获取 LayoutInflater
fun Context.layoutInflater() = LayoutInflater.from(this)

fun Context.isConnected(): Boolean {
val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return manager.activeNetworkInfo?.isConnectedOrConnecting ?: true
}

// 网络错误
fun Activity.noNetworkSnackBar(parentView: View, retryListener: () -> Unit) {
Snackbar.make(parentView, R.string.network_issue, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.try_again) {
retryListener.invoke()
}.show()
}



fun Int.dpToPx(context: Context) = this * context.resources.displayMetrics.density


fun RecyclerView.Adapter<ViewHolder>.createHolder(view: ViewGroup) = object : RecyclerView.ViewHolder(view) {}
fun <T : View> RecyclerView.Adapter<ViewHolder>.getView(holder: ViewHolder) = holder.itemView as T

// View 可见性
fun View.setVisible() {
this.visibility = View.VISIBLE
}

fun View.setInvisible() {
this.visibility = View.INVISIBLE
}

fun View.setGone() {
this.visibility = View.GONE
}

fun View.toggle(isVisible: Boolean) {
if (isVisible) setVisible() else setGone()
}

fun View.setSize(width: Int, height: Int) {
if (width <= 0 && height <= 0) return

val layoutParams = when (this.layoutParams) {
is LinearLayout.LayoutParams -> this.layoutParams as LinearLayout.LayoutParams
is FrameLayout.LayoutParams -> this.layoutParams as FrameLayout.LayoutParams
is RelativeLayout.LayoutParams -> this.layoutParams as RelativeLayout.LayoutParams
else -> this.layoutParams
}
val ratio = height / width
layoutParams.height = layoutParams.width * ratio
this.layoutParams = layoutParams
}

// 弹出snackbar
fun View.snackbar(message: String, duration: Int = Snackbar.LENGTH_SHORT) {
Snackbar.make(this,message,duration).show()
}

fun View.snackbar(messageRes: Int, duration: Int = Snackbar.LENGTH_SHORT) {
Snackbar.make(this,messageRes,duration).show()
}

// 任意类打log
fun Any.log(message: String) {
Log.e(this.javaClass.simpleName, message)
}



fun Context.getActivityManager() = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
fun Context.getAlarmManager() = getSystemService(Context.ALARM_SERVICE) as AlarmManager
fun Context.getAudioManager() = getSystemService(Context.AUDIO_SERVICE) as AudioManager
fun Context.getClipboardManager() = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
fun Context.getConnectivityManager() = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
fun Context.getKeyguardManager() = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
fun Context.getLayoutInflater() = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
fun Context.getLocationManager() = getSystemService(Context.LOCATION_SERVICE) as LocationManager
fun Context.getNotificationManager() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
fun Context.getPowerManager() = getSystemService(Context.POWER_SERVICE) as PowerManager
fun Context.getSearchManager() = getSystemService(Context.SEARCH_SERVICE) as SearchManager
fun Context.getSensorManager() = getSystemService(Context.SENSOR_SERVICE) as SensorManager
fun Context.getTelephonyManager() = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
fun Context.getVibrator() = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
fun Context.getWallpaperService() = getSystemService(Context.WALLPAPER_SERVICE) as WallpaperService
fun Context.getWifiManager() = getSystemService(Context.WIFI_SERVICE) as WifiManager
fun Context.getWindowManager() = getSystemService(Context.WINDOW_SERVICE) as WindowManager
fun Context.getInputMethodManager() = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
fun Context.getAccessibilityManager() = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
fun Context.getAccountManager() = getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
fun Context.getDevicePolicyManager() = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
fun Context.getDropBoxManager() = getSystemService(Context.DROPBOX_SERVICE) as DropBoxManager
fun Context.getUiModeManager() = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
fun Context.getDownloadManager() = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
fun Context.getStorageManager() = getSystemService(Context.STORAGE_SERVICE) as StorageManager
fun Context.getNfcManager() = getSystemService(Context.NFC_SERVICE) as NfcManager
fun Context.getUsbManager() = getSystemService(Context.USB_SERVICE) as UsbManager
fun Context.getTextServicesManager() = getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE) as TextServicesManager
fun Context.getWifiP2pManager() = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
fun Context.getInputManager() = getSystemService(Context.INPUT_SERVICE) as InputManager
fun Context.getMediaRouter() = getSystemService(Context.MEDIA_ROUTER_SERVICE) as MediaRouter
fun Context.getNsdManager() = getSystemService(Context.NSD_SERVICE) as NsdManager
fun Context.getDisplayManager() = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
fun Context.getUserManager() = getSystemService(Context.USER_SERVICE) as UserManager
fun Context.getBluetoothManager() = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
fun Context.getAppOpsManager() = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
fun Context.getCaptioningManager() = getSystemService(Context.CAPTIONING_SERVICE) as CaptioningManager
fun Context.getConsumerIrManager() = getSystemService(Context.CONSUMER_IR_SERVICE) as ConsumerIrManager
fun Context.getPrintManager() = getSystemService(Context.PRINT_SERVICE) as PrintManager
fun Context.getAppWidgetManager() = getSystemService(Context.APPWIDGET_SERVICE) as AppWidgetManager
fun Context.getBatteryManager() = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
fun Context.getCameraManager() = getSystemService(Context.CAMERA_SERVICE) as CameraManager
fun Context.getJobScheduler() = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
fun Context.getLauncherApps() = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
fun Context.getMediaProjectionManager() = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
fun Context.getMediaSessionManager() = getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager
fun Context.getRestrictionsManager() = getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager
fun Context.getTelecomManager() = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
fun Context.getTvInputManager() = getSystemService(Context.TV_INPUT_SERVICE) as TvInputManager
fun Context.getSubscriptionManager() = getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
fun Context.getUsageStatsManager() = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
fun Context.getCarrierConfigManager() = getSystemService(Context.CARRIER_CONFIG_SERVICE) as CarrierConfigManager
fun Context.getFingerprintManager() = getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
fun Context.getMidiManager() = getSystemService(Context.MIDI_SERVICE) as MidiManager
fun Context.getNetworkStatsManager() = getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager



// 扩展属性


val View.ctx: Context
get() = context

var TextView.textColor: Int
get() = currentTextColor
set(v) = setTextColor(v)

inline fun Notification.build(context: Context, func: NotificationCompat.Builder.() -> Unit): Notification {
val builder = NotificationCompat.Builder(context)
builder.func()
return builder.build()
}

其他资源

更多详细用法,查看官网文档
Kotlin 资源汇总

文章来自: https://hanks.pub