Kotlin直接使用控件ID原理解析

栏目: IOS · Android · 发布时间: 5年前

内容简介:最近断断续续地把项目的界面部分的代码由JAva改成了Kotlin编写,并且如果应用了下面我们来解析下原理。因为kotlin也是一门JVM语言,最近也会和java一样编译成class字节码,所以我们直接来反编译看看生成的java文件。选择

最近断断续续地把项目的界面部分的代码由 JAva 改成了Kotlin编写,并且如果应用了 kotlin-android-extensions 插件,一个显而易见的好处是再也不用写 findViewById() 来实例化你的控件对象了,直接操作你在布局文件里的id即可,这一点我感觉比 butterknife 做的还简洁友好。

Activity

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import 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"
    }
}

复制代码

下面我们来解析下原理。因为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.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import 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() 方法里使用。


以上所述就是小编给大家介绍的《Kotlin直接使用控件ID原理解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails, Third Edition

Agile Web Development with Rails, Third Edition

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2009-03-17 / USD 43.95

Rails just keeps on changing. Rails 2, released in 2008, brings hundreds of improvements, including new support for RESTful applications, new generator options, and so on. And, as importantly, we’ve a......一起来看看 《Agile Web Development with Rails, Third Edition》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具