kotlin-android-extensions是kotlin为Android专门提供的扩展插件,虽然现在其提供的功能不多,但是光是替代findViewById功能,就已经值得使用了。至于以后官方是否会提供更多的功能,让Android开发更快速便捷,就只能拭目以待了
module:app -> build.gradle 添加以下代码
apply plugin: ‘kotlin-android-extensions’
import kotlinx.android.synthetic.main.activity_main.*
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
helloTv.text = "Hello Kotlin!"
}
}
我们不需要使用findViewById来获取控件,只需要使用控件的id就可以操作控件的相关方法。当然大家也发现了import,没错,这也是必须的,AndroidStudio会自动为你添加。如果你不嫌麻烦,手动写也是没毛病的。
import格式是这样的:kotlinx.android.synthetic.main.布局名称.*。需要注意的是include进来的布局,也是需要通过import导入相应布局,这样才能正常使用。
AndroidStudio中可以直接打开kotlin Bytecode,进行反编译查看编译后的代码。
Tools->Kotlin->Show Kotlin Bytecode->Decompile
查看编译后的代码,我们可以发现很有趣的东西。
...
private HashMap _$_findViewCache;
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
((TextView)this._$_findCachedViewById(id.helloTv)).setText((CharSequence)"Hello Kotlin!");
}
public View _$_findCachedViewById(int var1) {
if(this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));
if(var2 == null) {
var2 = this.findViewById(var1);
this._$_findViewCache.put(Integer.valueOf(var1), var2);
}
return var2;
}
public void _$_clearFindViewByIdCache() {
if(this._$_findViewCache != null) {
this._$_findViewCache.clear();
}
}
...
代码很简单,在第一次使用控件的时候,在缓存集合中进行查找,有就直接使用,没有就通过findViewById进行查找,并添加到缓存集合中。其还提供了_$_clearFindViewByIdCache()方法用于清除缓存,在我们想要彻底替换界面控件时可以使用到。
private HashMap _$_findViewCache;
...
public void onViewCreated(@Nullable View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((TextView)this._$_findCachedViewById(id.helloTv)).setText((CharSequence)"Hello Fragment By Kotlin!");
}
public View _$_findCachedViewById(int var1) {
if(this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));
if(var2 == null) {
View var10000 = this.getView();
if(var10000 == null) {
return null;
}
var2 = var10000.findViewById(var1);
this._$_findViewCache.put(Integer.valueOf(var1), var2);
}
return var2;
}
public void _$_clearFindViewByIdCache() {
if(this._$_findViewCache != null) {
this._$_findViewCache.clear();
}
}
// $FF: synthetic method
public void onDestroyView() {
super.onDestroyView();
this._$_clearFindViewByIdCache();
}
和Activity的唯一区别就是在onDestroyView()方法中调用了_$_clearFindViewByIdCache(),来清楚缓存,所以我们不用担心在View销毁的时候,缓存不能及时释放的问题。
到这里,我想大家肯定很清楚了,我们并没有完全的离开findViewById,只是kotlin的扩展插件利用缓存的方式让我们开发更方便、更快捷。
使用1.1.4版本的kotlin-android-extensions增强功能,需要在build.gradle中开启实验性标志:
androidExtensions {
experimental = true
}
接下来我们就可以试着去编写ViewHolder了,只需要实现LayoutContainer接口,该接口只提供了一个containerView,用于存储视图,具体作用看编译后源码:
import android.support.v7.widget.RecyclerView
import android.view.View
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.activity_main.*
class ViewHolder constructor(override val containerView: View?)
: RecyclerView.ViewHolder(containerView),
LayoutContainer {
fun setContent(str: String) {
helloTv.text = str
}
}
ViewHolder初始化的时候,将传进来的view存储在containerView变量中,和Activity的_$_findCachedViewById一样,ViewHolder中的使用的是containerView.findViewById,即通过传进来的View进行View.findViewById,从而获取控件。
默认View的缓存是是使用的HashMap来做的,官方提供了注解的方式来进行修改:
@ContainerOptions(CacheImplementation.SPARSE_ARRAY)
class TestActivity : AppCompatActivity() {
...
}
CacheImplementation提供了三种方式:
public enum class CacheImplementation {
SPARSE_ARRAY,
HASH_MAP,
NO_CACHE;
public val hasCache: Boolean
get() = this != NO_CACHE
companion object {
val DEFAULT = HASH_MAP
}
}
当然某些时候你只在Activity加载的时候,使用一次控件,那么就可以选择NO_CACHE
Parcelable 扩展
@Parcelize
class User(val firstName: String, val lastName: String) : Parcelable