我的 Android 开发之旅(一):BaseActivity 的浅入
为什么要写 BaseAcivity
一行代码实现 Toolbar 效果
"少啰嗦, 先看东西"
最后
为什么要写 BaseAcivity
我们都知道在做 Android 应用开发的时候都需要创建一个 Activity, 但很多时候我们的程序有多个界面并且每个界面都有相似的内容 (例如: Toolbar,DrawerLayout) 和后台的操作有共同的方法, 这个时候我们写一个 BaseActivity 作为每一个 Activity 的基类, 统一管理程序中的每个 Activity.
一行代码实现 Toolbar 效果
activity_main.xml 的代码
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout 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=".MainActivity"
- Android:gravity="center"
- Android:background="@android:color/holo_blue_light">
- <TextView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:text="我是 MainActivity 的界面"
- App:layout_constraintBottom_toBottomOf="parent"
- App:layout_constraintLeft_toLeftOf="parent"
- App:layout_constraintRight_toRightOf="parent"
- App:layout_constraintTop_toTopOf="parent" />
- </LinearLayout>
MainAcitvity.java 的代码
public class MainActivity extends BaseActivity { @Override protected int getContentView() { return R.layout.activity_main; } }
在上面的 activity_main.xml 中可以看出, 父布局设置了背景颜色和里面只有一个 TextView, 并没图中的 Toolbar. 那到底是为什么呢? 其实细心观察的小伙伴们会发现, 怎么 MainActivity 中的代码和平常不一样呢? onCreate()方法呢? 别急, 我们重头开始!
"少啰嗦, 先看东西"
创建 BaseActivity
在项目创建后, 我们可以看到 AndroidStudio 自动帮我们生成了 MainActivity.java 和 activity_main.xml 文件, 然后我们再创建一个新的 Activity, 命名为 BaseActivity.
修改 activity_base.xml 文件
接着打开 activity_base.xml 文件, 把父布局的 ConstraintLayout 换成垂直的 LinearLayout(其实也可以不换的, 主要是我喜欢用 LinearLayout), 并在里面添加两个元素 Toolbar 和 FrameLayout.
注意: 由于 Toolbar 代替 ActionBar, 所以先把 ActionBar 去掉, 我们通过设置 Application 的 theme 来隐藏, 这样项目中所有的界面的 ActionBar 就都隐藏了.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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=".BaseActivity" Android:orientation="vertical"> <androidx.appcompat.widget.Toolbar Android:id="@+id/toolbar" Android:layout_width="match_parent" Android:layout_height="?attr/actionBarSize" Android:background="?attr/colorPrimary" Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" App:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <FrameLayout Android:id="@+id/container" Android:layout_width="match_parent" Android:layout_height="match_parent"> </FrameLayout> </LinearLayout>
修改 BaseActivity.java 文件
接下来打开 BaseActivity.java 文件, 让 BaseActivity 继承 AppCompatActivity , 修改代码如下
注意: protected abstract int getContentView(); 是一个抽象方法, 所以我们要将 BaseActivity 修改成抽象类. 为什么要修改成抽象类呢? 原因很简单, 因为一个类里是不允许有一个抽象方法的, 如要有抽象方法, 那这个类就必须是抽象类. 那可能你又会问, 为什么要用抽象方法呢?(你是十万个为什么吗? 哪来的那么多为什么)因为我们想让其他 Activity 的界面显示到 BaseActivity 中, 那这个方法是必须要实现的, 如果设置成普通的方法的话, 我们很有可能在写代码的时候忘记了调用了这个方法, 导致界面不显示. 所以我们得用抽象方法, 这样每个 Activity 继承这个 BaseActivity 的时候就必须覆写 getContentView() 这个方法.
public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_base); initView(); } private void initView() { // 绑定控件 Toolbar toolbar = findViewById(R.id.toolbar); FrameLayout container = findViewById(R.id.container); // 初始化设置 Toolbar toolbar.setTitle("我是 BaseActivity 的 Toolbar"); setSupportActionBar(toolbar); // 将继承了 BaseActivity 的布局文件解析到 container 中, 这样 BaseActivity 就能显示 MainActivity 的布局文件了 LayoutInflater.from(this).inflate(getContentView(), container); } /** * 获取要显示内容的布局文件的资源 id * * @return 显示的内容界面的资源 id */ protected abstract int getContentView(); }
修改 activity_main.xml 文件
打开 activity_main.xml 文件, 然后我们将父布局的背景颜色修改一下, 方便我们辨别到底是 MainActivity 的布局文件还是 BaseActivity 的布局文件. 再添加添加一个 TextView , 原因也是和修改背景颜色是一样的.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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=".MainActivity" Android:gravity="center" Android:background="@android:color/holo_blue_light"> <TextView Android:layout_width="wrap_content" Android:layout_height="wrap_content" Android:text="我是 MainActivity 的界面" App:layout_constraintBottom_toBottomOf="parent" App:layout_constraintLeft_toLeftOf="parent" App:layout_constraintRight_toRightOf="parent" App:layout_constraintTop_toTopOf="parent" /> </LinearLayout>
修改 MainActivity.java 文件
让 MainActivity 继承 BaseActivity 并覆写 getContentView() 方法, 然后删除 onCreate()方法. 通过 getContentView() 方法返回当前的布局资源 ID 给 BaseActivity, 让 BaseActivity 加载布局文件.
public class MainActivity extends BaseActivity { @Override protected int getContentView() { return R.layout.activity_main; } }
运行项目
现在你运行一下项目, 我们并没有在 MainActivity 的布局中添加 ToolBar, 但是运行出来的效果是 Toolbar 已经存在了.
现在就能做到用一行代码实现 Toolbar 的效果. 那你现在可能就会有疑问, 如果我像对 Toolbar 修改标题和添加按钮呢? 其实也简单, 我们继续往下看.
修改标题
我们在 BaseActivity 中再添加一个抽象方法, 并在初始化 Toolbar 那一处调用我们写的这个抽象方法.
public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_base); initView(); } private void initView() { // 绑定控件 Toolbar toolbar = findViewById(R.id.toolbar); FrameLayout container = findViewById(R.id.container); // 初始化设置 Toolbar toolbar.setTitle(setTitle()); setSupportActionBar(toolbar); // 将继承了 BaseActivity 的布局文件解析到 container 中, 这样 BaseActivity 就能显示 MainActivity 的布局文件了 LayoutInflater.from(this).inflate(getContentView(), container); } /** * 获取要显示内容的布局文件的资源 id * * @return 显示的内容界面的资源 id */ protected abstract int getContentView(); /** * 设置标题 * * @return 要显示的标题名称 */ protected abstract String setTitle(); }
修改 MainActivity.java
我们还是像刚才一样覆写 setTitle() 方法, 并在返回值输入我们想要显示的标题
public class MainActivity extends BaseActivity { @Override protected int getContentView() { return R.layout.activity_main; } @Override protected String setTitle() { return "我是 MainActivity 的标题"; } }
这个时候再运行以下你的程序就会出现你设置的标题了.
那么现在你可能又会问了, 如果我想对 Toolbar 添加一个返回按钮, 并能对他进行操作应该怎么办?(我不想写了, 你也别问了!)其实很简单, 在 BaseActivity 里自定义一个接口, 在子类中设置这个接口的实例就行.
显示返回按钮
我们先给 Toolbar 显示返回按钮, 通过 getSupportActionBar() 得到 ActionBar 的实例, 再调用 ActionBar 的 setDisplayHomeAsUpEnabled(true) 方法让返回按钮显示出来.
Toolbar 最左侧的按钮是叫做 HomeAsUp, 默认是隐藏的, 并且它的图标是一个返回箭头. 还有一种 setNavigationcon() 方法也能设置图标, 具体可以查找 Toolbar 的文档说明
private void initView() { // 绑定控件 Toolbar toolbar = findViewById(R.id.toolbar); FrameLayout container = findViewById(R.id.container); // 初始化设置 Toolbar toolbar.setTitle(setTitle()); setSupportActionBar(toolbar); // 将继承了 BaseActivity 的布局文件解析到 container 中, 这样 BaseActivity 就能显示 MainActivity 的布局文件了 LayoutInflater.from(this).inflate(getContentView(), container); // 显示返回按钮 ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } // 初始化 init(); }
自己定义一个接口并声明
这里我就用截图显示代码片段
设置监听事件
打开 MainActivity.java 文件, 覆写 init() 方法, 并调用父类的 setBackOnClickListener() 方法.
这里我用了 lambda 表达式, 这是 java 8 才支持的, 默认项目是不支持的, 你在 build.gradle 中需要声明一下.
@Override protected void init() { setBackOnClickListener(() -> Toast.makeText(this, "点击了一下返回按钮", Toast.LENGTH_SHORT).show() ); }
运行 App
最后
相信你对 BaseActivity 有了一些简单的了解了, 具体如何使用还是得看你的项目, 不是项目里就一定要写 BaseActivity 和所有 Activity 都要继承 BaseActivity , 我只是将我所理解的 BaseActivity 和大家分享一下. 可能你看完了这一篇文章发现还是没能理解, 在这里我想说声抱歉, 可能有些地方讲的不够通俗易懂或是讲解有误, 还请您多多指教, 我会虚心接受并及时改正(就算是讲错了我也不会改).
Demo 的 GitHub 地址:
https://github.com/lmx0206/BaseDemo
Demo 的 Gitee 地址:
https://gitee.com/Leungmx/BaseDemo
来源: https://blog.csdn.net/weixin_43139065/article/details/105360414