组件化之路 - ViewBinding基类封装
既然已经对 ViewBinding一知半解 ,那么接下来肯定是要集成到项目中跑起来,所以此篇主讲关于ViewBinding集成在基类的具体方式~
兄弟篇
- 组件化之路 - ViewBinding一知半解
- 组件化之路 - ViewBinding基类封装
我看了看网上关于ViewBinding
基类集成,一般都是通过反射
、非反射
的方法去集成基类,进行使用的 > <
我自己稍作总结后,得出以下结论,通篇也以此结论进行说明
关于ViewBinding基类集成,主要集成有俩种方式
- 常规写法,手动通过原始代码封装Base基类,达到基类封装效果,从而运用到自己的项目
- 三方框架,如加入 ViewBindingKTX 框架,包体积虽有增大,但作者能解决一些自己后续会遇到或忽略的问题 (起初是我朋友推荐,后来在知乎看到了原作者也在推荐)
关于ViewBinding基类集成,主要集成有俩种用法
- 非反射(不使用反射,常规写法)
- 反射(如果代码混淆的话,容易出现找不到类的场景)
关于ViewBinding基类集成,主要集成有俩种开发语言
- Java
- Kotlin
因为我用Kotlin经验还不足,所以我自己写了一下Java - BaseActivity基类封装 ~
- 常规集成(不使用反射)
- Java - BaseActivity
- Kotlin - BaseActivity
- Kotlin - BaseFragment
- 反射集成
- Java - BaseActivity
- Java - BaseFragment
- Kotlin - BaseActivity
- Kotlin - BaseFragment
- 三方框架
- Feature
- 基础配置
- Java改造基类
- 不使用反射
- 反射
常规集成(不使用反射)
关于ViewBinding基类封装的很多知识,借鉴了此篇 blog 的尾部代码(当然,这类型代码太常见了,至少我看到多篇相似的封装方式,不过一点儿都不影响我的学习热情,加油 ) ~
Java - BaseActivity
这种方式,也是我在项目中使用的方式,经本人亲自尝试,可用 ~
但要注意ViewBinding在不同场景的使用方式有所不同,此处仅作用于Activity相关组件, 如不懂可前往ViewBinding继续进阶 ~
//基类封装
public abstract class BaseBindingActivity<T extends ViewBinding> extends AppCompatActivity {private T mBinding;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);mBinding = getViewBinding();setContentView(mBinding.getRoot());}public abstract T getViewBinding();
}//使用方式
public class MainActivity extends AppCompatActivity {private ActivityMainBinding mBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mBinding.textView.text = "冲刺把,卡布达~"}@Overridepublic ViewBinding getViewBinding() {mBinding = ActivityMainBinding.inflate(getLayoutInflater());return mBinding;}
}
Kotlin - BaseActivity
//基类封装
abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)_binding = getViewBinding()setContentView(_binding.root)}protected abstract fun getViewBinding(): T
}//使用方式
class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "这是MainActivity"}override fun getViewBinding() = ActivityMainBinding.inflate(layoutInflater)
}
Kotlin - BaseFragment
//基类封装
abstract class BaseFragment<T : ViewBinding> : Fragment() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {_binding = getViewBinding(inflater, container)return _binding.root}protected abstract fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?): T
}//使用方式
class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "这是FirstFragment"}override fun getViewBinding(inflater: LayoutInflater,container: ViewGroup?) = FragmentFirstBinding.inflate(inflater, container, false)
}
反射集成
不推荐使用,会有混淆问题
Java - BaseActivity
//基类封装
public class BaseActivity<T extends ViewBinding> extends AppCompatActivity {protected T viewBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class);viewBinding = (T) inflate.invoke(null, getLayoutInflater());setContentView(viewBinding.getRoot());} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}}
}//使用方式
public class MainActivity extends BaseActivity<ActivityMainBinding> {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewBinding.button.setText("这是 MainActivity ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","点击按钮");}});}
}
Java - BaseFragment
//基类封装
public class BaseFragment<T extends ViewBinding> extends Fragment {protected T viewBinding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);viewBinding = (T) inflate.invoke(null, inflater, container, false);} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}return viewBinding.getRoot();}
}//使用方式
public class MainFragment extends BaseFragment<FragmentMainBinding>{@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);viewBinding.button.setText("这是 MainFragment ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","点击按钮");}});}
}
Kotlin - BaseActivity
//基类封装
open class BaseActivity<T : ViewBinding> : AppCompatActivity() {protected lateinit var binding: Toverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)binding = method.invoke(null, layoutInflater) as TsetContentView(binding.root)}
}//使用方式
class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "这是MainActivity"}
}
Kotlin - BaseFragment
//基类封装
open class BaseFragment<T:ViewBinding>:Fragment(){lateinit var binding: Toverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java,ViewGroup::class.java,Boolean::class.java)binding = method.invoke(null,layoutInflater,container,false) as Treturn binding.root}
}//使用方式
class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "这是FirstFragment"}
}
三方框架
这里使用的主要是 ViewBindingKTX 框架,此处仅介绍简单的使用方式,如有具体需求,可前往原作者的 Github ~
以下部分基本都是copy的原作者,实属无聊,权当记录把...
Feature
- 支持 Kotlin 和 Java 用法
- 支持多种使用反射和不使用反射的用法
- 支持封装改造自己的基类,使其用上 ViewBinding
- 支持 BaseRecyclerViewAdapterHelper
- 支持 Activity、Fragment、Dialog、Adapter
- 支持在 Fragment 自动释放绑定类的实例对象
- 支持实现自定义组合控件
- 支持 TabLayout 实现自定义标签布局
- 支持 NavigationView 设置头部控件
- 支持 DataBinding 自动设置 lifecycleOwner
基础配置
build(project)
allprojects {repositories {...maven { url 'https://www.jitpack.io' }}
}
build(app)
android {buildFeatures {viewBinding = true}
}dependencies {// 以下都是可选,请根据需要进行添加implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-ktx:1.2.4'implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-nonreflection-ktx:1.2.4'implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-base:1.2.4'implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-brvah:1.2.4'
}
Java改造基类
因对于Kotlin
还不熟,所以仅copy - Java改造基类
做个记录,有需要看Ktolin改造基类
的话, 直接跳这里看Ktolin封装的基类把 ~
不使用反射
Activity
public abstract class BaseBindingActivity<VB extends ViewBinding> extends AppCompatActivity {private VB binding;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = onCreateViewBinding(getLayoutInflater());setContentView(binding.getRoot());}protected abstract VB onCreateViewBinding(@NonNull LayoutInflater layoutInflater);public VB getBinding() {return binding;}
}//使用方式
public class MainActivity extends BaseBindingActivity<ActivityMainBinding> {@Overrideprotected ActivityMainBinding onCreateViewBinding(@NonNull LayoutInflater layoutInflater) {return ActivityMainBinding.inflate(layoutInflater);}@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);getBinding().getTvHelloWord().setText("Hello Android!");}
}
Fragment
public abstract class BaseBindingFragment<VB extends ViewBinding> extends Fragment {private VB binding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {binding = onCreateViewBinding(inflater, container);return binding.getRoot();}@Overridepublic void onDestroyView() {super.onDestroyView();binding = null;}public VB getBinding() {return binding;}protected abstract VB onCreateViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent);
}//使用方式
public class HomeFragment extends BaseBindingFragment<FragmentHomeBinding> {@Overrideprotected FragmentHomeBinding onCreateViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent) {return FragmentHomeBinding.inflate(inflater, parent, false);}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);getBinding().getTvHelloWord().setText("Hello Android!");}
}
Adapter
public abstract class BaseBindingQuickAdapter<T, VB extends ViewBinding>extends BaseQuickAdapter<T, BaseBindingQuickAdapter.BaseBindingHolder> {public BaseBindingQuickAdapter() {this(-1);}public BaseBindingQuickAdapter(@LayoutRes int layoutResId) {super(-layoutResId);}@NotNull@Overrideprotected BaseBindingHolder onCreateDefViewHolder(@NotNull ViewGroup parent, int viewType) {return new BaseBindingHolder(onCreateViewBinding(LayoutInflater.from(parent.getContext()), parent));}protected abstract VB onCreateViewBinding(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent);public static class BaseBindingHolder extends BaseViewHolder {private final ViewBinding binding;public BaseBindingHolder(@NotNull View view) {this(() -> view);}public BaseBindingHolder(@NotNull ViewBinding binding) {super(binding.getRoot());this.binding = binding;}@NonNull@SuppressWarnings("unchecked")public <VB extends ViewBinding> VB getViewBinding() {return (VB) binding;}}
}//使用方式
public class FooAdapter extends BaseBindingQuickAdapter<Foo, ItemFooBinding> {@Overrideprotected ItemFooBinding onCreateViewBinding(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {return ItemFooBinding.inflate(inflater, parent, false);}@Overrideprotected void convert(@NotNull BaseBindingHolder holder, Foo item) {ItemFooBinding binding = holder.getViewBinding();binding.tvFoo.setText(item.getValue());}
}
MultiType
public abstract class BindingViewDelegate<T, VB extends ViewBinding> extendsItemViewDelegate<T, BindingViewDelegate.BindingViewHolder<VB>> {@NotNull@Overridepublic BindingViewHolder<VB> onCreateViewHolder(@NotNull Context context, @NotNull ViewGroup parent) {return new BindingViewHolder<>(onCreateViewBinding(LayoutInflater.from(parent.getContext()), parent));}protected abstract VB onCreateViewBinding(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent);public static class BindingViewHolder<VB extends ViewBinding> extends RecyclerView.ViewHolder {private final VB binding;public BindingViewHolder(@NonNull VB binding) {super(binding.getRoot());this.binding = binding;}@NonNullpublic VB getBinding() {return binding;}}
}//使用方式
public class FooViewDelegate extends BindingViewDelegate<Foo, ItemFooBinding> {@Overrideprotected ItemFooBinding onCreateViewBinding(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {return ItemFooBinding.inflate(inflater, parent, false);}@Overridepublic void onBindViewHolder(@NotNull BindingViewHolder<ItemFooBinding> holder, Foo foo) {holder.getBinding().tvFoo.setText(item.getValue());}
}
反射
Activity
public abstract class BaseBindingActivity<VB extends ViewBinding> extends AppCompatActivity {private VB binding;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ViewBindingUtil.inflateWithGeneric(this, getLayoutInflater());setContentView(binding.getRoot());}public VB getBinding() {return binding;}
}//使用方式
public class MainActivity extends BaseBindingActivity<ActivityMainBinding>{@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);getBinding().getTvHelloWord().setText("Hello Android!");}
}
Fragment
public abstract class BaseBindingFragment<VB extends ViewBinding> extends Fragment {private VB binding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {binding = ViewBindingUtil.inflateWithGeneric(this, getLayoutInflater(), container, false);return binding.getRoot();}@Overridepublic void onDestroyView() {super.onDestroyView();binding = null;}public VB getBinding() {return binding;}
}//使用方式
class HomeFragment extends BaseBindingFragment<FragmentHomeBinding> {@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);getBinding().tvHelloWorld.setText("Hello Android!");}
}
Adapter
public abstract class BaseBindingQuickAdapter<T, VB extends ViewBinding>extends BaseQuickAdapter<T, BaseBindingQuickAdapter.BaseBindingHolder> {public BaseBindingQuickAdapter() {this(-1);}public BaseBindingQuickAdapter(@LayoutRes int layoutResId) {super(layoutResId);}@NotNull@Overrideprotected BaseBindingHolder onCreateDefViewHolder(@NotNull ViewGroup parent, int viewType) {VB viewBinding = ViewBindingUtil.inflateWithGeneric(this, parent);return new BaseBindingHolder(viewBinding);}public static class BaseBindingHolder extends BaseViewHolder {private final ViewBinding binding;public BaseBindingHolder(@NotNull View view) {this(() -> view);}public BaseBindingHolder(@NotNull ViewBinding binding) {super(binding.getRoot());this.binding = binding;}@NonNull@SuppressWarnings("unchecked")public <VB extends ViewBinding> VB getViewBinding() {return (VB) binding;}}
}//使用方式
class FooAdapter extends BaseBindingQuickAdapter<Foo, ItemFooBinding> {@Overridepublic void convert(@NotNull BindingViewHolder<ItemFooBinding> holder, Foo item) {ItemFooBinding binding = holder.getViewBinding();binding.tvFoo.setText(item.getValue());}
}
MultiType
public abstract class BindingViewDelegate<T, VB extends ViewBinding> extendsItemViewDelegate<T, BindingViewDelegate.BindingViewHolder<VB>> {@NotNull@Overridepublic BindingViewHolder<VB> onCreateViewHolder(@NotNull Context context, @NotNull ViewGroup parent) {return new BindingViewHolder<>(ViewBindingUtil.inflateWithGeneric(this, parent));}public static class BindingViewHolder<VB extends ViewBinding> extends RecyclerView.ViewHolder {private final VB binding;public BindingViewHolder(@NonNull VB binding) {super(binding.getRoot());this.binding = binding;}@NonNullpublic VB getBinding() {return binding;}}
}//使用方式
class FooViewDelegate extends BindingViewDelegate<Foo, ItemFooBinding> {@Overridepublic void onBindViewHolder(@NotNull BindingViewHolder<ItemFooBinding> holder, Foo item) {holder.getBinding().tvFoo.setText(item.getValue());}
}
组件化之路 - ViewBinding基类封装相关推荐
- android国籍组件,android组件化之路
问题:实际业务变化快,而工程内各个功能模块耦合度太高,不能对功能模块进行快速方便地拆分或组装.团队共同开发中,可能一个文件同时被多人修改,导致每次更新提交代码都需要消耗大量时间去merge代码.每次修 ...
- 蘑菇街App的组件化之路·续
原文:http://limboy.me/ios/2016/03/14/mgj-components-continued.html 蘑菇街 App 的组件化之路·续 前几天在「移动学习分享群」分享了关于 ...
- 组件化之路 - ViewModel一知半解
新的一年,优先把欠账补齐,关于Jetpack下Lifecycle.ViewModel.LiveData组件库,以及ViewModel+LiveData项目实践,如今也只差ViewModel还没有记录了 ...
- android 蘑菇街组件化,蘑菇街 App 的组件化之路
编辑推荐: 本文来自于csdn,文章主要分享了casatwy 的一些思路和思考问题的角度,希望对您的学习有帮助. 统一的调用实现 将「URL 调用」和「组件间调用」通过 runtime 达到统一,通过 ...
- android组件化蘑菇街,蘑菇街 App 的组件化之路·续
前几天在「移动学习分享群」分享了关于蘑菇街组件化方面的一点经验,由于时间和文字描述方面的限制,很多东西表述的不是很清楚,让一些同学产生了疑惑,casatwy老师也写了篇文章来纠正其中的一些实现,看完之 ...
- android mvp框架基类,Android MVP架构项目搭建封装,基类封装
综述 对于MVP (Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.而对于Android应用的开发中本身可视为一种MVC架构 ...
- 百度App组件化之路
原创:GuoJin 百度APP技术团队-资深技术专家 文章来源:百度APP技术微信公众号 组件化是一个老生常谈的涉及面很广的话题,即不是做好一件事而是做好一系列的事情才能达成:其中 ...
- 【超强干货】蘑菇街App的组件化之路
本文为『移动前线』群在3月10日的分享总结整理而成,转载请注明来自『移动开发前线』公众号. 嘉宾介绍 蘑菇街李忠(花名银时,网名 limboy),多年客户端开发经验,目前主要负责移动端基础架构设计及核 ...
- 蘑菇街 App 的组件化之路
在组件化之前,蘑菇街 App 的代码都是在一个工程里开发的,在人比较少,业务发展不是很快的时候,这样是比较合适的,能一定程度地保证开发效率. 慢慢地代码量多了起来,开发人员也多了起来,业务发展也快了起 ...
- 【Unity】UI交互组件之按钮Button可选基类总结
按钮(Button) 按钮控件可以响应于用户的点击并触发启动或确认操作,比如Web表单上的Submit及Cancel按钮.主要有三大属性:Interactable / Transition / Nav ...
最新文章
- linux系统下添加新硬盘的方法详解
- Ubuntu 16.04修改显示字体大小(包括GNOME/Unity)
- c++17(17)-异常try catch,operator[],vector at
- 【亚伦博客】反方观点: 下载不是偷窃
- PAT甲级1051 栈的模拟
- 未格式化的硬盘识别失败
- mysql基本常用命令_mysql 的基本操作以及常用命令
- 机器学习十大算法简介
- 数据结构-顺序表基本操作的实现(含全部代码)
- 安装算量软件图纸复制操作
- cad怎么画立体图形教学_cad怎么绘制三维图形,cad三维制图实例图文教程
- mac上面的文件分割与合并
- 激光雷达Velodyne16配置及录制rosbag
- python文件处理基础_第六篇:python基础之文件处理
- 一位期货人的总结:大道至简,悟者大成
- centos 虚拟机出问题 Oh no,something has gone wrong! 解决方法
- 乐教乐学各关的解(3-10)
- 在css中引用特殊字体
- 「PS-CC2019新版教程」画板工具-基础篇
- 我眼中的中国科研:一个中科院退学博士生的感想
热门文章
- lzg_ad:FBW控制台命令详解
- 10个典型的大数据案例
- 教程篇(7.0) 01. 介绍FortiClient和FortiClient EMS ❀ FortiClient EMS ❀ Fortinet 网络安全专家 NSE 5
- android模拟器 opengl,在Android模拟器上缺少OpenGL驱动程序
- DEVC++实现街头篮球(爷青回)(1.01版)
- Rhino6.25软件安装教程|兼容WIN10
- 标准盒子模型简单讲解
- 单月销量破万台,FITURE治好了健身镜的“水土不服”?
- 下载网络图片并上传微信公众平台素材库
- Java控制流程-for 天朝有一个乞丐姓洪,去天桥要钱 第一天要了1块钱 第二天要了2块钱 第三天要了4块钱 第四天要了8块钱 洪乞丐干10天,收入是多少?