Arquitetura de desenvolvimento híbrido | A engenharia do Android integra React Native, Flutter, ReactJs

Descrição do projeto de arquitetura

Este artigo apresenta e registra detalhes e processos importantes no desenvolvimento da arquitetura híbrida de front-end grande. Ao integrar as duas principais estruturas híbridas React Native, Flutter e ReactJs[Vue] no projeto nativo do Android, o design híbrido da arquitetura dos três tipos de módulos é integrado. E na criação de negócios dessas pilhas de tecnologia convencionais, eles constroem suas próprias rodas, usam design de arquitetura inovador e tecnologias essenciais para alcançar. E no processo de codificação, ele também criará ferramentas comuns, barra de status imersiva , barra de navegação inferior , atualização dinâmica do Flutter, entrada múltipla do Flutter,

tabela 1 tab2 tab3 tab4 tab5
Imitação da página inicial do China Merchants Bank imitação de mensagens instantâneas Imitação da página inicial do ICBC imitação vibrato minha página Classificação de imitação Vipshop

Crie uma página inicial no projeto nativo e use-a na página inicial 五个TAB.

  • TAB1, usando codificação nativa Java+Kotlin, imitando a página inicial do China Merchants Bank, usando excelente design de arquitetura e completando o desacoplamento independente de cada módulo da lista.
  • TAB2, usando codificação nativa Java+Kotlin, imitando o WeChat e realizando mensagens instantâneas por meio do Android Socket.
  • TAB3, usando codificação React Native, imitando a página inicial do ICBC.
  • TAB4, usando codificação Flutter, imitando Douyin na minha página.
  • TAB5, codificado com ReactJs, imitando a página de classificação do Vipshop.

Criar projeto nativo do Android

Versão do Android Studio versão do plug-in gradle versão gradle versão kotlin Versão do JDK outro
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

Criar Flutter

Versão do Android Studio versão do plug-in gradle versão gradle Versão do JDK outro
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 a engenharia nativa

Introdução detalhada da integração, por favor mova para ver

Criar Reagir Nativo

Comparado com a criação do Flutter, a criação do projeto React Native é muito mais complicada. Ao criar, você encontrará o problema de falha na criação. Após a criação bem-sucedida, você também encontrará o problema de relatório de erros ao iniciar o serviço Metro . E essas questões estão todas relacionadas a nodejs版本. Por favor, leia a documentação oficial do ambiente de construção em detalhes ,React Naitve版本

Instrução de criação do React Native: npx react-native init hibrid_rn --version 0.67.0
Instrução de inicialização do serviço Metro: npx react-native start
Instrução de compilação e instalação do Android apk:yarn android

versão do nó Reagir versão nativa Versão do JDK ilustrar
v16.17.0 0,67,0 JDK11 Para obter o número da versão detalhada, mova para ver o código

Resolva o problema do erro RN

Se houver um erro, o seguinte

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




Se houver um erro, o seguinte
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).

Solução, especifique ReactNative para determinar o número da versão !! Modifique ReactNative paraapp/build.gradle
implementation "com.facebook.react:react-native:+"implementation "com.facebook.react:react-native:0.67.0"

Se houver um erro, o seguinte
Execution failed for task ':app:mergeDebugNativeLibs'.
More than one file was found with OS independent path 'lib/x86_64/libfbjni.so'

insira a descrição da imagem aqui
A solução é adicionar o erro relatado na captura de tela no 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 a engenharia 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
        
    }
}

Descrição do campo de parâmetro:

  • entryFile : "index.android.js", indicando o nome do arquivo de entrada de recurso Android de carregamento de configuração.
  • def hermesPath = "../../hibrid_rn/node_modules/hermesvm/android/", indicando que enableHermes==truenaquela época , o motor de execução Hermes foi introduzido. Caso contrário, o mecanismo de execução JavaScriptCore é usado.

Hermes é um recurso opcional do React Native. Se você deseja habilitar o Hermes, precisa garantir que a versão do projeto React Native esteja 0.60.2版本acima e também precisa android/app/build.gradlefazer as seguintes alterações no . Nós configuramos aquienableHermes: false

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

Depois que o RN estiver integrado, inicie um erro

Depois de integrar o RN no projeto nativo, use o React Native como parte do LayoutView na Activity do projeto nativo para testar o status da integração. Descobriu que iniciar o React Native do Native relatou o seguinte erro ~

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.

insira a descrição da imagem aqui
A mensagem de erro dizia que o serviço Metro não foi iniciado ou que o pacote de recursos do bundle não foi encontrado. O fato é que o serviço Metro atual foi iniciado e não há problema em iniciar diretamente o projeto React Native. Existem duas soluções para isso:

  • Empacote o código do projeto atual React Nativee copie o código do pacote bundle资源para o diretório do projeto Nativo /main/assets/rn. Então não há problema em rodar em Nativo.
  • O terminal VSCode executa instruções de empacotamento: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/
  • Desempacotado. Ambos Native e React Native precisam ser configurados. ① Configure o IP do serviço e o número da porta para o APP do pacote de depuração instalado. ②Configurar permissões de rede, application标签configurar no meio tools:targetApi="28" android:allowBackup="true". ③ Inicie o serviço Metro.

insira a descrição da imagem aqui

Projeto de arquitetura da barra de navegação inferior

Use a linguagem java para personalizar o controle de layout da barra de navegação na parte inferior da página inicial (o efeito + código fonte de navegação na figura abaixo ) e introduza a UML personalizada~
insira a descrição da imagem aqui

  • TabBtnLayoutBottomNavExibição personalizada do layout da barra de navegação inferior. Herdado de FrameLayout, implementado a partir da interface ITabLayout. Layout da barra de navegação inferior, posicionamento interno TabBtnBottom,
  • TabBtnBottomUma única guia em um layout de barra de navegação inferior. Herdado de RelativeLayout, implementado a partir da interface I ITab (ITab herda a interface de escuta de evento de clique OnTabSelectedListener).
  • TabBtnLayoutBottomNavEncapsula internamente uma única coleção Tab List<OnTabSelectedListener>(incluindo todo o monitoramento OnTabSelectedListener adicionado por TabBtnBottom e TabBtnLayoutBottomNav) TabBtnBottom.setOnClickListener. , e o retorno de chamada de monitoramento adicionado por TabBtnLayoutBottomNav. Como resultado, um único Tab e TabBtnLayoutBottomNav são associados a eventos de clique e podem preparar o caminho para a exibição integrada de comutação de cliques de fragmentos.
    insira a descrição da imagem aquiinsira a descrição da imagem aqui
  • TabBtnFragmentLayout, para exibir o ** controle de layout personalizado ** da página de fragmento e colocá-lo no arquivo de layout TabBtnLayoutBottomNav. O índice de retorno de chamada de monitoramento adicionado por TabBtnLayoutBottomNav, o método setCurrentItemobtém instruções e exibe a página de fragmento correspondente.
  • TabBtnFragmentAdapter, para exibir a classe do adaptador para a página de fragmento. As instruções específicas mostram a lógica da página de fragmento, que é implementada no método instantiateItem.
    insira a descrição da imagem aqui

Imitação original da página inicial do China Merchants Bank

Mensagens instantâneas nativas do Android Socket

React Native imita a página inicial do ICBC

Use o RN para imitar a página inicial do Industrial and Commercial Bank of China (encontrei o ícone com dificuldade) e, em seguida, perceba o efeito StatusBar和TitleBaraleatório . **滑动渐变**Aqui, inicie e abra o RN pelo nativo, o efeito é o seguinte~
insira a descrição da imagem aqui

Passar nativamente o objeto inicial de props, RN usa

// 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 se comunicar com RN

Introdução do efeito alcançado

Um método para chamar Android ToastJRNBridge.kt é definido na classe de ponte do lado Nativo para o lado ReactNative chamar. O efeito é o seguinte
insira a descrição da imagem aqui

Notas durante o desenvolvimento

Aqui tomamos este projeto como exemplo para introduzir a lógica das etapas de desenvolvimento ao realizar a comunicação entre RN e C-side.
1. Defina a ferramenta de ponte no lado C do código-fonte lógicoJRNBridge.kt . A classe ponte herda de ReactContextBaseJavaModule.java, o método de implementação getName - o nome obtido será usado no lado ReactNative,

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

2. O método de comunicação entre ReactNative e C-side Native precisa ser anotado@ReactMethod.

3. Crie JReactPackage.kt para herdarReactPackage.kte reescrever o métodocreateNativeModules和createViewManagers. O método de reescritacreateNativeModulesé adicionar JReactPackage à lista NativeModule para registro subsequente.

createNativeModules createViewManagers
Reescrever e adicionar NativeModule quando ReactNative chamar o método Native Native UI, já que ReactNative UI foi reescrito e adicionado ViewManager

4. Adicione e registre MainReactPackage() e JReactPackage() no ReactInstanceManager.
Entre eles, MainReactPackage() e JReactPackage() são obrigatórios, caso contrário, um erro será relatado'StatusBarManager' could not be found. Verify that a module by this name is registered in the native binary.
insira a descrição da imagem aqui

Caso contrário, JReactPackage() relata um erro e não consegue localizá-lo RNBridge.toast({toast:'正在取号中,请稍后...'}).

5. Exporte o JRNBridge registrado em NativeModulesem ReactNativeEm seguida, introduza e use-o em vários lugares no ReactNative.
insira a descrição da imagem aqui

Código-fonte ReactNative

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

Flutter imita vibrato minha página

Flutter hot update

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

A ideia do carregamento dinâmico dos arquivos .so é
refletir o valor que está sendo modificadoFlutterLoader.java类,valorFlutterApplicationInfo.aotSharedLibraryNameoriginal. Depois disso,copiar a substituição para odiretório original. A maneira de copiar, como empacotar um novo apk de lançamento primeiro, descompactar e extrair o arquivo libapp.so neste momento (renomeado para libapp**.so) e colocá-lo no diretório assets/. Posteriormente, quando o código for copiado, o pacote so no diretório assets/ será copiado para o diretório recém-especificado onde será carregadoe, em seguida, a atualização a quente será concluída logicamente.libapp.solibapp**.solibapp**.solibapp.solibapp.so

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Crie vários mecanismos FlutterEngine e implemente várias entradas de dardo

Uma página de investimento e gestão financeira de flutter , como a segunda entrada de dardo. E aberto pelo motor correspondente definido abaixo.
insira a descrição da imagem aqui

Crie vários mecanismos FlutterEngine

Criando FlutterEngineum objeto de instância do mecanismo. Ele é passado durante a criação JFlutterLoadere redefine dart代码包a maneira como o FlutterLoader original o obtém. Depois disso, comece a executar o código Dart de acordo com o DartEntrypoint fornecido. E armazene em cache a Flutter引擎instância criada. que é passado DartEntrypointpara 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
}

Criar várias entradas de dardo

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

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

Combinado com o código-fonte do Flutter, analise a inicialização do Flutter a partir da ponta nativa

Comunicação nativa com Flutter

insira a descrição da imagem aqui

tipo ilustrar
MétodoCanal Comunicação única usada para transferir invokeMethodchamadas de método: como chamar a função de ponto enterrado do Flutter.

Aqui vamos apresentar o MethodChannel , como se comunicar entre Native e Flutter~ O lado Flutter envia e o lado Native recebe e processa.
Flutter侧发送, combinado com o código-fonte, criando um MethodChannel实例e especificando o nome do canal name. E ambos os lados namedevem ser iguais. Em seguida, use a instância MethodChannel para chamar e executar 方法invokeMethod, e será chamado o método passado para o lado Nativo 方法名称methode o conteúdo da mensagem de comunicação arguments. Depois disso, a chamada de transferência do Flutter para o lado nativo é iniciada.
Native侧接收处理, crie um canal com nameo mesmo nome do canal lateral do Flutter MethodChannel实例. Use a instância MethodChannel para chamar e executar 方法setMethodCallHandlerpara corresponder Flutter侧方法名称methodàs informações de recebimento e processamento enviadas do lado do Flutter. Projeto e implementação detalhados, mova para ver

Página da categoria Vipshop de imitação do ReactJs

Introdução de desenvolvimento detalhada, mova para ver

Endereço de origem do projeto

Clique para entrar no warehouse para ver o código-fonte do projeto

Acho que você gosta

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