亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Kotlin如何直接使用控件ID原理詳析

2024-07-21 23:03:51
字體:
來源:轉載
供稿:網友

前言

最近斷斷續續地把項目的界面部分的代碼由JAva改成了Kotlin編寫,并且如果應用了kotlin-android-extensions插件,一個顯而易見的好處是再也不用寫 findViewById()來實例化你的控件對象了,直接操作你在布局文件里的id即可,這一點我感覺比butterknife做的還簡潔友好。

Activity

import android.support.v7.app.AppCompatActivityimport android.os.Bundleimport kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {  super.onCreate(savedInstanceState)  setContentView(R.layout.activity_main)  textview.text="hello world" }}

其中kotlinx.android.synthetic.main.activity_main.*是kotlin-android-extensions插件自動生成的。下面我們來解析下原理。因為kotlin也是一門JVM語言,最近也會和java一樣編譯成class字節碼,所以我們直接來反編譯看看生成的java文件。

Kotlin,控件ID

選擇Decompile,解析出來的代碼如下

public final class MainActivity extends AppCompatActivity { private HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  this.setContentView(2131296284);  TextView var10000 = (TextView)this._$_findCachedViewById(id.textview);  Intrinsics.checkExpressionValueIsNotNull(var10000, "textview");  var10000.setText((CharSequence)"hello world"); } public View _$_findCachedViewById(int var1) {  if (this._$_findViewCache == null) {   this._$_findViewCache = new HashMap();  }  View var2 = (View)this._$_findViewCache.get(var1);  if (var2 == null) {   var2 = this.findViewById(var1);   this._$_findViewCache.put(var1, var2);  }  return var2; } public void _$_clearFindViewByIdCache() {  if (this._$_findViewCache != null) {   this._$_findViewCache.clear();  } }}

可以很清楚看到最終還是調用了findViewById() ,不過獲取View對象直接調用的是findCachedViewById,并且創建一個 HashMap 進行View對象的緩存,避免每次調用 View 時都會重新調用findViewById()進行查找。

Fragment

再來看下Fragment中的使用:

import android.os.Bundleimport android.support.v4.app.Fragmentimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport kotlinx.android.synthetic.main.fragment_blank.*class BlankFragment : Fragment() {  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {    return inflater.inflate(R.layout.fragment_blank, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) {  super.onViewCreated(view, savedInstanceState)  textview_fra.text="hello world" }}

反編譯后代碼如下

public final class BlankFragment extends Fragment { private HashMap _$_findViewCache; @Nullable public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  Intrinsics.checkParameterIsNotNull(inflater, "inflater");  return inflater.inflate(2131296285, container, false); } public void onViewCreated(@NotNull View view, @Nullable Bundle savedInstanceState) {  Intrinsics.checkParameterIsNotNull(view, "view");  super.onViewCreated(view, savedInstanceState);  TextView var10000 = (TextView)this._$_findCachedViewById(id.textview_fra);  Intrinsics.checkExpressionValueIsNotNull(var10000, "textview_fra");  var10000.setText((CharSequence)"hello world"); } public View _$_findCachedViewById(int var1) {  if (this._$_findViewCache == null) {   this._$_findViewCache = new HashMap();  }  View var2 = (View)this._$_findViewCache.get(var1);  if (var2 == null) {   View var10000 = this.getView();   if (var10000 == null) {   return null;   }   var2 = var10000.findViewById(var1);   this._$_findViewCache.put(var1, var2);  }  return var2; } public void _$_clearFindViewByIdCache() {  if (this._$_findViewCache != null) {   this._$_findViewCache.clear();  } } // $FF: synthetic method public void onDestroyView() {  super.onDestroyView();  this._$_clearFindViewByIdCache(); }}

可以看到最終是通過調用getView().findViewById()來進行控件的實例化。

看下getView()源碼

 @Nullable public View getView() {  return this.mView; }

再看下mView成員變量的賦值時機:

 void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  if (this.mChildFragmentManager != null) {   this.mChildFragmentManager.noteStateNotSaved();  }  this.mPerformedCreateView = true;  this.mViewLifecycleOwner = new LifecycleOwner() {   public Lifecycle getLifecycle() {    if (Fragment.this.mViewLifecycleRegistry == null) {     Fragment.this.mViewLifecycleRegistry = new LifecycleRegistry(Fragment.this.mViewLifecycleOwner);    }    return Fragment.this.mViewLifecycleRegistry;   }  };  this.mViewLifecycleRegistry = null;  this.mView = this.onCreateView(inflater, container, savedInstanceState);  if (this.mView != null) {   this.mViewLifecycleOwner.getLifecycle();   this.mViewLifecycleOwnerLiveData.setValue(this.mViewLifecycleOwner);  } else {   if (this.mViewLifecycleRegistry != null) {    throw new IllegalStateException("Called getViewLifecycleOwner() but onCreateView() returned null");   }   this.mViewLifecycleOwner = null;  } }

可以看到mView其實就是onCreateView()的返回值,所以我們不能在onCreateView()方法里操作控件ID的方式操作View對象,會產生空指針異常。建議在onViewCreated()方法里使用。

其他(動態布局)

除了Activity和Fragment,我們用的最多的UI布局當屬Adapter了,kotlin-android-extensions也提供了對這一類動態布局的支持。因為這一功能是實現性質的,默認關閉,我們需要手動打開,在build.gradle中開啟:

androidExtensions { experimental = true}

然后再recycler.adapter中使用如下:

import kotlinx.android.extensions.LayoutContainerimport kotlinx.android.synthetic.main.item_recyclerview.*class MyAdapter(val context: Context, val data: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {  val view = LayoutInflater.from(context).inflate(R.layout.item_recyclerview, parent, false)  return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) {  holder.name_tv.text = data[position]  holder.itemView.setOnClickListener {   Toast.makeText(context,"點擊了第$position 項",Toast.LENGTH_SHORT).show()  } } override fun getItemCount(): Int {  return data.size } inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), LayoutContainer {  override val containerView: View = itemView }}

可以看到相比Activity和Fragment,我們的ViewHolder需要多實現一個接口LayoutContainer??聪滤脑创a:

 public final class ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder implements LayoutContainer {  @NotNull  private final View containerView;  private HashMap _$_findViewCache;  @NotNull  public View getContainerView() {   return this.containerView;  }  public ViewHolder(@NotNull View itemView) {   Intrinsics.checkParameterIsNotNull(itemView, "itemView");   super(itemView);   this.containerView = itemView;  }  public View _$_findCachedViewById(int var1) {   if (this._$_findViewCache == null) {   this._$_findViewCache = new HashMap();   }   View var2 = (View)this._$_findViewCache.get(var1);   if (var2 == null) {   View var10000 = this.getContainerView();   if (var10000 == null) {    return null;   }   var2 = var10000.findViewById(var1);   this._$_findViewCache.put(var1, var2);   }   return var2;  }  public void _$_clearFindViewByIdCache() {   if (this._$_findViewCache != null) {   this._$_findViewCache.clear();   }  } }

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美xxxx18国产| 亚洲精品美女网站| 亚洲精品在线视频| 日韩欧美一区二区在线| 亚洲精品一区二区久| 最近2019中文字幕mv免费看| 国产美女久久精品香蕉69| 亚洲精品一区av在线播放| 精品欧美国产一区二区三区| 亚洲欧洲在线观看| 国产一区二区日韩| 动漫精品一区二区| 国产精品亚洲综合天堂夜夜| 欧美成人激情视频免费观看| 中文字幕视频一区二区在线有码| 中文字幕日韩在线播放| 亚洲女人天堂成人av在线| 精品国偷自产在线| 国产免费一区二区三区在线观看| 久久久av免费| 精品久久久一区二区| 成人写真视频福利网| 国产精品欧美亚洲777777| 欧美亚洲视频在线观看| 伊人久久五月天| 91亚洲国产成人精品性色| 国产97在线|亚洲| 亚洲一品av免费观看| 亚洲www视频| 欧美国产中文字幕| 欧美日本黄视频| 亚洲人成电影在线播放| 久久久久成人精品| 91久久精品美女高潮| 欧美高跟鞋交xxxxxhd| 国产精品美女主播在线观看纯欲| 91精品国产91| 久久久久在线观看| 日韩美女在线播放| 亚洲精品www久久久| 欧美在线精品免播放器视频| 色综合久久久久久中文网| 国内免费久久久久久久久久久| 九九热在线精品视频| 久久久精品一区二区| 亚洲欧美在线一区二区| 亚洲欧洲日产国产网站| 国产亚洲福利一区| 欧美综合激情网| 色与欲影视天天看综合网| 91网站免费观看| 欧美电影免费播放| 亚洲3p在线观看| 55夜色66夜色国产精品视频| 国产午夜精品麻豆| 日韩欧美在线视频日韩欧美在线视频| 久久在线精品视频| 欧美成人在线免费| 国产亚洲精品高潮| 国产精品久久久久久久久久小说| 亚洲精品网站在线播放gif| 疯狂做受xxxx欧美肥白少妇| 日韩欧美在线看| 中文综合在线观看| 亚洲一区二区福利| 欧美日韩国产页| 岛国av一区二区三区| 色噜噜久久综合伊人一本| 久久久在线视频| 中文字幕欧美视频在线| 91视频国产一区| 国产精品老牛影院在线观看| 中文字幕久热精品视频在线| 国产精品网站视频| 亚洲国产精品高清久久久| 亚洲最大成人免费视频| 久久艹在线视频| 亚洲自拍小视频免费观看| 日韩亚洲成人av在线| 精品久久久av| 黑人狂躁日本妞一区二区三区| 一区二区日韩精品| 欧美超级免费视 在线| 久久中文字幕国产| 日本午夜人人精品| 亚洲视频在线免费观看| 亚洲欧美国产一区二区三区| 久久影视电视剧免费网站清宫辞电视| 欧美精品在线极品| 欧美成aaa人片免费看| 日韩美女视频免费在线观看| 成人国产精品一区二区| 97视频在线播放| 7777精品久久久久久| 91精品久久久久久久久久入口| 91美女福利视频高清| 日韩av电影手机在线| 在线观看欧美www| 57pao精品| xvideos亚洲人网站| 欧美做受高潮1| 亚洲欧美日韩在线高清直播| 久久久久久久久久久免费精品| 国产精品亚洲自拍| 欧美国产欧美亚洲国产日韩mv天天看完整| 日韩欧美在线第一页| 精品久久久国产| 国产成人精品午夜| 成人免费在线视频网址| 日本成熟性欧美| 97在线视频一区| 日韩av在线高清| 久久人人爽人人| 精品久久中文字幕| 一本色道久久综合狠狠躁篇的优点| 欧美www在线| 91国语精品自产拍在线观看性色| 亚洲欧美三级伦理| 国产精品美女在线观看| 国产精品福利久久久| 91九色单男在线观看| 亚洲国产成人久久综合| 欧美人在线观看| 国产欧美久久一区二区| 国产精品精品一区二区三区午夜版| 尤物99国产成人精品视频| 国产亚洲精品91在线| 日韩精品在线免费播放| 欧美激情乱人伦| 国产亚洲成精品久久| 久久久999精品免费| 欧美成aaa人片在线观看蜜臀| 日韩亚洲精品视频| 热99精品里视频精品| 亚洲国产精品资源| 丝袜亚洲另类欧美重口| 亚洲美女性生活视频| 日本高清+成人网在线观看| 国产精品久久久久久久久久ktv| 亚洲午夜精品久久久久久久久久久久| 日韩av片永久免费网站| 欧美激情视频在线免费观看 欧美视频免费一| 久久夜色精品亚洲噜噜国产mv| 亚洲精品永久免费| 日韩av一区二区在线观看| 日韩高清电影好看的电视剧电影| 国产精品极品尤物在线观看| 亚洲天堂av电影| 国产成人精品999| 国产一区二区三区在线观看视频| 欧美另类99xxxxx| 久久久亚洲福利精品午夜| 久久久久久久999精品视频| 日韩中文视频免费在线观看| 亚洲性av在线| 怡红院精品视频| 日韩日本欧美亚洲| 成人免费视频网址| 精品视频久久久久久| 精品高清美女精品国产区| 亚洲自拍偷拍网址| 国产精品亚洲视频在线观看| 亚洲欧美日本另类| 欧美一区二区视频97|