Android组件化开发简单示例,2024华为Android面试真题解

public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {

//定义碎片集合

private Fragment[] fragments = new Fragment[3];

//当前显示的fragment的索引位置

private int currentIndex = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initFragment();

BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);

navigation.setOnNavigationItemSelectedListener(this);

}

/**

  • 初始化Fragment碎片

*/

private void initFragment() {

if (fragments[0] == null) {

fragments[0] = new ModuleAFragment();

getSupportFragmentManager().beginTransaction().add(R.id.content, fragments[0], “moduleA”).commit();

} else {

getSupportFragmentManager().beginTransaction().show(fragments[0]);

}

}

/**

  • 导航选择事件

  • @param item

  • @return

*/

@Override

public boolean onNavigationItemSelected(@NonNull MenuItem item) {

switch (item.getItemId()) {

case R.id.navigation_a:

if (currentIndex == 0) return true;//如果已经是当前的fragment,不用切换

FragmentTransaction transition0 = getSupportFragmentManager().beginTransaction();

hideAndShow(0,transition0);

return true;

case R.id.navigation_b:

if (currentIndex == 1) return true;//如果已经是当前的fragment,不用切换

FragmentTransaction transition1 = getSupportFragmentManager().beginTransaction();

if (fragments[1] == null) {

fragments[1] = new ModuleBFragment();

transition1.add(R.id.content, fragments[1], “moduleB”);

}

hideAndShow(1,transition1);

return true;

case R.id.navigation_c:

if (currentIndex == 2) return true;//如果已经是当前的fragment,不用切换

FragmentTransaction transition2 = getSupportFragmentManager().beginTransaction();

if (fragments[2] == null) {

fragments[2] = new ModuleCFragment();

transition2.add(R.id.content, fragments[2], “modulec”);

}

hideAndShow(2,transition2);

return true;

}

return false;

}

/**

  • 除了指定的fragment不hide,其他fragment全hide

  • @param expectIndex 指定的fragment在fragments中的位置

  • @param transition

*/

private void hideAndShow(int expectIndex,FragmentTransaction transition) {

for (int i = 0; i < fragments.length; i++) {

if (i != expectIndex && fragments[i] != null) {

transition.hide(fragments[i]);

}

}

transition.show(fragments[expectIndex]);

transition.commit();

currentIndex = expectIndex;

}

}

9、Run运行项目,最终效果如下图,点击导航,可以切换到对应的组件上:

七、各个组件单独开发(测试)

前面我们把各个组件集成到main组件中,现在我们把组件拆分出来,单独开发,开发测试完成后,再把组件集成到main组件中,最后发布。组件单独出来开发的方法就是:在build.gradle文件中,把apply plugin: ‘com.android.library’,改成apply plugin: ‘com.android.application’,也就是把其library模式改为application模式,因为只有application才可以单独运行,library必须依靠application才能运行。

那么问题来了?

组件单独开发时,我们需要改build.gradle的apply plugin模式,等要集成到main组件时,又得改回来,如果这样子手工去改,组件一多,修改起来比较麻烦,也不优雅。优雅的解决办法就是设置一个开关,打开时,就是application模式,可以单独开发;关闭时,就是library模式,可以集成到main组件中。现在按我下面的步骤来实现:

1、在项目根目录下,有一个build.gradle文件,在这个文件最末尾添加一个ext {}配置,然后在ext配置里设定一个常量isDebug,值设为true

ext {

/**

  • 组件调试模式

  • isDebug = true 是组件模块,说明是单独的App

  • isDebug = false是集成模式,说明是依赖Lib

  • 每次更改“isDebug”的值后,需要点击 “Sync Project” 按钮

*/

isDebug = true

}

2、build.gradle里设置了isDebug常量后,我们项目中的其他build.gradle文件都可以把这个常量读取出来,所以我们可以在其他组件的build.gradle文件中,读取该常量的值,动态设置apply plugin,代码如下:

if(isDebug){

apply plugin: ‘com.android.application’

}else{

apply plugin: ‘com.android.library’

}

3、这样子设置之后,当我们需要切换模式时,只需要修改项目根目录下build.gradle文件中isDebug常量的值,修改完成之后,点击Project sync按钮同步一下即可。如果有报错,那么还有个地方需要修改一下,就是main组件的build.gradle文件,我们把module的模式改成了application,main组件就不能引入application,引入的话就会报错,所以当是debug调试模式时,这里就不引入该组件,以免报错。所以在集成组件前,要先判断是什么模式,如下图:

4、接下来还得修改 AndroidManifest.xml,当把一个module设置为application时,AndroidManifest.xml需要包含一个app所需要的属性,例如app的icon、theme、launch Activity这些属性设置,而当module为library时,这些属性就都不需要用到,所以当我们处于不同模式时,AndroidManifest.xml文件的配置也得不同。方法如下:

(1)、Android目录模式切换到Project目录模式

(2)、 在各个组件的src文件夹中新创建一个debug目录,再把我们用于debug调试的AndroidManifest.xml文件放进去

(3)、调试用的AndroidManifest.xml文件可以直接复制manifests目录里的,然后添加application的基本信息,如下:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=“http://schemas.android.com/apk/res/android”

package=“net.zy13.module.modulea”>

<application

android:allowBackup=“true”

android:icon=“@mipmap/ic_launcher”

android:label=“@string/app_name”

android:roundIcon=“@mipmap/ic_launcher_round”

android:supportsRtl=“true”

android:theme=“@style/AppTheme”>

以上内容会有很多错误提示,其实提示的无非就是资源找不到,既然前面我们已经创建了公共的common组件,那么我们只需要把main组件中相应的资源移动到common组件中就可以了。

5、接下来在各个组件的build.gradle文件中,指定不同模式下使用的AndroidManifest.xml文件,在android {}里添加如下代码:

sourceSets {

main {

if (isDebug) {

manifest.srcFile ‘src/debug/AndroidManifest.xml’

}else{

manifest.srcFile ‘src/main/AndroidManifest.xml’

//集成开发模式下排除debug文件夹中的所有Java文件

java {

exclude ‘debug/**’

}

}

}

}

6、以上设置完成,并且sync project(同步项目)之后,各个组件会是这样的目录结构:

7、在各个组件里创建一个用于调试启动的MainActivity活动,然后把fragment加载到activity_main.xml里,所对应的activity_main.xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>

<fragment xmlns:android=“http://schemas.android.com/apk/res/android”

android:name=“net.zy13.module.modulea.fragment.ModuleAFragment”

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

8、添加MainActivity活动后,我们还需要手动设置该活动为入口,打开src/debug/目录下的AndroidManifest.xml文件,修改MainActivity的配置如下:

<activity

android:name=“.MainActivity”>

9、以上步骤完成之后,组件就可以单独作为一个app来开发测试了,android studio的运行app里面,同时多了几个可运行的项目,如下图:

八、统一项目版本号

各个组件的build.gradle文件中,有很多版本号。为了避免每次修改都得同时修改多份build.gradle文件,也避免不同的组件使用的版本不一样,导致冲突,所以我们可以把这些版本号统一管理起来,方法如下:

1、在项目根目录下的build.gradle文件中,定义版本号常量

ext {

/**

  • 组件调试模式

  • isDebug = true 是组件模块,说明是单独的App

  • isDebug = false是集成模式,说明是依赖Lib

  • 每次更改“isDebug”的值后,需要点击 “Sync Project” 按钮

*/

isDebug = true

//版本号

android = [

compileSdkVersion: 30,

buildToolsVersion: “30.0.0”,

minSdkVersion : 15,

targetSdkVersion : 30,

versionCode : 1,

versionName : “1.0”

]

}

2、然后在各个组件的build.gradle文件中,做这样的修改:

android {

compileSdkVersion rootProject.ext.android.compileSdkVersion

buildToolsVersion rootProject.ext.android.buildToolsVersion

defaultConfig {

minSdkVersion rootProject.ext.android.minSdkVersion

targetSdkVersion rootProject.ext.android.targetSdkVersion

versionCode rootProject.ext.android.versionCode

versionName rootProject.ext.android.versionName

}

}

九、使用路由实现组件之间的通信

通过前面的学习,我们已经知道组件可以拆分了,但是当他们集成到main组件中时,还是需要一定的通信,例如业务A需要调用到业务B的一个页面,甚至进行传参。但是在“组件化”模式下,业务A和业务B是完全分开的,在业务A的认知里,根本就不存在业务B,也就没办法直接调用。当然,如果要业务A与业务B可以直接通信,互相引入就可以,但是这样的话,项目耦合性太高,架构也混乱,会把“组件化”的所有优点都一一撇掉,所以我们应该用另外一种方式来处理。

这里需要引入一个概念:路由”,就如我们实际访问网络一样,我们电脑发送的请求都经过路由器转发,在“组件化”中,我们也可以设置这么一个中转站,来统一处理不同组件之间的调用关系。关于路由的用法,后面会补充,这里先用最简单的方法,来实现组件之间的调用(页面跳转),代码如下:

try {

Class c= Class.forName(“net.zy13.module.modulea.MainActivity”);

Intent intent = new Intent(context,c);

startActivity(intent);

} catch (ClassNotFoundException e) {

Log.e(“组件”,“组件未集成,无法跳转”);

}

以上代码是通过完整的类名来进行跳转,在debug模式下,调用其他组件时,找不到对应组件,不会直接报错,只是提示“未集成,无法跳转”。我们可以把这个方法写成一个工具类,放在common组件中,方法如下:

1、在common组件里创建一个工具类PageUtils.java,代码如下:

import android.content.Context;

import android.content.Intent;

import android.util.Log;

/**

  • @author 安阳 QQ:15577969

  • @version 1.0

  • @team 美奇软件开发工作室

  • @date 2020/11/12 11:55

*/

public class PageUtils {

/**

  • 页面跳转

  • @param context

  • @param className

*/

public static void jump(Context context, String className){

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

资源分享

  • 最新大厂面试专题

这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等

  • 对应导图的Android高级工程师进阶系统学习视频
    最近热门的,NDK,热修复,MVVM,源码等一系列系统学习视频都有!

从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-zcLaZGPf-1711049063023)]
[外链图片转存中…(img-dc9wEtnx-1711049063024)]
[外链图片转存中…(img-oU0FyQJm-1711049063024)]
[外链图片转存中…(img-tp28L2FL-1711049063025)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-Nc467FDk-1711049063025)]

资源分享

  • 最新大厂面试专题

这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等

[外链图片转存中…(img-j0gouFNB-1711049063026)]

  • 对应导图的Android高级工程师进阶系统学习视频
    最近热门的,NDK,热修复,MVVM,源码等一系列系统学习视频都有!

[外链图片转存中…(img-Xj4gikKN-1711049063027)]

下载方法:点赞+关注后 点击【Android高级工程师进阶学习】即可领取!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值