总结
最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司20年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
2、 main组件的gradle文件中,apply plugin使用的是com.android.application
3、其他业务模块(组件A、组件B、组件C、common组件等),apply plugin使用的是com.android.library
四、组件集成
各个组件都建立完成之后,接下来可以把组件集成到main组件中,集成非常简单,只需在main组件的gradle文件中添加dependencies{}配置,添加如下语句:
dependencies {
…
//集成组件A
implementation project(‘:modulea’)
//集成组件B
implementation project(‘:moduleb’)
//集成组件C
implementation project(‘:modulec’)
}
如下图:
五、组件资源共享
1、在common组件的build.gradle文件中,添加android 配置,如下:
android {
//省略前面的代码…
repositories {
flatDir {
dirs ‘libs’
}
}
}
在各个需要调用公共common组件的组件build.gradle文件中,也添加android 配置,如下:
android {
//省略前面的代码…
repositories {
flatDir {
dirs ‘…/common/libs/’, ‘libs’
}
}
}
2、common组件里引入各种类库的时候必须用api,而不是用implementation,原因:
implementation编译的依赖只作用于当前的module,即common组件模块中使用implementation编译的三方库只对common模块起作用,main组件模块中无法使用该三方库。
3、关于组件资源共享,举个简单示例:例如图片都是存放到公共的common组件的res里,那么如何在组件A、组件B、组件C里使用呢?
使用方法如下:
- 打开各组件的build.gradle文件,在dependencies{}里添加如下代码即可:
dependencies {
…
implementation project(‘:common’)
}
- 如此一来,就能在组件A里调用common组件的图片资源了
4、同样的道理, 组件A、 组件B、 组件C的颜色代码也可以直接调用公共common组件里colors.xml的代码
5、我们可以把其他第三方库、自定义view、工具类、公用资源都放进公共common组件里,也就是说组件A、组件B、组件C里build.gradle所引入的类库,都可以放到common组件里的dependencies{}里
6、所以各个业务组件里面的build.gradle文件的dependencies{}配置简化后,就变成了下面这样:
7、通过以上解说,大家应该都明白了吧,图片、xml这些(value目录下的各种xml文件),都可以放到公共common组件里,然后再被其他组件引用。对于全局共用的style.xml文件,我们更应该把它放在common组件中,例如我们的项目theme,本来是放在main组件的style里面,我们可以把它移到common中,这样其他组件调试时,作为一个单独的项目,也能和主项目有一样的主题。总而言之,所有你认为可以被各个组件共享的资源,都可以放在common组件中。
六、往组件里添加Fragment
1、以组件A为例,在组件A里添加一个包fragment
2、在fragment包右键 → New → Fragment →Fragment(Blank)
3、 填写Fragment碎片名称,勾选创建xml文件,如下:
4、对应的fragment_module_a.xml文件代码:
<FrameLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
<ImageView
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:scaleType=“centerCrop”
android:src=“@drawable/a” />
<TextView
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:gravity=“center”
android:padding=“5dp”
android:text=“组件A”
android:background=“@color/green”
android:textColor=“@android:color/white”
android:textSize=“24dp” />
5、其他组件也类似组件A一样,创建一个Fragment碎片,然后添加不同的背景图片即可。
6、main组件里添加导航和Fragment容器,main组件里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”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:id=“@+id/container”
android:orientation=“vertical”>
<FrameLayout
android:id=“@+id/content”
android:layout_width=“match_parent”
android:layout_height=“0dp”
android:layout_weight=“1”>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id=“@+id/navigation”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_gravity=“bottom”
android:background=“?android:attr/windowBackground”
app:menu=“@menu/navigation” />
7、res下创建一个menu目录,里面添加一个navigation.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?><item
android:id=“@+id/navigation_a”
android:icon=“@drawable/home”
android:title=“组件A” />
<item
android:id=“@+id/navigation_b”
android:icon=“@drawable/video”
android:title=“组件B” />
<item
android:id=“@+id/navigation_c”
android:icon=“@drawable/me”
android:title=“组件C” />
navigation.xml里调用的icon图片分别放到drawable和drawable-24目录里,最终主APP的MainActivity界面如下图:
8、MainActivity.java的代码如下:
package net.zy13.module.demo;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.MenuItem;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import net.zy13.module.modulea.fragment.ModuleAFragment;
import net.zy13.module.moduleb.fragment.ModuleBFragment;
import net.zy13.module.modulec.fragment.ModuleCFragment;
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文件的配置也得不同。方法如下:
最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
t_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxMTU1Nzc5Njk=,size_16,color_FFFFFF,t_70)
4、接下来还得修改 AndroidManifest.xml,当把一个module设置为application时,AndroidManifest.xml需要包含一个app所需要的属性,例如app的icon、theme、launch Activity这些属性设置,而当module为library时,这些属性就都不需要用到,所以当我们处于不同模式时,AndroidManifest.xml文件的配置也得不同。方法如下:
最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
[外链图片转存中…(img-1zgXZacG-1715662257589)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!