不错
https://www.jianshu.com/p/5f77209abb9b
https://www.jianshu.com/p/cf9d068d4b6c
Kotlin+RxJava+Android Architecture Components
1.Kotlin优缺点
2.Kotlin基本变量,方法,类
https://www.jianshu.com/p/cf9d068d4b6c
https://blog.csdn.net/carson_ho/article/details/96965702
1.Kotlin跟Java比,kotlin具有哪些优势?
Kotlin语言简练,而且Kotlin里面可以没有空指针问题,在Android中使用Java就会存在很多令人头大的空指针问题。
2.当你项目中同时使用Kotlin和Java,你是如何保证空指针问题的?
首先,Kotlin本身就不存在空指针问题,而如果你在Kotlin中去调用Java某个类的方法的时候,这个方法最好使用注解的方式来避免返回空指针。
1.Kotlin是什么?
1.Kotlin是一种基于JVM的编程语言。
2.实际上它是对Java的一种扩展。
3.Kotlin支持函数式编程。
4.Kotlin类和Java类的互相调用。
Kotlin允许开发者在不改变已有类的情况下,为某个类添加新的函数。这个特性叫做扩展函数。
举一个简单的例子。如果要关闭一个I/O流,使用Java可能是写一个工具方法。
/** * 安全关闭io流 * @param closeable */ public static void closeQuietly(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (IOException e) { e.printStackTrace(); } } }
对Kotlin而言,可以对Closeable扩展一个函数closeQuietly()。
fun Closeable?.closeQuietly() { try { this?.close() } catch (e: Throwable) { } }
之后,任何实现了Closeable接口的类,都可以使用它本身的closeQuietly()方法来关闭流。我们不再需要那个工具方法了。
fun loge(tag: String, content: String?) {
Log.e(tag, content ?: tag)
}
调用的时候直接使用loge(TAG, "content")
在项目中,我们使用扩展函数对Glide做了封装,大大简化了Glide的使用。
/** * 占位符矩形 */ fun ImageView.load(url: String) { get(url).placeholder(R.drawable.shape_default_rec_bg) .error(R.drawable.shape_default_rec_bg) .into(this) } /** * 占位符圆角矩形 */ fun ImageView.loadRound(url: String) { get(url).placeholder(R.drawable.shape_default_round_bg) .error(R.drawable.shape_default_round_bg) // .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0))) .transform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0)) .into(this) } /** * 占位符圆形 */ fun ImageView.loadCircle(url:Drawable) { get(url).placeholder(R.drawable.shape_default_circle_bg) .error(R.drawable.shape_default_circle_bg) .into(this) } fun ImageView.loadCircle(url: String) { get(url).placeholder(R.drawable.shape_default_circle_bg) .error(R.drawable.shape_default_circle_bg) .into(this) } fun ImageView.get(url: String): GlideRequest= GlideApp.with(context).load(url) fun ImageView.get(url: Drawable): GlideRequest = GlideApp.with(context).load(url)
fun Context.toast(str: String) = Toast.makeText(this, str, Toast.LENGTH_LONG).show() // 当我们需要toast的时候,我们可以这样调用 context.toast("test")
T.run、T.let、T.also、T.apply 以及run、width两个函数。对于这几个函数的使用刚开始的时候我还是很懵逼的,只是大概了解用法,以及带来的链式调用的便捷
一开始我并不了解这个概念。偶然间我看到我们的小伙伴在使用RxBus时,写下了这样的代码:
RxBus.get().register(LogoutEvent::class.java) { refresh() }
当时我感觉很疑惑,因为RxBus是我写的,记得没有提供这样的方法啊。点击register()方法进去看之后,发现register是这样的:
public Disposable register(Class eventType, Consumer onNext) {
return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext);
}
由于register()最后一个参数是一个方法或者说是一个闭包,可以把方法或者闭包提到最外面。变成项目中看到的样子
RxBus.get().register(LogoutEvent::class.java) { refresh() }
这就是尾随闭包,可以让代码看起来更加简洁。
with是将某个对象作为函数的参数,在函数块内可以通过 this 指代该对象。在函数块内可以直接调用对象的方法或者属性。
/** * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. */ @kotlin.internal.InlineOnly public inline funwith(receiver: T, block: T.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return receiver.block() }
class AppPublisherAdapter : BaseAdapter() { override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int,content: BoundAppInfoResponse.AppInfo) { holder.itemView.tv_game_name.text = content.name if (content.is_bound) { holder.itemView.tv_bound_user_name.text = content.bound_user_name holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bound_user_name)) } else { holder.itemView.tv_bound_user_name.text = context.getString(R.string.bind_on_account) holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bind_on_account)) } holder.itemView.iv_game_icon.load(content.logo_url) } }
使用with之后,该函数块可以省略"content."
class AppPublisherAdapter : BaseAdapter() { override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int, content: BoundAppInfoResponse.AppInfo) { with(content) { holder.itemView.tv_game_name.text = name if (is_bound) { holder.itemView.tv_bound_user_name.text = bound_user_name holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bound_user_name)) } else { holder.itemView.tv_bound_user_name.text = context.string(R.string.bind_on_account) holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bind_on_account)) } holder.itemView.iv_game_icon.load(logo_url) } } }
kotlin-android-extensions
相当于DataBinding,同样的目的为了偷懒不用写findViewByIdAndroid 开发必备。
如果使用了kotlin-android-extensions,不使用findviewfindid操作一定要在对应的kotlin文件里导入:
inline(内联)、infix(中缀)、高阶函数