功能
- 版本参数优化:common_config.gradle
- 动态创建Fragment:ViewPager+Fragment
- 动态初始化Application:IBaseAppInit
- 组件间通信:EventBus
- 组件间跳转:ARouter
- 组件化存储:GreenDao
- 组件化权限:PermissionSDK
- 调试优化:isDebugModuleDebug
- Gradle 4.1依赖特性:implementation、API
架构
组件化架构
代码
1.settings.gradle
include ':app', ':modulea', ':moduleb', ':modulec', ':base', ':permission', ':debugmodule'
rootProject.name='ModuleTest'
2.build.gradle(project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
//GreenDao 1
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
3.common_config.gradle(project)
project.ext {
//设置App配置
setAppDefaultConfig = {
extension ->
//引用Application插件库
extension.apply plugin: 'com.android.application'
//GreenDao 2
extension.apply plugin: 'org.greenrobot.greendao'
extension.description "app"
setAndroidConfig extension.android
setDependencies extension.dependencies
}
//设置Lib配置
setLibDefaultConfig = {
extension ->
//引用lib插件库
extension.apply plugin: 'com.android.library'
//GreenDao 3
extension.apply plugin: 'org.greenrobot.greendao'
extension.description "lib"
setAndroidConfig extension.android
setDependencies extension.dependencies
}
//设置Android配置
setAndroidConfig = {
extension ->
extension.compileSdkVersion 29
extension.buildToolsVersion "29.0.0"
extension.defaultConfig {
minSdkVersion 15
targetSdkVersion 29
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//ARouter 1
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME : extension.project.getName()]
}
}
}
}
//设置依赖
setDependencies = {
extension ->
extension.implementation fileTree(dir: 'libs', include: ['*.jar'])
extension.implementation 'androidx.appcompat:appcompat:1.1.0'
extension.testImplementation 'junit:junit:4.12'
extension.androidTestImplementation 'androidx.test.ext:junit:1.1.1'
extension.androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
//ARouter 2
extension.annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
}
//调试优化 1
//声明单独模块调试变量
isDebugModuleDebug = false
}
4.应用层:App
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
project.ext.setAppDefaultConfig project
android {
defaultConfig {
applicationId "com.tomorrow.moduletest"
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api project(':modulea')
api project(':moduleb')
api project(':modulec')
//调试优化 2
if(!project.ext.isDebugModuleDebug) {
api project(':debugmodule')
}
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.moduletest">
<application
android:name=".MainApplication"
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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
//PageConfig
public class PageConfig {
private static final String ModuleAFragment = "com.tomorrow.modulea.ModuleAFragment";
private static final String ModuleBFragment = "com.tomorrow.moduleb.ModuleBFragment";
private static final String ModuleCFragment = "com.tomorrow.modulec.ModuleCFragment";
private static final String BaseInit = "com.tomorrow.base.BaseInit";
private static final String ModuleAInit = "com.tomorrow.modulea.ModuleAInit";
public static String[] fragmentNames = {
ModuleAFragment,
ModuleBFragment,
ModuleCFragment,
};
public static String[] initModules = {
BaseInit,
ModuleAInit,
};
}
//MainApplication
public class MainApplication extends Application {
private static final String TAG = "MainApplication";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "zwm, onCreate");
initModules();
}
private void initModules() {
Log.d(TAG, "zwm, initModules");
for(String init : PageConfig.initModules) {
try {
Class<?> clazz = Class.forName(init);
IBaseAppInit moduleInit = (IBaseAppInit) clazz.newInstance();
moduleInit.onInit(this);
} catch (ClassNotFoundException e) {
} catch (IllegalAccessException e) {
} catch(InstantiationException e) {
}
}
}
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private List<Fragment> mFragmentList = new ArrayList<>();
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
Log.d(TAG, "zwm, initView");
try {
for(String address : PageConfig.fragmentNames){
Class clazz = Class.forName(address);
Fragment item = (Fragment) clazz.newInstance();
mFragmentList.add(item);
}
}catch (ClassNotFoundException e){
}catch (IllegalAccessException e){
}catch (InstantiationException e){
}
mViewPager = findViewById(R.id.view_pager);
mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), mFragmentList);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setOffscreenPageLimit(3);
}
}
//activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
//ViewPagerAdapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private static final String TAG = "ViewPagerAdapter";
public List<Fragment> fragmentList;
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
this.fragmentList = fragmentList;
}
@Override
public Fragment getItem(int arg0) {
return fragmentList.get(arg0); //显示第几个页面
}
@Override
public int getCount() {
return fragmentList.size(); //有几个页面
}
}
5.业务组件:ModuleA
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
project.ext.setLibDefaultConfig project
android {
defaultConfig {
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api project(':base')
}
//AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.modulea" >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
//ModuleAInit
public class ModuleAInit implements IBaseAppInit {
private static final String TAG = "ModuleAInit";
@Override
public void onInit(Application application) {
Log.d(TAG, "zwm, onInit, application: " + application);
}
}
//ModuleAFragment
public class ModuleAFragment extends Fragment {
private static final String TAG = "ModuleAFragment";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "zwm, onCreateView");
View view = inflater.inflate(R.layout.fragment_modulea,container,false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "zwm, onActivityCreated");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, EventBus post event");
TestEvent event = new TestEvent("Event From ModuleA");
EventBus.getDefault().post(event);
}
}, 2000);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, ARouter start navigation");
ARouter.getInstance().build("/test/activity").navigation();
}
}, 4000);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, GreenDao CRUD");
User user = new User();
user.setName("Tomy");
user.setAge("30");
user.setContent("Android");
BaseInit.getInstance().getDaoSession().insert(user);
Log.d(TAG, "zwm, insert name: Tomy, age: 30, content: Android");
List<User> users = BaseInit.getInstance().getDaoSession().loadAll(User.class);
for(User item : users) {
Log.d(TAG, "zwm, query id: " + item.getId() + ", name: " + item.getName() + ", age: " + item.getAge() + ", content: " + item.getContent());
}
}
}, 6000);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, PermissionSDK");
if(PermissionUtil.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.d(TAG, "zwm, READ_EXTERNAL_STORAGE permission get");
} else {
Log.d(TAG, "zwm, READ_EXTERNAL_STORAGE permission not get");
}
}
}, 8000);
}
}
//fragment_modulea.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is ModuleA Fragment"/>
</RelativeLayout>
6.业务组件:ModuleB
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
project.ext.setLibDefaultConfig project
android {
defaultConfig {
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api project(':base')
}
//AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.moduleb" />
//ModuleBFragment
public class ModuleBFragment extends Fragment {
private static final String TAG = "ModuleBFragment";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "zwm, onCreateView");
View view = inflater.inflate(R.layout.fragment_moduleb,container,false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "zwm, onActivityCreated, EventBus register");
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "zwm, onDestroy, EventBus unregister");
EventBus.getDefault().unregister(this);
}
@Subscribe
public void onEvent(TestEvent event){
Log.d(TAG, "zwm, EventBus onEvent msg: " + event.getMsg() + ", thread: " + Thread.currentThread().getName());
}
}
//fragment_moduleb.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is ModuleB Fragment"/>
</RelativeLayout>
7.业务组件:ModuleC
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
project.ext.setLibDefaultConfig project
android {
defaultConfig {
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api project(':base')
}
//AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.modulec">
<application>
<activity android:name=".ModuleCActivity"/>
</application>
</manifest>
//ModuleCFragment
public class ModuleCFragment extends Fragment {
private static final String TAG = "ModuleCFragment";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "zwm, onCreateView");
View view = inflater.inflate(R.layout.fragment_modulec,container,false);
return view;
}
}
//fragment_modulec.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is ModuleC Fragment"/>
</RelativeLayout>
//ModuleCActivity
@Route(path = "/test/activity")
public class ModuleCActivity extends AppCompatActivity {
private static final String TAG = "ModuleCActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_modulec);
}
}
//activity_modulec.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is ModuleC Activity"/>
</RelativeLayout>
8.业务组件:DebugModule
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
//调试优化 3
if(!project.ext.isDebugModuleDebug){
project.ext.setLibDefaultConfig project //当前为lib
} else{
project.ext.setAppDefaultConfig project //当前为app
}
android {
defaultConfig {
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
//调试优化 4
sourceSets {
main {
if (project.ext.isDebugModuleDebug) {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
}
}
}
}
dependencies {
api project(':base')
}
//src/main/release/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.debugmodule" />
//src/main/debug/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.debugmodule">
<application
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light">
<activity android:name=".DebugModuleActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
//DebugModuleActivity
public class DebugModuleActivity extends AppCompatActivity {
private static final String TAG = "DebugModuleActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_debugmodule);
}
}
//activity_debugmodule.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is DebugModule Activity"/>
</RelativeLayout>
9.基础组件:Base
//build.gradle
apply from: "${rootProject.rootDir}/common_config.gradle"
project.ext.setLibDefaultConfig project
android {
defaultConfig {
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
//EventBus
api 'org.greenrobot:eventbus:3.0.0'
//ARouter 3
api'com.alibaba:arouter-api:1.5.0'
//GreenDao 4
api 'org.greenrobot:greendao:3.2.2'
//PermissionSDK
api project(':permission')
}
//GreenDao 5
greendao {
schemaVersion 1 //指定数据库版本号,更新操作会用到
daoPackage 'com.tomorrow.base.db.greendao' //自动生成的dao的包名,包名默认是entity所在的包
targetGenDir 'src/main/java' //生成数据库文件的目录
}
//AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.base" />
//src/main/java/com.tomorrow.base/IBaseAppInit.java
public interface IBaseAppInit {
void onInit(Application application);
}
//src/main/java/com.tomorrow.base/BaseInit.java
public class BaseInit implements IBaseAppInit {
private static final String TAG = "BaseInit";
private static BaseInit mInstance;
private Application mApplication;
private DaoSession mDaoSession;
public static BaseInit getInstance() {
return mInstance;
}
@Override
public void onInit(Application application) {
Log.d(TAG, "zwm, onInit, application: " + application);
mInstance = this;
mApplication = application;
Log.d(TAG, "zwm, init ARouter");
ARouter.init(application);
initGreenDao();
}
private void initGreenDao() {
Log.d(TAG, "zwm, init GreenDao");
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(mApplication.getApplicationContext(), "tomorrow.db");
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
mDaoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return mDaoSession;
}
}
//src/main/java/com.tomorrow.base/event/TestEvent.java
public class TestEvent {
private String msg;
public TestEvent(String msg) {
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
//src/main/java/com.tomorrow.base/db/User.java
@Entity
public class User {
@Id(autoincrement = true)
private Long id; //主键,自增长
@NotNull
private String name; //名称,不允许为空
private String age;
private String content;
@Generated(hash = 1079760932)
public User(Long id, @NotNull String name, String age, String content) {
this.id = id;
this.name = name;
this.age = age;
this.content = content;
}
@Generated(hash = 586692638)
public User() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
}
//src/main/java/com.tomorrow.base/db/greendao/
DaoMaster、DaoSession、UserDao
10.功能组件:PermissionSDK
//build.gradle
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
//AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.permission" />
//PermissionUtil
public class PermissionUtil {
private static final String TAG = "PermissionUtil";
public static boolean checkSelfPermission(Context context, String permission) {
boolean exist = false;
if(ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
exist = true;
}
Log.d(TAG, "zwm, checkSelfPermission: " + permission + ", exist: " + exist);
return exist;
}
}
网友评论