하이브리드 개발 아키텍처 | Android 엔지니어링은 React Native, Flutter, ReactJs를 통합합니다.

아키텍처 설계 설명

이 기사에서는 대규모 프런트 엔드 하이브리드 아키텍처 개발의 중요한 세부 정보와 프로세스를 소개하고 기록합니다. Android 네이티브 프로젝트에 두 가지 주류 하이브리드 프레임워크인 React Native, Flutter, ReactJs[Vue]를 통합하여 세 가지 유형의 모듈 아키텍처의 하이브리드 설계가 통합되었습니다. 그리고 이러한 주류 기술 스택의 비즈니스 창출에서 자체 바퀴를 만들고 새로운 아키텍처 설계와 핵심 기술을 사용하여 달성합니다. 그리고 코딩 과정에서 공통 도구, 몰입형 상태 표시줄 , 하단 탐색 표시줄 , Flutter 핫 업데이트, Flutter 다중 입력,

1 번 테이블 탭2 탭3 탭4 탭5
초상은행 홈페이지 모방 모조 인스턴트 메시징 모조 ICBC 홈페이지 모조 비브라토 마이페이지 모조 Vipshop 분류

네이티브 프로젝트에서 홈페이지를 생성하여 홈페이지에서 사용하세요 五个TAB.

  • TAB1, 네이티브 Java+Kotlin 코딩 사용, China Merchants Bank의 홈페이지 모방, 우수한 아키텍처 설계 사용, 목록의 각 모듈의 독립적인 분리 완료.
  • TAB2, 네이티브 Java+Kotlin 코딩 사용, WeChat 모방, Android 소켓을 통한 IM 인스턴트 메시징 실현.
  • TAB3, React Native 코딩을 사용하여 ICBC의 홈페이지를 모방합니다.
  • TAB4, Flutter 코딩을 사용하여 Douyin 내 페이지를 모방합니다.
  • TAB5, ReactJs로 코딩되어 Vipshop의 분류 페이지를 모방합니다.

Android 네이티브 프로젝트 만들기

안드로이드 스튜디오 버전 그래들 플러그인 버전 그래들 버전 코 틀린 버전 JDK 버전 다른
3.6 3.6.0 gradle-6.7.1-all.zip(이전 5.6.4) 1.5.31 JDK11 compileSdkVersion 31, buildToolsVersion "30.0.0", minSdkVersion 21, targetSdkVersion 30

플러터 만들기

안드로이드 스튜디오 버전 그래들 플러그인 버전 그래들 버전 JDK 버전 다른
3.6 3.6.0 gradle-5.6.4-all.zip JDK11 compileSdkVersion 31, buildToolsVersion "30.0.0", minSdkVersion 21, targetSdkVersion 30

기본 엔지니어링 통합 및 내장

자세한 통합 소개는 보기로 이동하세요.

리액트 네이티브 만들기

Flutter 생성과 비교할 때 React Native 프로젝트 생성은 훨씬 더 복잡합니다. 생성 시 생성 실패 문제가 발생하며, 생성 성공 후 Metro 서비스를 시작할 때 오류 보고 문제 도 발생합니다 . 그리고 이러한 질문은 모두 nodejs版本. 공식 빌드 환경 문서를 자세히 읽으십시오 .React Naitve版本

React Native 생성 지침: npx react-native init hibrid_rn --version 0.67.0
Metro 서비스 시작 지침: npx react-native start
Android apk 컴파일 및 설치 지침:yarn android

노드 버전 네이티브 버전 반응 JDK 버전 설명하다
v16.17.0 0.67.0 JDK11 자세한 버전 번호는 코드 보기로 이동하십시오.

RN 오류 문제 해결

오류가 있는 경우 다음

如下报错信息,则是node版本号使用不当导致~
/node_modules/@react-native-community/cli/build/commands/doctor/healthchecks/index.js:48
} catch {}
^
SyntaxError: Unexpected token { at createScript (vm.js:80:10) at Object.runInThisContext (vm.js:139:10) Module._compile(module.js:617:28)에서 Object.Module._extensions…js(module.js:664:10) … … …




오류가 있는 경우 다음
Could not find react-native-0.71.0-rc.0-debug.aar (com.facebook.react:react-native:0.71.0-rc.0).

Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugCompileClasspath'.
   > Could not find react-native-0.71.0-rc.0-debug.aar (com.facebook.react:react-native:0.71.0-rc.0).

해결 방법은 ReactNative를 지정하여 버전 번호를 결정합니다 !! ReactNative를 다음으로 수정합니다 .app/build.gradle
implementation "com.facebook.react:react-native:+"implementation "com.facebook.react:react-native:0.67.0"

오류가 있는 경우 다음
Execution failed for task ':app:mergeDebugNativeLibs'.
More than one file was found with OS independent path 'lib/x86_64/libfbjni.so'

여기에 이미지 설명 삽입
해결책은 다음과 같이 Android app/build.gradle {} 의 스크린샷에 보고된 오류를 추가하는 것 입니다.lib/x86_64/libfbjni.so

packagingOptions {
    
    
        pickFirst 'lib/x86/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/x86/libfbjni.so'
        pickFirst 'lib/x86_64/libfbjni.so' // 截图中有这个报错,这里添加该so修复
        pickFirst 'lib/armeabi-v7a/libfbjni.so'
        pickFirst 'lib/arm64-v8a/libfbjni.so'
    }

기본 엔지니어링 통합 및 내장


// 【app/build.gradle】下进行配置
// 【配置共三步】rn第一步配置:start
project.ext.react = [
        entryFile   : "index.android.js",
        enableHermes: false,
        bundleInDebug:true,
        bundleInBeta:true
]

def enableHermes = project.ext.react.get("enableHermes", false);
def jscFlavor = 'org.webkit:android-jsc:+'

def safeExtGet(prop, fallback) {
    
    
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
// 【配置共三步】rn第一步配置:end
dependencies {
    
    
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    ......
    // 【配置共三步】rn第二步配置:start
    if (enableHermes) {
    
    
        def hermesPath = "../../hibrid_rn/node_modules/hermesvm/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
    
    
        implementation jscFlavor
    }
    implementation "com.facebook.react:react-native:+" // From node_modules
    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
    // 【配置共三步】rn第二步配置:end
}

// 【project/build.gradle】下进行配置
allprojects {
    
    
    repositories {
    
    
        ......
        // 【配置共三步】rn第三步配置:start
        maven {
    
    
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../hibrid_rn/node_modules/react-native/android"
        }
        maven {
    
    
            // Android JSC is installed from npm
            url("$rootDir/../hibrid_rn/node_modules/jsc-android/dist")
        }
        //【配置共三步】rn第三步配置:end
        
    }
}

매개변수 필드 설명:

  • entryFile : "index.android.js", Android 리소스 항목 파일을 로드하는 구성의 이름을 나타냅니다.
  • def hermesPath = "../../hibrid_rn/node_modules/hermesvm/android/", enableHermes==true당시 . 그렇지 않으면 JavaScriptCore 실행 엔진이 사용됩니다.

Hermes는 선택적 React Native 기능입니다. Hermes를 활성화하려면 React Native 프로젝트의 버전이 상위 버전인지 확인 하고 다음과 0.60.2版本같이 변경해야 합니다 . android/app/build.gradle여기에서 구성합니다enableHermes: false

project.ext.react = [
  entryFile: "index.js",
  enableHermes: true // 配置开启Hermes引擎
]

RN 통합 후 오류 시작

네이티브 프로젝트에서 RN을 통합한 후 네이티브 프로젝트 활동 아래 LayoutView의 일부로 React Native를 사용하여 통합 상태를 테스트합니다. Native에서 React Native를 시작하면 다음 오류가 보고된 것을 발견했습니다~

ReactNative: Exception in native call java.lang.RuntimeException: Unable to load script. Make sure you're either running Metro (run 'npx react-native start') or that your bundle 'rn/index.android.bundle' is packaged correctly for release.

여기에 이미지 설명 삽입
오류 메시지는 Metro 서비스가 시작되지 않았거나 번들 리소스 패키지를 찾을 수 없다는 내용이었습니다. 사실은 현재 Metro 서비스가 시작되었고 React Native 프로젝트를 직접 시작해도 괜찮습니다. 이에 대한 두 가지 솔루션이 있습니다 .

  • 현재 React Native프로젝트 코드를 패키징하고 패키징된 코드를 bundle资源네이티브 프로젝트의 디렉터리에 복사합니다 /main/assets/rn. 그러면 네이티브에서 실행하는 데 문제가 없습니다.
  • VSCode 터미널은 패키징 명령을 실행합니다.react-native bundle --platform android --dev false --entry-file index.js --bundle-output ../HybridArcPro/app/src/main/assets/rn/index.android.bundle --assets-dest ../HybridArcPro/app/src/main/res/
  • 미포장. 기본 및 반응 기본을 모두 구성해야 합니다. ① 설치된 디버그 패키지 APP의 서비스 IP와 포트 번호를 설정합니다. ②네트워크 권한을 구성하고 application标签중간에 구성합니다 tools:targetApi="28" android:allowBackup="true". ③ 메트로 서비스를 시작합니다.

여기에 이미지 설명 삽입

하단 탐색 모음 아키텍처 디자인

자바 언어를 사용하여 홈페이지 하단에 있는 내비게이션 바의 레이아웃 컨트롤(아래 그림의 효과 + 내비게이션 소스 코드 )을 커스터마이즈하고 커스텀 UML을 도입합니다~
여기에 이미지 설명 삽입

  • TabBtnLayoutBottomNav하단 탐색 모음 레이아웃 사용자 지정 보기. FrameLayout에서 상속되고 ITabLayout 인터페이스에서 구현됩니다. 하단 탐색 모음 레이아웃, 내부 배치 TabBtnBottom,
  • TabBtnBottom하단 탐색 모음 레이아웃의 단일 탭입니다. I 인터페이스 ITab에서 구현된 RelativeLayout에서 상속됨(ITab은 클릭 이벤트 수신 인터페이스 OnTabSelectedListener를 상속함).
  • TabBtnLayoutBottomNav단일 탭 컬렉션을 내부적으로 캡슐화합니다 List<OnTabSelectedListener>.(TabBtnBottom 및 TabBtnLayoutBottomNav에 의해 추가된 모든 모니터링 OnTabSelectedListener 포함) 사용자가 탭을 클릭하면 클릭 이벤트가 TabBtnBottom.setOnClickListener컬렉션 목록의 순회를 트리거합니다. 이때 클릭 이벤트는 각 TabBtnBottomz에 전달됩니다. , TabBtnLayoutBottomNav에 의해 추가된 모니터링 콜백. 결과적으로 단일 Tab 및 TabBtnLayoutBottomNav는 클릭 이벤트와 연결 되며 통합된 프래그먼트 클릭 전환 표시를 위한 길을 열 수 있습니다.
    여기에 이미지 설명 삽입여기에 이미지 설명 삽입
  • TabBtnFragmentLayout, 조각 페이지의 ** 사용자 지정 레이아웃 컨트롤 ** 을 표시 하고 레이아웃 파일 TabBtnLayoutBottomNav에 배치합니다. TabBtnLayoutBottomNav에 의해 추가된 모니터링 콜백 인덱스, 메서드는 setCurrentItem지침을 얻고 해당 조각 페이지를 표시합니다.
  • TabBtnFragmentAdapter, 조각 페이지에 대한 어댑터 클래스를 표시합니다. 특정 지침은 메서드에서 구현되는 조각 페이지의 논리를 보여줍니다 instantiateItem.
    여기에 이미지 설명 삽입

원본 모조 China Merchants Bank 홈페이지

기본 Android 소켓 인스턴트 메시징

React Native는 ICBC의 홈페이지를 모방합니다.

RN을 사용하여 중국공상은행 홈페이지를 흉내내고(어렵게 아이콘을 찾았습니다) StatusBar和TitleBar랜덤 **滑动渐变**효과를 실현합니다. 여기에서 네이티브로 RN을 시작하고 열면 효과는 다음과 같습니다~
여기에 이미지 설명 삽입

기본적으로 props 초기 객체 전달, RN은 사용

// React Native中配置bundle
val bundle = Bundle()
rnBundle.putCharSequence("device-info","设备信息对象")
rnBundle.putCharSequence("state","用户登录状态")
mReactRootView!!.startReactApplication(mReactInstanceManager, "hibrid_rn", bundle)

// 在对应的ReactNative的Coponent中获取,则可通过this.props得到!

RN과 통신하기 위한 네이티브

달성 효과 소개

Android Toast를 호출하는 메소드는 ReactNative 측에서 호출할 수 있도록 Native 측의 브릿지 클래스 JRNBridge.kt에 정의되어 있습니다 . 효과는 다음과 같습니다
여기에 이미지 설명 삽입

개발 중 참고 사항

여기에서는 이 프로젝트를 예로 들어 RN과 C 측 간의 통신을 실현할 때 개발 단계의 논리를 소개합니다.
1. 로직 소스 코드 의 C 측에서 브리징 도구를 정의합니다 JRNBridge.kt. 브리지 클래스는 구현 방법인 ReactContextBaseJavaModule.java에서 상속합니다 getName . 얻은 이름은 ReactNative 측에서 사용됩니다.

// bridge/index.js
import {
    
    NativeModules} from 'react-native'
module.exports = NativeModules.RNBridge  // 这里的 RNBridge 就是getName得到。

2. ReactNative와 C-side Native 간의 통신 방법에 주석을 달아야 합니다@ReactMethod.

3.ReactPackage.kt JReactPackage.kt를 생성하여 메서드를상속createNativeModules和createViewManagers. 재작성 방법은createNativeModules후속 등록을 위해 JReactPackage를 NativeModule 목록에 추가하는 것입니다.

네이티브 모듈 만들기 createViewManagers
ReactNative가 Native 메서드를 호출할 때 NativeModule을 다시 작성하고 추가합니다. Native UI, ReactNative UI가 재작성되고 ​​ViewManager가 추가됨에 따라

4. ReactInstanceManager에 MainReactPackage() 및 JReactPackage()를 추가하고 등록합니다.
이 중 MainReactPackage() 및 JReactPackage()가 필요하며, 그렇지 않으면 오류가 보고됩니다.'StatusBarManager' could not be found. Verify that a module by this name is registered in the native binary.
여기에 이미지 설명 삽입

그렇지 않으면 JReactPackage()가 오류를 보고하고 오류를 찾을 수 없습니다 RNBridge.toast({toast:'正在取号中,请稍后...'}).

5. ReactNative에서NativeModules에 등록된 JRNBridge를 내보냅니다 . 그런 다음 ReactNative의 여러 곳에서 소개 하고 사용하십시오.
여기에 이미지 설명 삽입

ReactNative 소스 코드

import RNBridge from '@bridge/index'
<TouchableOpacity onPress={
    
    ()=>{
    
    RNBridge.toast({
    
    toast:'正在取号中,请稍后...'})}} >

Flutter는 내 페이지를 진동으로 모방합니다.

Flutter 핫 업데이트

Flutter热更新,通过动态.so文件的加载实现。

.so 파일의 동적 로딩에 대한 아이디어는
수정되는 값을 반영하여FlutterLoader.java类FlutterLoaderFlutterApplicationInfo.aotSharedLibraryName원래libapp.so값을libapp**.so. 그런 다음libapp**.so대체 항목을 원래libapp.so디렉토리에 복사하십시오. 새 릴리스-apk를 먼저 패키징한 다음 이 때 libapp.so 파일(libapp**.so로 이름 변경)을 압축 해제하고 추출하여 assets/ 디렉토리에 넣는 것과 같은 복사 방법. 이후에 코드를 복사하면 assets/ 디렉터리에 있는 so 패키지가 로드될 새로 지정된 디렉터리에 복사된libapp.so다음 핫 업데이트가 논리적으로 완료됩니다.

여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

여러 FlutterEngine 엔진을 만들고 여러 다트 항목을 구현합니다.

두 번째 dart 항목인 flutter의 투자 및 재무 관리 페이지입니다 . 그리고 아래에 정의된 해당 엔진에 의해 열립니다.
여기에 이미지 설명 삽입

여러 FlutterEngine 엔진 만들기

FlutterEngine엔진 인스턴스 객체 생성 . 생성 중에 전달되며 원래 FlutterLoader가 가져오는 방식을 JFlutterLoader재정의합니다 . dart代码包그런 다음 주어진 DartEntrypoint에 따라 Dart 코드 실행을 시작합니다. 그리고 생성된 Flutter引擎인스턴스를 캐시합니다. DartEntrypoint전달되는 moduleName是dart入口名称,findAppBundlePath是flutter资产目录flutterAssetsDir

// 初始化,根据moduleName(dart入口名称)创建多个Flutter引擎
private fun initFlutterEngine(context: Context, moduleName: String): FlutterEngine? {
    
    
    var flutterEngine:FlutterEngine = FlutterEngine(context, JFlutterLoader.get(), FlutterJNI())
        
    flutterEngine.dartExecutor
            .executeDartEntrypoint(DartExecutor.DartEntrypoint(JFlutterLoader.get().findAppBundlePath(), moduleName))
    FlutterEngineCache.getInstance().put(moduleName, flutterEngine) // 缓存起来
    return flutterEngine
}

여러 다트 항목 만들기

// 在flutter的dart代码中main.dart
// 至少有一个默认入口,如 'main'
void main() {
    
    
  runApp(const MyApp());
  init();
}

// 此时,可仿照默认入口,通过注解,创建多个不同的dart入口 - 工行的'投资理财'详情页面
@pragma('vm:entry-point')
void finance() {
    
    
  runApp(FinanceEntryApp());
}

Flutter의 소스 코드와 결합하여 네이티브 엔드에서 Flutter의 시작을 분석합니다.

Flutter와의 네이티브 커뮤니케이션

여기에 이미지 설명 삽입

유형 설명하다
방법채널 메서드 invokeMethod호출을 전송하는 데 사용되는 일회성 통신: Flutter의 묻힌 포인트 기능 호출 등.

여기에서는 Native와 Flutter 간의 통신 방법인 MethodChannel을 소개합니다 ~ Flutter 측은 를 보내고 Native 측은 수신하여 처리합니다 .
Flutter侧发送, 소스 코드와 결합하여 하나를 만들고 MethodChannel实例채널 이름을 지정합니다 name. 그리고 양쪽이 name같아야 합니다. 그런 다음 MethodChannel 인스턴스를 사용하여 호출하고 실행 方法invokeMethod하면 Native 측에 전달된 메서드가 호출되고 方法名称method통신 메시지의 내용이 호출됩니다 arguments. 그 후 Flutter에서 Native 측으로의 전송 호출이 시작됩니다. , Flutter 측 채널과 동일한 이름
Native侧接收处理으로 채널을 만듭니다 . MethodChannel 인스턴스를 사용하여 Flutter 측에서 보낸 수신 및 처리 정보와 일치하도록 호출하고 실행합니다. 상세 설계 및 구현은 보기로 이동해주세요.nameMethodChannel实例方法setMethodCallHandlerFlutter侧方法名称method

ReactJs 모방 Vipshop 카테고리 페이지

자세한 개발 소개는 보기로 이동해주세요

프로젝트 소스 주소

프로젝트 소스 코드를 보려면 창고를 입력하려면 클릭하십시오.

추천

출처blog.csdn.net/u012827205/article/details/126880806