Arquitectura de desarrollo híbrida | La ingeniería de Android integra React Native, Flutter, ReactJs

Arquitectura Diseño Descripción

Este artículo presenta y registra detalles y procesos importantes en el desarrollo de la gran arquitectura híbrida front-end. Al integrar los dos frameworks híbridos convencionales React Native, Flutter y ReactJs[Vue] en el proyecto nativo de Android, se integra el diseño híbrido de la arquitectura de los tres tipos de módulos. Y en la creación de negocios de estas pilas de tecnología convencional, construyen sus propias ruedas, utilizan un diseño de arquitectura novedoso y tecnologías centrales para lograrlo. Y en el proceso de codificación, también creará herramientas comunes, barra de estado inmersiva , barra de navegación inferior , actualización en caliente de Flutter, entrada múltiple de Flutter,

tabla 1 tab2 tab3 tab4 tab5
Imitación de la página de inicio de China Merchants Bank imitacion de mensajeria instantanea Imitación de la página de inicio de ICBC imitacion vibrato mi pagina Clasificación Imitación Vipshop

Cree una página de inicio en el proyecto nativo y utilícela en la página de inicio 五个TAB.

  • TAB1, utilizando codificación nativa Java+Kotlin, imitando la página de inicio de China Merchants Bank, utilizando un excelente diseño de arquitectura y completando el desacoplamiento independiente de cada módulo de la lista.
  • TAB2, usando codificación Java+Kotlin nativa, imitando WeChat y realizando mensajería instantánea IM a través de Android Socket.
  • TAB3, utilizando la codificación React Native, imitando la página de inicio de ICBC.
  • TAB4, usando la codificación de Flutter, imitando a Douyin en mi página.
  • TAB5, codificado con ReactJs, imitando la página de clasificación de Vipshop.

Crear proyecto nativo de Android

Versión de estudio de Android versión del complemento gradle versión gradle versión kotlin versión JDK otro
3.6 3.6.0 gradle-6.7.1-all.zip (anteriormente 5.6.4) 1.5.31 JDK11 compileSdkVersion 31, buildToolsVersion “30.0.0” , minSdkVersion 21, targetSdkVersion 30

Crear aleteo

Versión de estudio de Android versión del complemento gradle versión gradle versión JDK otro
3.6 3.6.0 gradle-5.6.4-all.zip JDK11 compileSdkVersion 31, buildToolsVersion “30.0.0” , minSdkVersion 21, targetSdkVersion 30

Integre e incorpore ingeniería nativa

Introducción detallada de integración, muévase para ver

Crear reaccionar nativo

En comparación con la creación de Flutter, la creación de proyectos React Native es mucho más complicada. Al crear, encontrará el problema de la falla de creación. Después de la creación exitosa, también encontrará el problema del informe de error cuando inicia el servicio de Metro . Y todas estas preguntas están relacionadas con nodejs版本. Lea la documentación oficial del entorno de compilación en detalle ,React Naitve版本

Instrucciones de creación de React Native: npx react-native init hibrid_rn --version 0.67.0
Instrucciones de inicio del servicio Metro: npx react-native start
Instrucciones de instalación y compilación de apk de Android:yarn android

versión de nodo Reaccionar versión nativa versión JDK ilustrar
v16.17.0 0.67.0 JDK11 Para obtener un número de versión detallado, muévase para ver el código

Resolver el problema del error RN

Si hay un error, lo siguiente

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




Si hay un error, lo siguiente
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).

Solución, especifique ReactNative para determinar el número de versión Modifique ReactNative aapp/build.gradle
implementation "com.facebook.react:react-native:+"implementation "com.facebook.react:react-native:0.67.0"

Si hay un error, lo siguiente
Execution failed for task ':app:mergeDebugNativeLibs'.
More than one file was found with OS independent path 'lib/x86_64/libfbjni.so'

inserte la descripción de la imagen aquí
La solución es agregar el error informado en la captura de pantalla en android app/build.gradle {}, comolib/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'
    }

Integre e incorpore ingeniería nativa


// 【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
        
    }
}

Descripción del campo de parámetro:

  • entryFile : "index.android.js", que indica el nombre de la configuración que carga el archivo de entrada de recursos de Android.
  • def hermesPath = "../../hibrid_rn/node_modules/hermesvm/android/", indicando que enableHermes==trueen ese momento se introdujo el motor de ejecución Hermes. De lo contrario, se utiliza el motor de ejecución JavaScriptCore.

Hermes es una característica opcional de React Native. Si desea habilitar Hermes, debe asegurarse de que la versión del proyecto React Native esté 0.60.2版本arriba, y también debe android/app/build.gradlerealizar los siguientes cambios en . Configuramos aquíenableHermes: false

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

Después de que se integre el RN, inicie un error

Después de integrar RN en el proyecto nativo, use React Native como parte de LayoutView en la actividad del proyecto nativo para probar el estado de integración. Descubrí que iniciar React Native desde Native informó el siguiente error ~

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.

inserte la descripción de la imagen aquí
El mensaje de error decía que el servicio Metro no se inició o que no se pudo encontrar el paquete de recursos del paquete. El hecho es que el servicio actual de Metro se ha iniciado y está bien iniciar directamente el proyecto React Native. Hay dos soluciones para esto:

  • Empaquete el código del proyecto actual React Nativey copie el empaquetado bundle资源en el directorio del proyecto nativo /main/assets/rn. Entonces no hay problema para ejecutarse en Native.
  • El terminal VSCode ejecuta las instrucciones de empaquetado: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/
  • Sin empaquetar Tanto Native como React Native deben configurarse. ① Configure la IP del servicio y el número de puerto para la aplicación del paquete de depuración instalado. ②Configure los permisos de red, application标签configure en medio tools:targetApi="28" android:allowBackup="true". ③ Iniciar el servicio de Metro.

inserte la descripción de la imagen aquí

Diseño de arquitectura de la barra de navegación inferior

Use el lenguaje Java para personalizar el control de diseño de la barra de navegación en la parte inferior de la página de inicio (el efecto + código fuente de navegación en la figura a continuación ) e introduzca el UML personalizado ~
inserte la descripción de la imagen aquí

  • TabBtnLayoutBottomNavVista personalizada del diseño de la barra de navegación inferior. Heredado de FrameLayout, implementado desde la interfaz ITabLayout. Diseño de la barra de navegación inferior, ubicación interna TabBtnBottom,
  • TabBtnBottomUna sola pestaña en un diseño de barra de navegación inferior. Heredado de RelativeLayout, implementado desde la interfaz I ITab (ITab hereda la interfaz de escucha de eventos de clic OnTabSelectedListener).
  • TabBtnLayoutBottomNavEncapsula internamente una sola colección de pestañas List<OnTabSelectedListener>(incluido todo el monitoreo OnTabSelectedListener agregado por TabBtnBottom y TabBtnLayoutBottomNav). Cuando el usuario hace clic en la pestaña, el evento de clic TabBtnBottom.setOnClickListenerdesencadena el recorrido de la lista de colección. En este momento, el evento de clic se pasa a cada TabBtnBottomz y la devolución de llamada de monitoreo agregada por TabBtnLayoutBottomNav. Como resultado, una sola pestaña y TabBtnLayoutBottomNav están asociados con eventos de clic y pueden allanar el camino para la visualización de cambio de clic de fragmento integrado.
    inserte la descripción de la imagen aquíinserte la descripción de la imagen aquí
  • TabBtnFragmentLayout, para mostrar el ** control de diseño personalizado ** de la página del fragmento y colocarlo en el archivo de diseño TabBtnLayoutBottomNav. El índice de devolución de llamada de monitoreo agregado por TabBtnLayoutBottomNav, el método setCurrentItemobtiene instrucciones y muestra la página de fragmento correspondiente.
  • TabBtnFragmentAdapter, para mostrar la clase de adaptador para la página del fragmento. Las instrucciones específicas muestran la lógica de la página del fragmento, que se implementa en el método instantiateItem.
    inserte la descripción de la imagen aquí

Imitación original de la página de inicio de China Merchants Bank

Mensajería instantánea nativa de Android Socket

React Native imita la página de inicio de ICBC

Use RN para imitar la página de inicio del Banco Industrial y Comercial de China (encontré el ícono con dificultad) y luego realice StatusBar和TitleBarel **滑动渐变**efecto aleatorio. Aquí, inicie y abra RN de forma nativa, el efecto es el siguiente ~
inserte la descripción de la imagen aquí

Pase de forma nativa el objeto inicial de los accesorios, los usos de RN

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

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

Nativo para comunicarse con RN

Introducción al efecto logrado

Se define un método para llamar a Android ToastJRNBridge.kt en la clase de puente del lado nativo para que llame el lado ReactNative. El efecto es el siguiente
inserte la descripción de la imagen aquí

Notas durante el desarrollo

Aquí tomamos este proyecto como ejemplo para presentar la lógica de los pasos de desarrollo al realizar la comunicación entre RN y C-side.
1. Defina la herramienta de puente en el lado C del código fuente lógicoJRNBridge.kt . La clase de puente hereda de ReactContextBaseJavaModule.java, el método de implementación getName : el nombre obtenido se usará en el lado de ReactNative,

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

2. El método de comunicación entre ReactNative y C-side Native debe anotarse@ReactMethod.

3. Cree JReactPackage.kt para heredarReactPackage.kty reescribir el métodocreateNativeModules和createViewManagers. El método de reescrituracreateNativeModuleses agregar JReactPackage a la lista NativeModule para el registro posterior.

crear módulos nativos crearViewManagers
Vuelva a escribir y agregue NativeModule cuando ReactNative llame al método nativo Interfaz de usuario nativa, ya que la interfaz de usuario de ReactNative se reescribió y se agregó ViewManager

4. Agregue y registre MainReactPackage() y JReactPackage() en ReactInstanceManager.
Entre ellos, se requieren MainReactPackage() y JReactPackage(), de lo contrario se informará un error'StatusBarManager' could not be found. Verify that a module by this name is registered in the native binary.
inserte la descripción de la imagen aquí

De lo contrario, JReactPackage() informa un error y no puede encontrarlo RNBridge.toast({toast:'正在取号中,请稍后...'}).

5. Exportar el JRNBridge registrado en NativeModulesen ReactNativeLuego introdúzcalo y utilícelo en varios lugares en ReactNative.
inserte la descripción de la imagen aquí

Código fuente de ReactNative

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

Flutter imita vibrato mi pagina

Actualización en caliente de Flutter

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

La idea de la carga dinámica de archivos .so es
reflejar el valor que se está modificandoFlutterLoader.java类,valorFlutterApplicationInfo.aotSharedLibraryNameoriginal. Después de eso,copie el reemplazo en eldirectorio original. La forma de copiar, como empaquetar primero una nueva versión-apk, luego descomprimir y extraer el archivo libapp.so en este momento (renombrado como libapp**.so), y colocarlo en el directorio assets/. Luego, cuando se copia el código, el paquete so en el directorio assets/ se copiará en el directorio recién especificado donde se cargará, y luego la actualización en caliente se completará lógicamente.libapp.solibapp**.solibapp**.solibapp.solibapp.so

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Cree múltiples motores FlutterEngine e implemente múltiples entradas de dardos

Una página de inversión y gestión financiera de flutter , como la segunda entrada de dart. Y abierto por el motor correspondiente definido a continuación.
inserte la descripción de la imagen aquí

Crear múltiples motores FlutterEngine

Mediante FlutterEnginela creación de un objeto de instancia de motor. Se pasa durante la creación JFlutterLoadery redefine dart代码包la forma en que el FlutterLoader original lo obtiene. Después de eso, comience a ejecutar el código Dart de acuerdo con el DartEntrypoint dado. Y almacene en caché la Flutter引擎instancia creada. que se pasa DartEntrypointa 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
}

Crear múltiples entradas de dardos

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

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

Combinado con el código fuente de Flutter, analice el inicio de Flutter desde el extremo nativo

Comunicación nativa con Flutter

inserte la descripción de la imagen aquí

tipo ilustrar
MétodoChannel Comunicación única utilizada para transferir invokeMethodllamadas de método: como llamar a la función de punto enterrado de Flutter.

Aquí presentaremos MethodChannel , cómo comunicarse entre Native y Flutter ~ El lado de Flutter envía , y el lado nativo recibe y procesa.
Flutter侧发送, combinado con el código fuente, creando uno MethodChannel实例y especificando el nombre del canal name. Y ambos lados namedeben ser iguales. Luego use la instancia de MethodChannel para llamar y ejecutar 方法invokeMethod, y se llamará al método pasado al lado nativo 方法名称methody el contenido del mensaje de comunicación arguments. Después de eso, se inicia la llamada de transferencia de Flutter al lado nativo.
Native侧接收处理, crea un canal con nameel mismo nombre que el canal lateral de Flutter MethodChannel实例. Use la instancia de MethodChannel para llamar y ejecutar 方法setMethodCallHandlerpara que coincida con Flutter侧方法名称methodla información de recepción y procesamiento enviada desde el lado de Flutter. Diseño detallado e implementación, mueva para ver

Página de categoría Vipshop de imitación de ReactJs

Introducción detallada al desarrollo, muévase para ver

Dirección de origen del proyecto

Haga clic para ingresar al almacén para ver el código fuente del proyecto

Supongo que te gusta

Origin blog.csdn.net/u012827205/article/details/126880806
Recomendado
Clasificación