//混淆规则
-keep class 包名.databinding.* {*;}
使用反射
BaseActivity:
public class BaseActivity<T extends ViewBinding> extends AppCompatActivity {
protected T binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Type superclass = getClass().getGenericSuperclass();
Class<?> aClass = (Class<?>) ((ParameterizedType) superclass).getActualTypeArguments()[0];
try {
Method method = aClass.getDeclaredMethod("inflate", LayoutInflater.class);
binding = (T) method.invoke(null, getLayoutInflater());
setContentView(binding.getRoot());
} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {
e.printStackTrace();
}
}
}
使用 泛型传入ViewBinding即可:
public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// binding.button1 ……
}
}
BaseFragment
public class BaseFragment<T extends ViewBinding> extends Fragment {
protected T binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Type superclass = getClass().getGenericSuperclass();
Class<?> aClass = (Class<?>) ((ParameterizedType) superclass).getActualTypeArguments()[0];
try {
Method method = aClass.getDeclaredMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);
binding = (T) method.invoke(null, getLayoutInflater(),container,false);
} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {
e.printStackTrace();
}
return binding.getRoot();
}
}
使用:
public class BlankFragment extends BaseFragment<FragmentBlankBinding> {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//binding.textView ……
}
}
kotlin的写法:
open class BaseActivity<VB:ViewBinding> :AppCompatActivity() {
protected val binding: VB by lazy {
//使用反射得到viewbinding的class
val type = javaClass.genericSuperclass as ParameterizedType
val aClass = type.actualTypeArguments[0] as Class<*>
val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
method.invoke(null, layoutInflater) as VB
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
open class BaseFragment<VB:ViewBinding>:Fragment(){
lateinit var binding: VB
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val type = javaClass.genericSuperclass as ParameterizedType
val 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 VB
return binding.root
}
}
不使用反射
关于要不要用反射,以及反射的性能问题,我测试了几次,反射的耗时为20-350毫秒,不使用反射的话,基本在10毫秒以内,所以用不用看个人吧
如果不想使用反射,binding就需要自己实例化,其实写起来也简单:
open class ViewActivity<VB : ViewBinding>(open val block:(LayoutInflater)->VB) : BaseActivity(){
protected val binding by lazy { block(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
abstract class ViewFragment2<VB : ViewBinding>(val bindingBlock:(LayoutInflater, ViewGroup?,Boolean)->VB) : BaseFragment(){
private lateinit var _binding: VB
protected val binding get() = _binding
override fun getLayoutId() = 0
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
isLoaded = false
_binding = bindingBlock(inflater,container,false)
return _binding.root
}
}
使用:
class MainActivity2 : ViewActivity<ActivityMain2Binding>(ActivityMain2Binding::inflate){
}
class MyFragment:ViewFragment2<FragmentMyBinding>(FragmentMyBinding::inflate){
}