Grundlegende Fähigkeiten für fortgeschrittene Ingenieure: Vollständige Analyse der Architektur von Android-Komponenten! (Mit Video + E-Book + Studiennotizen teilen)

Vorwort

Heutzutage denken die meisten Apps beim Refactoring an Komponentisierung oder Modularisierung, insbesondere in großen Fabriken oder einigen großen Unternehmen. Es ist besonders wichtig, die Entkopplung und Optimierung von Apps zu erleichtern. Nach meinem Verständnis bedeutet Komponentisierung, jedes Modul einzeln mit derselben Funktion zu installieren und es dann in Form einer Bibliothek zu verwenden, die unser Haupt-App-Modul aufrufen kann. Im Haupt-App-Modul wird lediglich keine Geschäftslogik ausgeführt Verpackung Nun, zusätzlich zum Haupt-App-Modul gehen die anderen Module zu ihren jeweiligen Häusern zurück, finden ihre eigenen Mütter und machen ihre eigene Geschäftslogik. Einfach ausgedrückt, die Komponentisierung besteht darin, dass Bibliothek und Anwendung untereinander wechseln können. und libray können als separate App ausgeführt werden. Es kann auch als abhängige Bibliothek zur Haupt-App aufgerufen werden. Diese Art von Konstruktionsidee kann die Entwicklungseffizienz erheblich verbessern, die Kosten für die Codewartung senken, die Codekopplung verringern und das Verständnis für andere erleichtern.

der ganze Rahmen

  • common: Der grundlegende Komponententeil, der nichts mit dem Geschäft zu tun hat und auf den sich alle Komponenten zusammen verlassen müssen, z. B.: Kapselung von Netzwerkanforderungen, Kapselung zum Laden von Bildern, UI-bezogene Basisklassen, Tool-Sets usw. (Natürlich Diese Inhalte können je nach Schichtprinzip-Modul auf verschiedenen Fundamenten platziert werden.
  • router-comp: routengesteuerte Komponente, die die Routing-Arbeit des gesamten Projekts übernimmt
  • comp1: Geschäftskomponente 1, z. B. Videokomponente, kann unabhängig ausgeführt werden
  • comp2: Geschäftskomponente 2, z. B. Nachrichtenkomponente, kann unabhängig ausgeführt werden
  • comp3: Geschäftskomponente 3, z. B. Videokomponente, kann unabhängig ausgeführt werden
  • App: Shell-Projekt, mit dem jede Komponente zu einer fertigen App zusammengefügt wird

Probleme bei der Komponentisierung

  • Integration von Integrationsmodus und Komponentenmodus (Hot Plug)
  • Seitensprung (Routing) zwischen Komponenten
  • Kommunizieren Sie zwischen Komponenten und rufen Sie sich gegenseitig an
  • Verpackungsverwirrung

Komponentisierte Realisierung

Als Antwort auf die oben genannten Probleme werden wir ihre Lösungen nacheinander nacheinander erläutern. Nachdem Sie diese Probleme gelöst haben, werden Sie feststellen, dass Sie ein komponentenbasiertes Projekt erstellt haben. Die folgende Abbildung zeigt eine vollständige komponentenbasierte Projektstruktur: Common ist das grundlegende Komponentenmodul, das als Bibliothek vorhanden ist und von dem alle Komponenten abhängig sein müssen. Comp1 und comp2 sind als Komponenten vorhanden und können als Bibliothek oder als Modul konfiguriert werden, das unabhängig ausgeführt werden kann ; App ist eine Shell, durch Montage Komponenten erkennen ihren Wert.

Integration von Integrationsmodus und Komponentenmodus (Hot Plug)

Das Android-Projekt wird durch gradle erstellt, und die unterschiedliche Leistung des Moduls wird durch Konfigurieren des gradle jedes Moduls realisiert. Das Modul von Android Studio hat zwei Attribute, nämlich:

  • Anwendungsattribut: Kann unabhängig ausgeführt werden. Dies ist unsere App
  • Bibliotheksattribut: Kann nicht unabhängig ausgeführt werden, die Bibliothek ist abhängig von der App

Das Modulattribut wird über die Gradle-Datei in ihrem Verzeichnis konfiguriert. Wenn das Modulattribut Anwendung ist, existiert das Modul als vollständige App und kann unabhängig ausgeführt werden, um das Kompilieren und Debuggen zu erleichtern. Wenn das Modulattribut Bibliothek ist, wird das Modul als verwendet Eine abhängige Bibliothek. Das Shell-Projekt hängt von einer App ab und wird zu einer App zusammengestellt. Wie können diese beiden Modi automatisch konvertiert werden? Wenn Sie die Konfiguration jeder Komponente bei jedem Moduswechsel manuell ändern, ist es akzeptabel, wenn weniger Komponenten vorhanden sind, und es ist sehr unpraktisch, wenn mehr Komponenten vorhanden sind. Lassen Sie uns darüber sprechen, wie eine automatische Konvertierung zwischen den beiden Modi erreicht wird. 1. Deklarieren Sie zunächst globale Konfigurationsvariablen, um die Eigenschaften des Moduls (App oder Bibliothek) zu identifizieren. Deklarieren Sie beispielsweise die boolesche Variable ext.isModule in der Datei build.gradle im Projektverzeichnis. True repräsentiert die Komponente als eigenständige App und false steht für Die Komponente ist eine abhängige Bibliothek, wie unten gezeigt

buildscript {
 ext.kotlin_version = '1.3.21'
 ext.isModule = true //true-每个组件都是单独的module,可独立运行 false-组件作为library存在
 repositories {
   google()
   jcenter()
 }
}

2. Konfigurieren Sie die Datei build.gradle der Komponente

//1 if (rootProject.ext.isModule) {
//可独立运行的app
apply plugin: 'com.android.application'
} else{
//被依赖的library
apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion 28
defaultConfig {

//applicationId "com.study.comp1" //2 如果没有,默认包名为applicationId
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
//3
sourceSets {
main {
if(rootProject.ext.isModule){
manifest.srcFile 'src/main/java/module/AndroidManifest.xml'
} else{
manifest.srcFile 'src/main/java/library/AndroidManifest.xml'
java {//移除module包下的代码
exclude 'module'
}
}
}
}
}

Das Obige ist Teil des Codes des abgefangenen Komponentengradles, der den gesamten Inhalt enthält, der für die Komponentisierung konfiguriert werden muss, und jeder Punkt wird kommentiert

  • Hinweis 1: Wie oben erwähnt, legen Sie gemäß dem Wert von isModule die Attribute des Moduls als App oder Bibliothek fest
  • Hinweis 2: Wenn das Modulattribut Bibliothek ist, kann die Anwendungs-ID nicht festgelegt werden. Wenn es sich um eine App handelt und die Anwendungs-ID nicht festgelegt ist, lautet der Standardpaketname applicationId. Aus praktischen Gründen wird hier die Anwendungs-ID nicht festgelegt
  • Hinweis 3: Android Studio generiert für jedes Modul die entsprechende Datei AndroidManifest.xml und deklariert die erforderlichen Berechtigungen, vier Hauptkomponenten, Daten usw.; Wenn das Modulattribut App ist, muss die entsprechende Datei AndroidManifest.xml einen vollständigen App-Speicherort haben Alle erforderlichen Konfigurationen, insbesondere die Aktivitäten, die Anwendung und Start deklarieren. Wenn das Modulattribut Bibliothek ist und jede Komponente ihre eigene Anwendung deklariert und Aktivität startet, treten während der Zusammenführung Konflikte auf, und die Kompilierung wird nicht bestanden Sie müssen eine AndroidManifest.xml-Datei für das aktuelle Modul neu definieren, die Aktivität der Anwendung nicht deklarieren und starten und dann den Pfad von AndroidManifest.xml gemäß dem Wert von isModule angeben. Daher gibt es die Möglichkeit, in Anmerkung 3 zu schreiben. Um Namenskonflikte im integrierten Modus zu vermeiden, ist es eine gute Möglichkeit, jede Datei mit einem eigenen Modulnamenpräfix zu benennen. Die folgende Abbildung zeigt das Verzeichnis des Moduls

Wenn Sie das Modulattribut wechseln müssen, ändern Sie den in Schritt 1 deklarierten Variablenwert und kompilieren Sie ihn erneut

Seitensprung (Routing) zwischen Komponenten

In der komponentenbasierten Architektur sind verschiedene Komponenten ausgeglichen, und es besteht keine wechselseitige Beziehung (siehe das Architekturdiagramm am Anfang des Artikels). Angenommen, Sie möchten zu der Seite in Komponente B in Komponente A springen. Wenn Sie Intent zum expliziten Springen verwenden, funktioniert dies nicht. Und jeder weiß, dass die implizite Sprungverwaltung von Intent sehr unpraktisch ist, sodass Arouter erschien. Und es gibt eine Starke technische Teamunterstützung, Sie können es mit Vertrauen verwenden. Wie wende ich Arouter in einer komponentenbasierten Architektur an? Lassen Sie uns unten im Detail sprechen

1. Abhängigkeitsverarbeitung

Abhängig von Arouter in der allgemeinen Komponente und konfigurieren Sie die Kompilierungsparameter, führen Sie das aouter-Compiler-Plug-In in der Geschäftskomponente ein und konfigurieren Sie gleichzeitig die Compilerparameter. Das Folgende ist ein Teilfragment der Gradle-Datei der allgemeinen Komponente

//配置arouter编译器参数,每个组件都需配置 kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}

dependencies {
//arouter api,只需在common组件中引入一次
api('com.alibaba:arouter-api:1.4.1') {
exclude group: 'com.android.support'
}
//arouter编译器插件,每个组件都需引入
kapt 'com.alibaba:arouter-compiler:1.2.2'
}

2. Initialisierung und Codierungsrealisierung

In der Komponentenarchitektur treten häufig Situationen auf, in denen die Komponente den globalen Kontext verwenden muss. Wenn das Komponentenattribut eine App ist, kann es durch Anpassen der Anwendung implementiert werden. Wenn das Komponentenattribut eine Bibliothek ist, kann die Anwendung nicht aufgerufen werden, da dies die Komponente ist Abhängig von der App. Instanz, und es gibt keine Anwendung. Daher besteht die hier angegebene Lösung darin, eine BaseApplication in der gemeinsamen Komponente zu erstellen und dann die Anwendung im integrierten Modus (Komponentenmodus) die BaseApplication erben zu lassen, um den globalen Kontext zu erhalten in der BaseApplication und einige Initialisierungen durchführen Um zu funktionieren, muss Arouter initialisiert werden. Das Folgende ist die BaseApplication, die in der allgemeinen Komponente deklariert ist.

abstract class BaseApplication : Application() {

companion object {
var _context: Application? = null
//获取全局Context
fun getContext(): Application {
return _context!!
}
}
override fun onCreate() {
super.onCreate()
_context = this
//初始化Arouter
initARouter()
//初始化其他第三方库
}
private fun initARouter() {
if (BuildConfig.DEBUG) {
ARouter.openDebug()
ARouter.openLog()
}
ARouter.init(this)
}
override fun onTerminate() {
super.onTerminate()
//清理Arouter注册表
ARouter.getInstance().destroy()
}
}

Entsprechend den Routing-Eigenschaften von Arouter können Sie die Seite nach der Initialisierung mit der Annotation @Route registrieren und dann die Arouter-API aufrufen, um den Seitensprung zu realisieren (der sogenannte komponentenübergreifende Seitensprung bezieht sich hier nicht auf den integrierten Modus Komponentenmodus), Es spielt keine Rolle, ob sie sich unter derselben Komponente befinden. Angenommen, wir möchten von der Seite der Komponente 1 mit Parametern zur Seite der Komponente 2 springen. Weitere Informationen finden Sie im folgenden Beispiel

/**
* 在组件2中通过@Route注解注册该页面
*/ @Route(path = "/comp2/msg",name = "我是组件2的MSGActivity")
class Comp2MsgActivity : BaseActivity() {
//传递过来的参数
@Autowired(name = "msg")
@JvmField
var msg: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//注入传递的参数
ARouter.getInstance().inject(this)
setContentView(R.layout.comp2_activity_msg)
comp2_msg_msg.text = msg!!
}
}

//在组件1中发起跳转命令
ARouter.getInstance()
.build("/comp2/msg")
.withString("msg", "hello Im from Comp1")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()

Das Obige hat einen einfachen Seitensprung über Komponenten abgeschlossen, was nur die grundlegende Verwendung von Arouter ist. Nachdem wir das Problem der Seitensprünge zwischen Komponenten gelöst haben, werfen wir einen Blick auf die Implementierung der Kommunikation zwischen Komponenten und das Aufrufen der Dienste des jeweils anderen. Die Kommunikation zwischen Komponenten, das Aufrufen der Dienste des anderen , die Kommunikationsfunktionen und die Routingfunktionen zwischen Komponenten haben etwas gemeinsam, dh sie werden alle durch die Grundfunktionen von Arouter realisiert. Die Arouter-Treiberschicht definiert die von jeder Komponente bereitgestellten Schnittstellen und implementiert sie dann die Schnittstelle im eigenen Modul der Komponente. Rufen Sie andere Komponentendienste über Arouter auf. Angenommen, wir müssen den Dienst in Komponente 1 in Komponente 2 aufrufen, was als die folgenden 3 Punkte zusammengefasst werden kann

  • Definieren Sie die Schnittstelle: Definieren Sie die Schnittstelle CompServer1, die von Komponente 1 in der allgemeinen Komponente bereitgestellt wird. Beachten Sie, dass der Schnittstellentyp der Arouter-Vorlagentyp IProvider ist
/**
* 组件1对外提供的接口
*/
interface CompServer1 : IProvider {
fun showMsg(msg: String)
}

  • Schnittstelle implementieren: Implementieren Sie die oben in comm1 definierte Schnittstelle und registrieren Sie sich über die Annotation @Route
@Route(path = "/comp1/server",name = "comp1对外提供的服务")
class CompServer : CompServer1 {
var mContext: Context? = null
override fun showMsg(msg: String) {
Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show()
}
override fun init(context: Context?) {
this.mContext = context!!
}
}
  • Aufrufen des Dienstes: Rufen Sie nach Abschluss der Definition und Implementierung der Schnittstelle von Komponente 1 die Schnittstelle auf, wo dies in Komponente 2 erforderlich ist
val server1 = ARouter.getInstance().build("/comp1/server").navigation() as CompServer1
server1.showMsg("我从comp2吊起了comp1的接口")

Fühlt es sich einfach an? ? Das ist richtig, es ist so einfach, beeil dich und benutze es! Haha

Verpackungsverwirrung

Wenn man von Verschleierung spricht, fragen sich manche Leute vielleicht, ob sie in verschiedene Komponenten eingemischt werden kann. Diese Verwirrung wird nicht empfohlen! ! Da die Komponente von gradle im integrierten Modus in ein aar-Paket vom Release-Typ integriert ist, ist es zu diesem Zeitpunkt schwierig, die Ursache des Fehlers gemäß dem Protokoll zu verfolgen, wenn der Code einen Fehler aufweist Verschiedene Komponenten werden separat verwechselt Es ist sehr unpraktisch, sie zu warten und zu ändern, weshalb es nicht empfohlen wird, buildType in Geschäftskomponenten zu konfigurieren. Daher wird die Code-Verschleierung des Komponentenprojekts im integrierten Modus im App-Shell-Projekt platziert, und jede Geschäftskomponente ist nicht für die Verschleierung konfiguriert. Aktivieren Sie im integrierten Modus die Verschleierung im Release-Erstellungsmodus der .gradle-Datei des App-Shell-Projekts. Die andere buildType-Konfiguration entspricht der eines normalen Projekts. Die verschleierte Datei wird unter dem App-Shell-Projekt und der Code-Verschleierung abgelegt jeder Komponente wird in die verschleierte Datei gelegt.

Zu guter Letzt

Oben haben wir die verschiedenen Probleme der Komponentisierung nacheinander gelöst. Bisher haben wir ein einfaches Projekt für eine komponentenbasierte Architektur erstellt. Ist es nicht schwierig, es zu realisieren, ohne es zu wissen? Lassen Sie mich nun die Vorteile der Komponentisierung zusammenfassen.

  • Entkopplung: 90% des Geschäftskomponentencodes sind vom Projekt entkoppelt, also 90% statt 100%, da die Geschäftskomponente die offene Schnittstelle in der gemeinsamen Komponente deklarieren muss. Gibt es eine Möglichkeit, eine vollständige Entkopplung zu erreichen? Was? ? Es wurde noch kein besserer Weg gefunden. . .

  • Verbesserung der Entwicklungseffizienz: Aufgrund des Vorteils der Entkopplung können sich die Teammitglieder nur auf die Komponenten konzentrieren, für die sie verantwortlich sind, und die Entwicklungseffizienz ist höher. Außerdem kompilieren sie nur ihre eigenen Module während des Komponentenentwicklungsprozesses, was die Kompilierungszeit erheblich verkürzt und vermeidet langes Warten auf Kompilierungssituation.

  • Klare Struktur: Unter der Voraussetzung einer klaren Trennung der Geschäftskomponenten wird die Projektstruktur äußerst klar, was für die Gesamtkontrolle sehr praktisch ist.

Um Ihnen das Erlernen des Prinzips der komponentenbasierten Architektur und der Interpretation des zugrunde liegenden Quellcodes zu erleichtern, habe ich eine Reihe von komponentenbasierten Lernmaterialien für Video + E-Book + Studiennotizen gesammelt und organisiert. Das Video ist das "Learning Componentization from Scratch" und das komponentenbasierte Lern-E-Book "Android Componentized Architecture" sowie eine Reihe von "Open Source Framework-Analyse- und Studiennotizen von Drittanbietern", einschließlich Plug-In, die von Iqiyi Senior Engineer unterrichtet werden Lance. Komponentenanalyse, Hotfix und andere beliebte Hinweise zur Framework-Analyse von Drittanbietern!

Freunde, die die oben genannten Lernmaterialien benötigen, können hier klicken, um sie kostenlos zu erhalten, nachdem sie + einen Kommentar mögen !

Komponentiertes Lernvideo
Komponentisiertes E-Book
Open Source Framework zur Interpretation des Katalogs und eines Teils des Analyseinhalts

Freunde, die die oben genannten Lernmaterialien benötigen, können hier klicken, um sie kostenlos zu erhalten, nachdem sie + einen Kommentar mögen !

Ich denke du magst

Origin blog.csdn.net/star_nwe/article/details/111173661
Empfohlen
Rangfolge