ピットを回避するための初心者ガイド:Androidコンポーネント開発の詳細な説明

学習目標:

コンポーネント開発、ルーティング構成の習熟度


学習内容:

**コンポーネント開発を使用する前に、まずプロジェクトフレームワーク全体を明確にし、モジュールとビジネス(焦点)を分割する必要があります。そうすれば、良いスタートを切ることで良い結果が得られます。**モジュールが明確に分割されたら、モジュールの構成を開始します。

図に示すように、次の機能を完了する必要があります。

1.モールをクリックしてShoppingModuleに入ります

2. [ログイン]をクリックして、LoginModuleに入ります

3.請求書の赤い領域をクリックして、請求書リスト(他のモジュールのフラグメント)を表示します

(shareModuleはパブリックモジュールです)

ビジネス要件に応じて次のように作成されます。

アプリのgradle.propertiesファイルの下に追加して、モジュールが独立して実行されるかどうかを制御します。

#配置某个组件是否可以独立运行
isShoppingRunAlone = true
isLoginRunALone = true

次に、Appbuild.gradleを構成します。

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
 
android {
    compileSdkVersion 30
    buildToolsVersion "29.0.3"
 
    defaultConfig {
        applicationId "com.example.moduledemo"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
 
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
 
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
 
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
 
    //导入公共模块
    implementation project(':ShareModule')
 
    // 根据gradle中的配置来决定是否引用module
    if (!isLoginRunALone.toBoolean()){
        implementation project(':LoginModule')
    }
    if (!isShoppingRunAlone.toBoolean()){
        implementation project(':ShoppingModule')
    }
 
}

他のモジュールのbuild.gradleファイルの構成を続けます。

if (isShoppingRunAlone.toBoolean()){
    apply plugin: 'com.android.application'
}else {
    apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
 
android {
    compileSdkVersion 30
    buildToolsVersion "29.0.3"
 
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 30
        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'
        }
    }
    sourceSets{
        main{
            // 在独立运行或者作为Libarary调试时,使用不同的AndroidManifest.xml文件
            if (isShoppingRunAlone.toBoolean()){
                manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
            }else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }
}
 
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.0'
    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'
    //导入公共模块
    implementation project(':ShareModule')
 
}

さまざまな動作モードでさまざまなマニフェストファイルを使用します。

対応するモジュールのメインディレクトリに新しいマニフェストフォルダを作成する必要があります(そうしないと、マニフェストファイルを単独で実行しても見つかりません)。

個別に実行されるマニフェストファイルは、次のように設定されます。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.loginmodule">
 
    <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">
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>

次のように、メインモジュールのランタイムマニフェストファイル設定を組み込みます。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.shoppingmodule">
 
    <application>
        <activity android:name=".ShoppingActivity"/>
    </application>
</manifest>

すべての構成が完了したら、gradle.propertiesの変数の値を変更し、コンパイルして構成が正しいかどうか、マニフェストファイルが置き換えられているかどうかを確認できます。実行して、正常かどうかを確認します。

次に、ルーティングの構成を開始します。

多くの人々は、モジュールを参照した後にサブモジュールのアクティビティを直接取得できるのに、なぜルーティングジャンプを使用する必要があるのか​​疑問に思っています。これは、コンポーネント開発が単一のモジュールを独立してコンパイルするためです。メインモジュールがサブモジュールのクラス名を参照している場合、サブモジュールが単独で実行されると、メインモジュールは異常にコンパイルされます。

プロジェクトにサブモジュールを1つだけ含めることはできないことを知っておく必要があります。他のサブモジュールが相互にジャンプしたいときに、ルーティングを使用するにはどうすればよいですか。したがって、ShareModuleでルーティングを構成する必要があります。前の構成では、ShareModuleを各モジュールにインポートしました。

最初の一歩

モジュールに対応するジャンプテンプレートを作成します

import android.content.Context;
import android.os.Bundle;
 
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
 
public interface ILoginService {
    void launch(Context ctx, String targetClass);
 
}
import android.content.Context;
import android.os.Bundle;
 
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
 
public interface IShoppingService {
    void launch(Context ctx, String string);
    Fragment newBillFragment(FragmentManager fragmentManager, int viewId, Bundle bundle);
}

第二段階

対応するモジュールでジャンプロジックと値転送操作を実現します

package com.example.loginmodule;
 
import android.content.Context;
import android.content.Intent;
 
import com.example.sharemodule.ILoginService;
 
 
public class LoginService implements ILoginService {
    @Override
    public void launch(Context ctx, String targetClass) {
        Intent intent = new Intent(ctx, LoginActivity.class);
        ctx.startActivity(intent);
    }
}
package com.example.shoppingmodule;
 
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
 
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
 
import com.example.sharemodule.IShoppingService;
 
 
public class ShoppingService implements IShoppingService {
 
    @Override
    public void launch(Context ctx, String string) {
        Intent intent = new Intent(ctx, ShoppingActivity.class);
        ctx.startActivity(intent);
    }
 
    @Override
    public Fragment newBillFragment(FragmentManager fragmentManager, int viewId, Bundle bundle) {
        BillFragment fragment = new BillFragment();
        fragment.setArguments(bundle);
        fragmentManager.beginTransaction().replace(viewId, fragment).commit();
        return fragment;
    }
}

3番目のステップ

次に、ServiceFactoryを作成してジャンプインスタンスを提供し、単独で実行しているときに発生する可能性のある例外を処理します

package com.example.sharemodule;
 
public class ServiceFactory {
    private static final ServiceFactory instance = new ServiceFactory();
 
    private ILoginService mLoginService;
    private IShoppingService mShoppingService;
 
    private ServiceFactory(){}
 
    public static ServiceFactory getInstance() {
        return instance;
    }
 
    public ILoginService getLoginService() {
        if (mLoginService == null){
            mLoginService = new EmptyLoginService();
        }
        return mLoginService;
    }
 
    public void setLoginService(ILoginService mLoginService) {
        this.mLoginService = mLoginService;
    }
 
    public IShoppingService getSignService() {
        if (mShoppingService == null){
            mShoppingService = new EmptyShoppingService();
        }
        return mShoppingService;
    }
 
    public void setSignService(IShoppingService mSignService) {
        this.mShoppingService = mSignService;
    }
}
package com.example.mylibrarySharedLibrary;
 
import android.content.Context;
import android.os.Bundle;
 
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
 
public class EmptyLoginService implements ILoginService {
    @Override
    public void launch(Context ctx, String targetClass) {
 
    }
 
    @Override
    public Fragment newUserInfoFragment(FragmentManager fragmentManager, int viewId, Bundle bundle) {
        return null;
    }
}
package com.example.mylibrarySharedLibrary;
 
import android.content.Context;
 
public class EmptySignService implements ISignService  {
    @Override
    public void launch(Context ctx, String userId) {
 
    }
}

このように、メインMoudleを単独で実行しても例外は発生しません。

上でジャンプしたコードは終了しました。次のステップはserviceFactoryに追加することです

プライベートILoginServicemLoginService;
プライベートIShoppingServicemSignService;

割り当て

package com.example.sharemodule;
 
import android.app.Application;
 
public interface IComponentApplication {
    void initialize(Application application);
}

統一された初期化インターフェースを提供する

package com.example.moduledemo;
 
import android.app.Application;
import android.util.Log;
 
import com.example.sharemodule.AppConfig;
import com.example.sharemodule.IComponentApplication;
 
 
public class MainApplication extends Application implements IComponentApplication {
    private static Application application;
 
    public static Application getApplication(){
        return application;
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
        initialize(this);
    }
 
    @Override
    public void initialize(Application application) {
        for (String cpnt : AppConfig.Components){
            try{
                Class<?> clz = Class.forName(cpnt);
                Object obj = clz.newInstance();
                if (obj instanceof IComponentApplication){
                    ((IComponentApplication) obj).initialize(this);
                }
            }catch (Exception e){
                Log.e("TAG", e.getMessage());
            }
        }
    }
}
package com.example.loginmodule;
 
import android.app.Application;
 
import com.example.sharemodule.IComponentApplication;
import com.example.sharemodule.ServiceFactory;
 
 
public class LoginApplication extends Application implements IComponentApplication {
 
    private static Application application;
 
    public static Application getApplication(){
        return application;
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
    }
 
    @Override
    public void initialize(Application app) {
        application = app;
        ServiceFactory.getInstance().setLoginService(new LoginService());
    }
}
package com.example.shoppingmodule;
 
import android.app.Application;
 
import com.example.sharemodule.IComponentApplication;
import com.example.sharemodule.ServiceFactory;
 
 
public class ShoppingApplication extends Application implements IComponentApplication {
    private static Application application;
 
    public static Application getApplication() {
        return application;
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
 
    }
 
    @Override
    public void initialize(Application app) {
        application = app;
        ServiceFactory.getInstance().setSignService(new SignService());
    }
}
package com.example.sharemodule;
 
public class AppConfig {
    public static final String[] Components = {
            "com.example.shoppingmodule.ShoppingApplication",
            "com.example.loginmodule.LoginApplication"
    };
}

アプリに入るときに初期化され、サブモジュールのアプリケーションインスタンスは初期化のためのリフレクションを通じて取得されます。

最終結果:

この記事 はオープンソースプロジェクトに含まれています:https//github.com/Android-Alvin/Android-LearningNotesには、Androidコンポーネント(Meituanアプリ、Getアプリ、Alipayアプリ、WeChatアプリ、 Mogujie App、Youzan APP ...)など。リソースは継続的に更新されています...

おすすめ

転載: blog.csdn.net/weixin_43901866/article/details/112492393