Android ViewBinding使用介绍

目录
  • 一、kotlin-android-extensions
  • 二、ViewBinding使用
    • 1.gradle配置
    • 2.在Activity 使用
    • 3.在Fragment使用
    • 4.在Adapter中使用
    • 5.在Dialog中使用
    • 6.Include中使用
  • 三、ViewBinding封装
    • 1.在BaseActivity中封装
    • 2.通过反射的方式封装
    • 3.反射+基类
      • 1.在Activity 中使用
      • 2.在Fragment中使用
    • 4.委托的方式

一、kotlin-android-extensions

在使用ViewBinding之前,我们一直使用的是kotlin-android-extensions,使用kotlin-android-extensions可以节约很多写findViewById的时间。不过这个kotlin-android-extensions插件已经废弃了,简单说一下kotlin-android-extensions存在的问题:

1.通过反编译kotlin-android-extensions的代码,发现会创建一个HashMap,用来存放所有的id和对应的View的缓存,如果缓存中没有View,那么就通过findViewById去创建并存入缓存,否则就直接获取。所以会存在内存问题。

private HashMap _$_findViewCache;
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();
}

2.由于kotlin-android-extensions是通过view的id名直接引用的,如果多个布局间的同名id,就需要手动对import进行重命名处理,如果引用错误的布局文件,就会出现crash。所以存在资源重名的问题。

3.只有Kotlin才可以使用。

所以ViewBinding优势有:java,kotlin都可以使用,可以有效避免NullPointerException。

二、ViewBinding使用

1.gradle配置

buildFeatures {
    viewBinding true
}

开启ViewBinding之后,在编译时,AGP会自动帮我们给每个xml布局创建一个Binding类,位于build/generated/data_binding_base_class_source_out/目录下。

public final class FragmentLoginBinding implements ViewBinding {
  @NonNull
  private final ConstraintLayout rootView;
  @NonNull
  public final ConstraintLayout container;
  @NonNull
  public final ProgressBar loading;
  @NonNull
  public final Button login;
  @NonNull
  public final EditText password;
  @NonNull
  public final EditText username;
  private FragmentLoginBinding(@NonNull ConstraintLayout rootView,
      @NonNull ConstraintLayout container, @NonNull ProgressBar loading, @NonNull Button login,
      @NonNull EditText password, @NonNull EditText username) {
    this.rootView = rootView;
    this.container = container;
    this.loading = loading;
    this.login = login;
    this.password = password;
    this.username = username;
  }
  @Override
  @NonNull
  public ConstraintLayout getRoot() {
    return rootView;
  }
  @NonNull
  public static FragmentLoginBinding inflate(@NonNull LayoutInflater inflater) {
    return inflate(inflater, null, false);
  }
  @NonNull
  public static FragmentLoginBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup parent, boolean attachToParent) {
    View root = inflater.inflate(R.layout.fragment_login, parent, false);
    if (attachToParent) {
      parent.addView(root);
    }
    return bind(root);
  }
  @NonNull
  public static FragmentLoginBinding bind(@NonNull View rootView) {
    // The body of this method is generated in a way you would not otherwise write.
    // This is done to optimize the compiled bytecode for size and performance.
    int id;
    missingId: {
      ConstraintLayout container = (ConstraintLayout) rootView;
      id = R.id.loading;
      ProgressBar loading = rootView.findViewById(id);
      if (loading == null) {
        break missingId;
      }
      id = R.id.login;
      Button login = rootView.findViewById(id);
      if (login == null) {
        break missingId;
      }
      id = R.id.password;
      EditText password = rootView.findViewById(id);
      if (password == null) {
        break missingId;
      }
      id = R.id.username;
      EditText username = rootView.findViewById(id);
      if (username == null) {
        break missingId;
      }
      return new FragmentLoginBinding((ConstraintLayout) rootView, container, loading, login,
          password, username);
    }
    String missingId = rootView.getResources().getResourceName(id);
    throw new NullPointerException("Missing required view with ID: ".concat(missingId));
  }
}

注意:

1.因为这些类编译时就生成了,就不会占用运行时内存。

2.未使用的Binding文件会在混淆时被删除,所以对包大小影响很小。

3.编译器生成Binding文件是增量更新的。

那么如何不生成Binding类呢?tools:viewBindingIgnore="true"

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:viewBindingIgnore="true"
    tools:context=".MainActivity">

2.在Activity 使用

class TestViewBindingActivity : AppCompatActivity() {
    private lateinit var bindding: ActivityTestViewBindingBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bindding = ActivityTestViewBindingBinding.inflate(layoutInflater)
        setContentView(bindding.root)
        changeText()
    }
    private fun changeText() {
        bindding.titleTv.text = "哈哈,在Activity中使用ViewBinding了"
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".testviewbinding.TestViewBindingActivity">
    <TextView
        android:id="@+id/titleTv"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center"
        android:text="在Activity中使用ViewBinding"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

3.在Fragment使用

class TextViewBindingFragment : Fragment() {
    private var param1: String? = null
    private var param2: String? = null
    private var _binding: FragmentTextViewBindingBinding? = null
    private val binding get() = _binding!!
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentTextViewBindingBinding.inflate(layoutInflater, container, false)
        return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        changeText()
    }
    private fun changeText() {
        binding.tvTitle.text = "哈哈,在Fragment中使用ViewBinding"
    }
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
    companion object {
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            TextViewBindingFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
        @JvmStatic
        fun newInstance() = TextViewBindingFragment()
    }
}
class TestViewBindingActivity : AppCompatActivity() {
    private lateinit var bindding: ActivityTestViewBindingBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bindding = ActivityTestViewBindingBinding.inflate(layoutInflater)
        setContentView(bindding.root)
        val newInstance = TextViewBindingFragment.newInstance()
        addFragment(
            supportFragmentManager,
            newInstance,
            isAllowStateLoss = true,
            frameId = R.id.fragmentFrame
        )
    }
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".testviewbinding.TextViewBindingFragment">
    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="在Fragment中" />
</FrameLayout>

4.在Adapter中使用

class TestAdapterActivity : AppCompatActivity() {
    private lateinit var binding: ActivityTestAdapterBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityTestAdapterBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initView()
    }
    companion object {
        val ITEMS = mutableListOf<String>("1", "2", "3", "4", "5", "6")
    }
    private fun initView() {
        with(binding.contentRcycler) {
            layoutManager = GridLayoutManager(context, 4)
            adapter = TestRecyclerViewAdapter(ITEMS)
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".testviewbinding.TestAdapterActivity">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/contentRcycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
class TestRecyclerViewAdapter(private val values: List<String>) :
    RecyclerView.Adapter<TestRecyclerViewAdapter.ViewHolder>() {
    inner class ViewHolder(binding: RecyclerItemLayoutBinding) :
        RecyclerView.ViewHolder(binding.root) {
        val textTv = binding.contentTv
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            RecyclerItemLayoutBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = values[position]
        holder.textTv.text = item
    }
    override fun getItemCount(): Int = values.size
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="200dp">
    <TextView
        android:id="@+id/contentTv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="16dp"
        tools:text="99" />
</androidx.constraintlayout.widget.ConstraintLayout>

5.在Dialog中使用

class CommonDialog(context: Context) : Dialog(context) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(DialogLayoutBinding.inflate(layoutInflater).root)
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/dialogContent"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:text="This is Dialog"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

6.Include中使用

class TestIncludeActivity : AppCompatActivity() {
    private lateinit var binding: ActivityTestIncludeBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityTestIncludeBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initView()
    }
    private fun initView() {
        binding.itemInclude.itemContentTv.text = "哈哈, this is include"
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".testviewbinding.TestIncludeActivity">
    <include
        android:id="@+id/itemInclude"
        layout="@layout/item_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/itemContentTv"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:text="Test include"
        android:textSize="30sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

三、ViewBinding封装

1.在BaseActivity中封装

abstract class BaseViewBindingActivity<T : ViewBinding> : AppCompatActivity() {
    protected val binding by lazy {
        getViewBinding()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
    }
    protected abstract fun getViewBinding(): T
}
class ChildViewBindingMainActivity :
    BaseViewBindingActivity<ActivityChildViewBindingMainBinding>() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.titleTv.text = "哈哈,this is child binding activity"
    }
    override fun getViewBinding(): ActivityChildViewBindingMainBinding {
        return ActivityChildViewBindingMainBinding.inflate(layoutInflater)
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".encapsulatviewbinding.ChildViewBindingMainActivity">
    <TextView
        android:id="@+id/titleTv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="36sp" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.通过反射的方式封装

class TestViewBindingMainActivity : AppCompatActivity() {
    private val binding by inflate<ActivityTestViewBindingMainBinding>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.titleTv.text = "哈哈,通过反射封装ViewBinding"
    }
}
inline fun <reified T : ViewBinding> inflateByViewBinding(layoutInflater: LayoutInflater) =
    T::class.java.getMethod("inflate", LayoutInflater::class.java).invoke(null, layoutInflater) as T
inline fun <reified T : ViewBinding> Activity.inflate() = lazy {
    inflateByViewBinding<T>(layoutInflater).apply {
        setContentView(root)
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".encapsulatviewbinding.TestViewBindingMainActivity">
    <TextView
        android:id="@+id/titleTv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="36sp" />
</androidx.constraintlayout.widget.ConstraintLayout>

3.反射+基类

1.在Activity 中使用

abstract class BaseBindingMainActivity2<T : ViewBinding> : AppCompatActivity() {
    protected lateinit var binding: T
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val clazz = type.actualTypeArguments[0] as Class<T>
            val method = clazz.getMethod("inflate", LayoutInflater::class.java)
            binding = method.invoke(null, layoutInflater) as T
        }
        setContentView(binding.root)
    }
}
class ChildViewBindingMainActivity2 :
    BaseBindingMainActivity2<ActivityChildViewBindingMain2Binding>() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.titleTv.text = "哈哈,这是反射+基类的方式"
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".encapsulatviewbinding.ChildViewBindingMainActivity2">
    <TextView
        android:id="@+id/titleTv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.在Fragment中使用

abstract class BaseBindingViewFragment<T : ViewBinding> : Fragment() {
    private var _binding: T? = null
    protected val binding get() = _binding!!
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val type = javaClass.genericSuperclass
        val clazz = (type as ParameterizedType).actualTypeArguments[0] as Class<T>
        val method = clazz.getMethod(
            "inflate",
            LayoutInflater::class.java,
            ViewGroup::class.java,
            Boolean::class.java
        )
        _binding = method.invoke(null, layoutInflater, container, false) as T
        this.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    Log.v(TAG, "onDestroy binding be null")
                    _binding = null
                }
            }
        })
        return binding.root
    }
    companion object {
        const val TAG = "BaseBindingViewFragment"
    }
}
class ChildBindingFragment : BaseBindingViewFragment<FragmentChildBindingBinding>() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return super.onCreateView(inflater, container, savedInstanceState)
    }
    companion object {
        @JvmStatic
        fun newInstance() = ChildBindingFragment()
    }
}
class TestBindingMainActivity3 : BaseBindingMainActivity2<ActivityTestBindingMain3Binding>() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val newInstance = ChildBindingFragment.newInstance()
        addFragment(
            supportFragmentManager,
            newInstance,
            isAllowStateLoss = true,
            frameId = R.id.frame
        )
    }
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".encapsulatviewbinding.ChildBindingFragment">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />
</FrameLayout>

4.委托的方式

class TestViewBindingFragment2 : Fragment(R.layout.fragment_test_view_binding2) {
    private val binding by inflate<FragmentTestViewBinding2Binding>()
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.root
    }
    companion object {
        @JvmStatic
        fun newInstance() = TestViewBindingFragment2()
    }
}
inline fun <reified T : ViewBinding> Fragment.inflate() =
    FragmentViewBindingDelegate(T::class.java)
class FragmentViewBindingDelegate<T : ViewBinding>(private val clazz: Class<T>) :
    ReadOnlyProperty<Fragment, T> {
    private var binding: T? = null
    override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        if (binding == null) {
            binding =
                clazz.getMethod("bind", View::class.java).invoke(null, thisRef.requireView()) as T
            thisRef.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    if (event == Lifecycle.Event.ON_DESTROY) {
                        binding = null
                    }
                }
            })
        }
        return binding!!
    }
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".encapsulatviewbinding.TestViewBindingFragment2">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="8888888" />
</FrameLayout>

到此这篇关于Android ViewBinding使用介绍的文章就介绍到这了,更多相关Android ViewBinding内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android使用ViewBinding的详细步骤(Kotlin简易版)

    ViewBinding 是什么 2020年的3月份 巨佬 JakeWharton 开源的 butterknife 被官宣 停止维护,在github 上 说明 Attention: This tool is now deprecated. Please switch to view binding. Existing versions will continue to work, obviously, but only critical bug fixes for integration with

  • Android Studio 3.6中新的视图绑定工具ViewBinding 用法详解

    前言 我们在Android开发的过程中总是需要获取XML布局中的ViewId,以便给其赋值进行显示,早期我们只能使用 findViewById 这个API,会导致很多的模版代码出现.2013年左右Android界大神 Jake Wharton开源了Butter Knife框架,通过Bind("viewid")方式方便开发者获取ViewId.近两年由于谷歌对Kotlin的支持,我们开始使用 Android Kotlin extensions. 在文件中导入布局文件直接引用viewId.无

  • Android开发Viewbinding委托实例详解

    目录 背景 从Crash到有意思的源码 有趣的代码 另外一些有意思的地方 结尾 背景 前一阵子我们在使用viewbinding的委托的时候碰到了点crash问题,然后发现了一个比较有意思的解决方案,就和大家展开聊聊. 另外一点就是我后面打算将kotlin extensions这个插件统一移除掉. 估计大家应该对Viewbinding的委托应该都有一定的了解,好几个大佬分享过类似的文章,但是大佬们的代码貌似也有一阵子都没有维护了,所以我找到了一个外国大佬写的仓库,其实应该算是一个相对来说比较稳定的

  • Android Studio3.6新特性之视图绑定ViewBinding使用指南

    View Binding是一项功能,使您可以更轻松地编写与视图交互的代码.在模块中启用视图绑定后,它将为该模块中存在的每个XML布局文件生成一个绑定类.绑定类的实例包含对在相应布局中具有ID的所有视图的直接引用. 正文 Android Studio 3.6 Canary 11 及更高版本中推出了ViewBinding功能,ViewBinding将逐步替换掉findViewById,还等什么,抓紧时间学习吧! 谷歌官方文档的ViewBinding Demo是用Kotlin语言写的,看起来比较生疏,

  • Android ViewBinding的使用详解

    目录 一.什么是view binding 设置说明 二.基本用法 Activity中使用 Fragment 中使用 Adapter 中使用 三.了解源码实现 BaseActivity BaseFragment BaseAdapter 四.其他 最近Android Studio 升级后 butterknife 有一个警告: Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using them as

  • Android ViewBinding使用介绍

    目录 一.kotlin-android-extensions 二.ViewBinding使用 1.gradle配置 2.在Activity 使用 3.在Fragment使用 4.在Adapter中使用 5.在Dialog中使用 6.Include中使用 三.ViewBinding封装 1.在BaseActivity中封装 2.通过反射的方式封装 3.反射+基类 1.在Activity 中使用 2.在Fragment中使用 4.委托的方式 一.kotlin-android-extensions 在

  • Android ViewDragHelper使用介绍

    ViewDragHelper是support.v4下提供的用于处理拖拽滑动的辅助类,查看Android的DrawerLayout源码,可以发现,它内部就是使用了该辅助类来处理滑动事件的. public DrawerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setDescendantFocusability(ViewGroup.FOCUS_AFTER_DE

  • Gradle编译打包Android apk详细介绍

    Gradle编译打包Android apk详细介绍 理解Gradle构建过程,解读Android Gradle插件的配置 阅读本文一定是要使用过Gradle生成apk,文中不会讲如何安装运行Gradle,如有需要可先看文末的参考文章. APK包是一个ZIP压缩包,从Java源代码.资源文件到生成这个APK,经过了编译打包一系列特定的过程,SDK文档(/docs/tools/building/index.html)中找到.而这一系列特定的过程,重复繁琐,构建工具(build tool)就是来流程化

  • Android超详细介绍自定义多选框与点击按钮跳转界面的实现

    总程:在avtivity_main.xml设计5个控件,btn1-5,点击btn1弹出一个多选对话框,点击按钮btn1弹出一个多选框可选择你喜欢的打野英雄,点击btn2跳转到activity_main2界面(就是图片,不可选择)设计思路流程:在activity_main.xml布局界面,总体在头目录进行垂直排列,然后镶嵌5个水平的线性布局(左是ImageView,右边是Button按钮)由于5张图的大小在一个屏幕显示不出来,所以添加一个ScoveView滚动,以使所有资源可以看到! 在MainA

  • Android控件系列之Button以及Android监听器使用介绍

    学习目的: 1.掌握在Android中如何建立Button 2.掌握Button的常用属性 3.掌握Button按钮的点击事件(监听器) Button是各种UI中最常用的控件之一,它同样也是Android开发中最受欢迎的控件之一,用户可以通过触摸它来触发一系列事件,要知道一个没有点击事件的Button是没有任何意义的,因为使用者的固定思维是见到它就想去点! 先看下Android中普通Button的样子: 以及点中Button后的样子: 我在Android控件系列之XML静态资源中已经强调了布局和

  • Android学习之介绍Binder的简单使用

    前言 最近因为公司项目需求,需要远程调度启动客户端输入法输入内容. 这就是大致的需求流程,这篇首先讲远程与服务控制端通讯.首先控制服务端定义好一个Service,且在ServiceManager注册添加服务. 在这里我讲解远程端与服务控制端通讯(主要通过C++往ServiceManager注册服务). 首先我们得获取到服务控制端注册在ServiceManager的服务IBinder对象,通过Java反射机制获得Ibinder接口对象. public static IBinder getRemot

  • Android签名机制介绍:生成keystore、签名、查看签名信息等方法

    Android独有的安全机制,除了权限机制外,另外一个就是签名机制了.签名机制主要用在以下两个主要场合起到其作用:升级App和权限检查. 升级App 用户在升级一款已经安装过的App时,如果程序的修改来自于同一来源,则允许升级安装,否则会提示签名不一致无法安装的提示. 权限检查 我曾在Android Permission权限机制的具体使用一文中提过,对于申请权限的  protection level 为 signature 或者 signatureOrSystem 的,会检查权限申请者和权限声明

  • android CursorLoader用法介绍

    工作内容集中到Contact模块,这个应用查询数据的地方很多,其使用了CursorLoader这个工具大大简化了代码复杂度.android自3.0提供了Loader机制,当时google的API只是简单的介绍了一下没有给出用法,大家很少有关注.后来因为重度模型下的性能优化,R&D的朋友发现这个东西非常给力,这才开始注意到这个强大的工具.CursorLoader是Loader的子类,可以说是Loader的升级版.这篇小结以loader为基础说明,弄懂原理之后也就明白了CursorLoader.先说

  • android AsyncTask详细介绍

    AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 使用的优点: 简单,快捷 过程可控 使用的缺点: 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来. 2 )Handler异步实现的原理和适用的优缺点 在Handler 异步实现时,涉及到

随机推荐