文章目录
ViewGroup获取ChildView集合
fun ViewGroup.asSequence(): Sequence<View> = (0..childCount).asSequence().map { getChildAt(it) }
inline noinline crossinline比较
参考:https://blog.csdn.net/u013009899/article/details/78584994
Kotlin代码
fun outterFun() {
innerFun {
return//支持直接返回outterFun
return@innerFun 1 //如果要返回lambda,则必须有返回值
}
innerFun_ {
//return//不支持直接返回outterFun
return@innerFun_ 1 //如果要返回lambda,则必须有返回值
}
innerFun__ {
//return//不支持直接返回outterFun
return@innerFun__ 1 //如果要返回lambda,则必须有返回值
}
//以下lambada变换意义相同/总有一款你喜欢的
foo(fun() {}, { "" })
foo({}, { "" })
foo(fun() = Unit, { "" })
foo({}) { "" }//推荐
//方式一 外部变量
foo({ }, testNotInlined)
//方式二 局部变量
//如果是匿名或者具名函数,则支持
var f = fun(): String? { return "MaQi" }
foo({ }, f)
foo({ }, innerFun___no())
//方式三 函数传参
innerFun___(fun(reult: String?) {
//返回的Maqi将在该函数中被调用
}, { "Maqi" })
foo({ }, innerFun___({ reult -> }) { "Maqi" })
//转换
foo({}, innerFun___(fun(reult: String?) {
//返回的Maqi将在该函数中被调用
}, { "Maqi" }))
//测试 crossinline
val retsult = innerFun___c(fun(reult: String?): String? {
//返回的Maqi将在该函数中被调用
return reult
}, { "" })
}
//没有inline,函数不能外部返回,即innerFun不能直接return
fun innerFun__(a: () -> Int) {}
//让函数允许非局部返回(外部返回)
inline fun innerFun(a: () -> Int) {}
//inline crossinline需要同时存在
inline fun innerFun_(crossinline a: () -> Int) {}
//noinline 修饰 该函数只能作为参数传递,不能外部申明,inline noinline需要同时存在
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> String?) {}
//方式一
var testNotInlined = fun(): String? {
return ""
}
//方式二
fun innerFun___(): () -> String? {
return testNotInlined
}
//方式三
inline fun innerFun___(callback: (reult: String?) -> Unit, notInlined: () -> String?): () -> String? {
val string = notInlined()
callback(string)
return { string }
}
//可以发现 我们加上inlin后提示 noinline必须同时加上
//Can't inline 'notInlined' here: it may contain non-local returns. Add 'crossinline' modifier to parameter declaration 'notInlined'
//翻译以下大概意思是 函数当参数 有出现嵌套的情况下 我们必须让被套的那个不能提前return
//因为inline允许外部返回,即直接return,这样可能出现问题
inline fun innerFun___c(crossinline callback: (reult: String?) -> String?, crossinline notInlined: () -> String?): () -> String? {
return { callback(notInlined()) }
}
inline fun innerFun___no(): () -> String? {
//Local functions are not yet supported in inline functions
// return fun(): String? {
// return ""
// }
//如果是匿名或者具名函数,则支持
return {""}
}
结论
- inline 修饰fun ,使函数可非局部返回
- crossinline 和 noinline 限制非局部返回,都只能修饰函数参数
- crossinline 或noinline存在时,inline 必须存在
- noinline 修饰的函数参数 只能在内联函数内部调用或者作为可内联的参数传递
- 它们貌似只会在代码编辑的时候提示,反编译Java代码没有什么特别,都是另外申明一个静态类继承Lambda 和实现invoke函数
如下为:testNotInlined 代码反编译示例
import kotlin.Metadata;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.internal.Lambda;
import org.jetbrains.annotations.Nullable;
@Metadata(bv = {1, 0, 3}, d1 = {"\u0000\b\n\u0000\n\u0002\u0010\u000e\n\u0000\u0010\u0000\u001a\u0004\u0018\u00010\u0001H\n¢\u0006\u0002\b\u0002"}, d2 = {"<no name provided>", "", "invoke"}, k = 3, mv = {1, 1, 13})
/* compiled from: Demo.kt */
final class DemoKt$testNotInlined$1 extends Lambda implements Function0<String> {
public static final DemoKt$testNotInlined$1 INSTANCE = new DemoKt$testNotInlined$1();
DemoKt$testNotInlined$1() {
super(0);
}
@Nullable
public final String invoke() {
return "";
}
}
非局部返回:直接在lambda返回外部函数
Kotlin 简化 Parcelable
在build gradle中申明
androidExtensions {
experimental = true
}
@Parcelize 注解
@Parcelize
class Book(val title: String, val author: String, val year: Int) : Parcelable
参考Kotlin开发者:Parcelable, simplified
注意:文中指出存在兼容和继承的隐患,请谨慎使用
orEmpty()
String.kt 扩展函数
/** Returns the string if it is not `null`, or the empty string otherwise. */
@kotlin.internal.InlineOnly
public inline fun String?.orEmpty(): String = this ?: ""
当然还有很多很多骚操作,这里不一一列举。
kotlin 代理 关键字 by
@SuppressLint("ParcelCreator")
@Parcelize
data class TaskDetailArgs(val id: String) : Parcelable
private val args: TaskDetailArgs by args()
fun <V : Any> args() = object : ReadOnlyProperty<Fragment, V> {
var value: V? = null
override fun getValue(thisRef: Fragment, property: KProperty<*>): V {
if (value == null) {
val args = thisRef.arguments ?: throw IllegalArgumentException("There are no fragment arguments!")
val argUntyped = args.get(“KEY_ARG”)
argUntyped ?: throw IllegalArgumentException("arguments not found at key KEY_ARG!")
@Suppress("UNCHECKED_CAST")
value = argUntyped as V
}
return value ?: throw IllegalArgumentException("")
}
}
kotlin List find
data class User(val name: String)
val data: List<User> = emptyList()
data.find { it.name == "MqQi" }
//等价于
data.firstOrNull { it.name == "MqQi" }
TimingKt 获取执行时长
/**
* Executes the given [block] and returns elapsed time in milliseconds.
*/
public inline fun measureTimeMillis(block: () -> Unit): Long {
val start = System.currentTimeMillis()
block()
return System.currentTimeMillis() - start
}
使用
val time = measureTimeMillis {}
Kotlin List 操作符重载
Collection.kt 扩展函数
/**
* Returns a list containing all elements of the original collection and then the given [element].
*/
public operator fun <T> Collection<T>.plus(element: T): List<T> {
val result = ArrayList<T>(size + 1)
result.addAll(this)
result.add(element)
return result
}
val list = listOf<String>() + "MQ"
repeat 重复执行
repeat(100) {
Log.i("repeat", "repeat:$it")
}
startForegroundService
@SuppressLint("NewApi")
fun Service.setForegroundIfNecessary() {
val exitIntent = Intent(this, ExitBroadcastReceiver::class.java).apply {
action = "ACTION_TO_BACKGROUND"
}
val exitPendingIntent = PendingIntent.getBroadcast(this, 0, exitIntent, 0)
val builder = NotificationCompat.Builder(this, "CHANNEL_NODE")
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.background_connection_enabled))
.setPriority(NotificationCompat.PRIORITY_MIN)
.setWhen(0)
.setDefaults(0)
.setSound(null)
.setDefaults(0)
.setOnlyAlertOnce(true)
.setColor(ContextCompat.getColor(this, R.color.gray_light))
.setSmallIcon(R.drawable.ic_msg_default)
.addAction(R.drawable.ic_close_black_24dp, getString(R.string.exit), exitPendingIntent)
val pendingIntent = PendingIntent.getActivity(
this, 0,
MainActivity.getSingleIntent(this), 0
)
builder.setContentIntent(pendingIntent)
supportsOreo {
val channel = NotificationChannel(
"CHANNEL_NODE",
"Message_Node", NotificationManager.IMPORTANCE_LOW
)
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
channel.setSound(null, null)
channel.setShowBadge(false)
notificationManager.createNotificationChannel(channel)
}
startForeground(66666, builder.build())
}
inline fun supportsOreo(code: () -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
code()
}
}
class ExitBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
}
}
companion object {
fun startService(ctx: Context, action: String? = null) {
val intent = Intent(ctx, MessageService::class.java).apply {
this.action = action
}
ContextCompat.startForegroundService(ctx, intent)
}
fun stopService(ctx: Context) {
val intent = Intent(ctx, MessageService::class.java)
ctx.stopService(intent)
}
}
companion object {
fun getSingleIntent(context: Context): Intent {
return Intent(context, MainActivity::class.java).apply {
addCategory(Intent.CATEGORY_LAUNCHER)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
}
}
}
vararg 关键字
fun addPlayer(game: Game, vararg players: Player):Deferred<List<PlayerStatus>>{
players.forEach { player ->
}
}
To be continue…