ViewBinding时代,Activity基类封装

前言

ViewBinding是一款新的视图绑定框架, 是findViewById的替代方案。相比于DataBinding对Xml的注入式绑定,ViewBinding显的更为高效与简洁。

ViewBinding简介

当你在build.grade中添加如下代码即可开启ViewBinding机制。

	buildFeatures {
        viewBinding = true
    }

ViewBinding将根据你所有的XML布局文件生成对应的ViewBinding派生类。如下是我们的MainActivity。

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.id.layout_main);
   }
}

MainActivity的布局layout_main生成的ViewBinding类会自动命名为ActivityMainBinding,而我们通过ActivityMainBinding的静态方法-inflate(),并给该方法传递一个LayoutInflater就可获得ActivityMainBinding对象,并通过getRoot()获得布局。

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
       setContentView(binding.getRoot());
   }
}

在XML中我们有一个TextView,id为tv_show,而ViewBinding自动将它绑定给了tvShow,我们像下面这样访问它。

binding.tvShow.setText("Android");

对ViewBinding“抽象”化

每一个Activity将对应一个ViewBinding对象,如果我们像上面那样每个Activity做这样的操作会显的很麻烦,我们直接建一个抽象类来完成模板复用。

public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity {

  public T binding;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Type sup = getClass().getGenericSuperclass();
      Class<?> cls = (Class<?>) ((ParameterizedType) sup).getActualTypeArguments()[0];
      try {
          Method mInflate = cls.getDeclaredMethod("inflate", LayoutInflater.class);
          binding = (T) mInflate.invoke(null, getLayoutInflater());
          setContentView(binding.getRoot());
      } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
          Toast.makeText(this, e.toString() + "启动遇到了错误!", Toast.LENGTH_SHORT).show();
          android.os.Process.killProcess(android.os.Process.myPid());
          System.exit(0);
      }
  }
}

这里我们首先使用反射来完成ViewBinding的“抽象”,使用时添加对应的泛型即可。

public class ChatActivity extends BaseActivity<ActivityChatBinding>{}

反射虽然好用,但是它会有一定的耗时,大概在500ms以内。追求的页面的响应速度,我提供如下的解决方式。

public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity {

  public T binding;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      binding = getViewBinding();
      setContentView(binding.getRoot());
  }
  
  protected abstract T getViewBinding();
}

使用时需要添加对应的泛型,并实现抽象方法getViewBinding();

public class ChatActivity extends BaseActivity<ActivityChatBinding> {

 @Override
 protected ActivityChatBinding getViewBinding() {
     return ActivityChatBinding.inflate(getLayoutInflater());
 }
}

较完善的Activity基类

public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity {

    public T binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = getViewBinding();
        setContentView(binding.getRoot());
        if (!onFullscreen() && !onImmersion())
            StatusBarUtil.setStatusLightTheme(this, true);//设置状态栏为白底黑字样式

        if (adaptVirtualNavigation()) {
            //适配虚拟导航按键
            if (VirtualNavigationUtil.checkDeviceHasNavigationBar(this)) {
                VirtualNavigationUtil.assistActivity(findViewById(android.R.id.content));
            }
        }
		//当然Butterknife已经被Google搞废了,但暂时还能用
        //ButterKnife.bind(this);
        initData();
        getParentIntent();
        initView();
        initListener();
        initBroadcast();
    }

    @Override
    protected void onStart() {
        super.onStart();
        initAnimation();
    }

    @Override
    protected void onResume() {
        super.onResume();
        startAnimation();
    }

    protected abstract T getViewBinding();

    protected abstract void initView();

    protected void initAnimation() {}

    protected void startAnimation() {}

    /**
     * 开启全屏
     */
    protected boolean onFullscreen() {
        return false;
    }

    /**
     * 开启沉浸式
     */
    protected boolean onImmersion() {
        return false;
    }

    /**
     * 适配虚拟导航键
     */
    protected boolean adaptVirtualNavigation() {
        return false;
    }

    protected void initListener() {}

    protected void getParentIntent() {}

    protected void initData() {}

    protected void initBroadcast() {}

    protected InputMethodManager getInputMethodManager() {
        return DisplayUtil.getInputMethodManager(this);
    }

    /**
     * 重载startActivity()
     */
    protected void startActivity(Context context, Class<?> cls) {
        startActivity(context, cls, null, null, null);
    }

    protected void startActivity(Context context, Class<?> cls, String action) {
        startActivity(context, cls, action, null, null);
    }

    protected void startActivity(Context context, Class<?> cls, String bundleKey, Bundle bundle) {
        startActivity(context, cls, null, bundleKey, bundle);
    }

    protected void startActivity(Context context, Class<?> cls, String action, String bundleKey, Bundle bundle) {
        Intent intent = new Intent(context, cls);
        if (action != null)
            intent.setAction(action);
        if (bundle != null)
            intent.putExtra(bundleKey, bundle);
        startActivity(intent);
    }

    /**
     * 开启新activity并结束本身
     */
    protected void finishStartActivity(Context context, Class<?> cls) {
        startActivity(context, cls, null, null, null);
        finish();
    }

    protected void finishStartActivity(Context context, Class<?> cls, String action) {
        startActivity(context, cls, action, null, null);
        finish();
    }

    protected void finishStartActivity(Context context, Class<?> cls, String bundleKey, Bundle bundle) {
        startActivity(context, cls, null, bundleKey, bundle);
        finish();
    }
}

模板中我提供了沉浸式导航栏与虚拟按键的适配。沉浸式的开启只需要在需要的Activity中重写onImmersion()方法即可。

public class MainActivity extends BaseActivity<ActivityMainBinding> {

    @Override
    protected ActivityMainBinding getViewBinding() {
        return ActivityMainBinding.inflate(getLayoutInflater());
    }

    @Override
    protected boolean onImmersion() {
        return StatusBarUtil.setImmersion(this);
    }
    
    @Override
    protected void initView() {}
}

这里我把用到的一些工具类包括StatusBarUtil和VirtualNavigationUtil都放在gitee上了,需要的自提吧。
链接: wrmzd

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值