혼합 개발 Android 기사의 Flutter 시리즈

이전 기사에서는 Navigator 컴포넌트, Flex 레이아웃, 이미지 로딩, 위젯 라이프 사이클 등과 같은 Flutter 개발의 기본 지식을 소개했습니다. 기사 링크는 다음과 같습니다.

오늘은 Flutter 하이브리드 개발 모델과 기존 Android 프로젝트에 Flutter 모듈을 추가하는 방법을 소개하겠습니다. 주요 내용은 다음과 같습니다.

  1. Flutter 하이브리드 개발 모델
  2. Flutter 모듈을 만드는 방법
  3. Flutter를 추가하는 몇 가지 방법
  4. 단일 Flutter 페이지 추가
  5. FlutterFragment 추가
  6. Flutter와 Android가 서로 점프

Flutter 하이브리드 개발 모델

Flutetr 하이브리드 개발에는 일반적으로 두 가지 방법이 있습니다.

  1. 네이티브 프로젝트를 Flutter 프로젝트의 하위 프로젝트로 직접 사용하면 Flutter는 기본적으로 Android 및 iOS 용 프로젝트 디렉토리를 생성합니다.
  2. Flutter 모듈을 종속성으로 생성하고 기존 네이티브 프로젝트에 추가합니다.

두 번째 방법은 특히 기존 프로젝트의 낮은 비용을 위해 첫 번째 방법보다 더 분리되어 있습니다.

Flutter 모듈을 만드는 방법

Flutter 모듈을 만드는 방법에는 두 가지가 있습니다.

  1. 명령을 사용하여 Flutter 모듈 생성
flutter create -t module --org com.manu.flutter flutter_module_one
  1. As를 사용하여 Flutter 모듈 만들기

As에서 File-> New-> New Flutter Project를 선택하고 Flutter Module을 선택하여 다음과 같이 Flutter Module 하위 프로젝트를 만듭니다.

Flutter를 추가하는 몇 가지 방법

여기에 추가하는 방법은 두 번째 방법을 의미합니다. Flutter 모듈은 Flutter 모듈의 형태로 기존 프로젝트에 추가됩니다. 기존 Android 프로젝트에 Flutter를 추가하는 방법에는 두 가지가 있습니다.

  1. aar 방식으로 통합 된 기존 Android 프로젝트에서 :

Flutter 모듈을 생성 한 후에는 aar 형식으로 컴파일해야합니다. 다음 명령으로 aar를 컴파일 할 수 있습니다.

// cd到Flutter Module根目录
cd flutter_module
flutter build aar

Android에서는 As 도구를 사용하여 aar를 컴파일하고 Build-> Flutter-> Build AAR를 선택하여 aar를 컴파일 할 수도 있습니다.

그런 다음 프롬프트에 따라 기본 프로젝트 프로젝트의 build.grade 파일에서 관련 구성을 만듭니다. 다음을 참조하세요.

repositories {
    
    
    maven {
    
    
        url 'G:/xxx/flutter_module_one/build/host/outputs/repo'
    }
    maven {
    
    
        url 'https://storage.googleapis.com/download.flutter.io'
    }
}

buildTypes {
    
    
    profile {
    
    
        initWith debug
    }
}

dependencies {
    
    
    debugImplementation 'com.manu.flutter.flutter_module_one:flutter_debug:1.0'
    profileImplementation 'com.manu.flutter.flutter_module_one:flutter_profile:1.0'
    releaseImplementation 'com.manu.flutter.flutter_module_one:flutter_release:1.0'
}
  1. Flutet 모듈 방식으로 기존 Android 프로젝트에 통합 :

다음과 같이 setting.gradle 파일에서 flutter 모듈을 구성합니다.

include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(
  settingsDir,
  'flutter_module_two/.android/include_flutter.groovy'
))

그런 다음 다음과 같이 build.gradle 파일에 flutter 모듈의 종속성을 추가합니다.

dependencies {
    
    
  implementation project(':flutter')
}

단일 Flutter 페이지 추가

FlutterActivity를 상속하는 활동을 만들고 AndroidManifest.xml 파일에 선언합니다.

<activity
    android:name=".AgentActivity"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize">
</activity>

이 FlutterActivity를 시작하는 방법은 다음과 같습니다.

// 默认路由 /
myButton.setOnClickListener {
    
    
  startActivity(
    FlutterActivity.createDefaultIntent(this)
  )
}

// 自定义路由
myButton.setOnClickListener {
    
    
  startActivity(
    FlutterActivity
      .withNewEngine()
      .initialRoute("/my_route")
      .build(this)
  )
}

위 코드는 내부적으로 자체 FlutterEngine 인스턴스를 생성합니다. 각 FlutterActivity는 자체 FlutterEngine을 생성합니다. 즉, 표준 FlutterActivity를 시작하면 인터페이스가 표시 될 때 짧은 지연이 발생합니다. 미리 캐시 된 FlutterEngine을 사용하여 줄일 수 있습니다. 실제로 Delay는 내부적으로 사전 캐시 된 FlutterEngine이 있는지 먼저 확인합니다. 존재하는 경우 FlutterEngine을 사용하고, 그렇지 않으면 계속해서 사전 캐시되지 않은 FlutterEngine을 사용합니다. 소스 코드는 다음과 같이 판단됩니다.

/* package */ void setupFlutterEngine() {
    
    
Log.v(TAG, "Setting up FlutterEngine.");

 // 1. 检查预缓存的FlutterEngine
String cachedEngineId = host.getCachedEngineId();
if (cachedEngineId != null) {
    
    
  flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
  isFlutterEngineFromHost = true;
  if (flutterEngine == null) {
    
    
    throw new IllegalStateException(
        "The requested cached FlutterEngine did not exist in the FlutterEngineCache: '"
            + cachedEngineId
            + "'");
  }
  return;
}
// 2. 是否有自定义的FlutterEngine
// Second, defer to subclasses for a custom FlutterEngine.
flutterEngine = host.provideFlutterEngine(host.getContext());
if (flutterEngine != null) {
    
    
  isFlutterEngineFromHost = true;
  return;
}

Log.v(
    TAG,
    "No preferred FlutterEngine was provided. Creating a new FlutterEngine for"
        + " this FlutterFragment.");
// 3. 创建新的FlutterEngine
flutterEngine =
    new FlutterEngine(
        host.getContext(),
        host.getFlutterShellArgs().toArray(),
        /*automaticallyRegisterPlugins=*/ false);
isFlutterEngineFromHost = false;
}

미리 캐시 된 FlutterEngine의 사용은 반복되지 않으며 공식 웹 사이트를 직접 확인할 수 있습니다.

FlutterFragment 추가

마찬가지로 기존 Android 프로젝트에 FlutterFragment를 추가합니다. 후속 통신의 편의를 위해 다음과 같이 FlutterFragment를 상속하도록 Fragment를 사용자 정의한 다음 활동에 추가해야합니다.

class AgentActivity2 : FragmentActivity() {
    
    
    private val flutterFragmentTag = "flutter_fragment_tag"
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_agent2)
        val fragmentManager = supportFragmentManager
        var flutterFragment = fragmentManager.findFragmentByTag(flutterFragmentTag)
        if (flutterFragment == null){
    
    
//            flutterFragment = FlutterFragment.createDefault()
            flutterFragment = MFlutterFragment
                .withNewEngine()
                ?.build()
            if (flutterFragment != null) {
    
    
                fragmentManager.beginTransaction()
                    .add(R.id.ff_container,flutterFragment,flutterFragmentTag)
                    .commit()
            }
        }
    }
}

다음과 같이 FlutterFragment의 Activity에서 사용하는 Intent를 점프하고 추가하면됩니다.

// 跳转添加Fragment的Activyt
val intent = Intent(this@LaunchActivity,AgentActivity2::class.java)
startActivity(intent)

Flutter와 Android가 서로 점프

Flutter와 Android는 서로 점프합니다. 위는 기본적으로 기본 Android에서 FlutterActivity 또는 FlutterFragment를 추가하는 Activity로 점프 한 다음 Flutter 페이지에서 기본 Activity로 이동하는 방법입니다.

주로 MethodChannel, EventChannel 및 BasicMessageChannel을 포함하여 Flutter와 네이티브 간의 통신 메커니즘이 포함됩니다.이 섹션에는 많은 콘텐츠가 포함되어 있습니다. 한 섹션은 확실히 완료되지 않을 것입니다. 다음은 MethodChannel 사용에 대한 간략한 소개입니다. MethodChannel이 주로 사용됩니다. Flutter 페이지는 Android 네이티브 API에서 제공하는 메서드를 호출합니다.

Flutter에서 네이티브 Android 로의 점프를 실현하기 위해 MethodChannel을 주로 사용합니다. 단일 Flutter 페이지이든 FlutterFragment를 추가하든 각각 FlutterActivity와 FlutterFragment를 상속 한 다음 configureFlutterEngine 메서드를 다시 작성해야합니다. 다음을 참조하세요.

// FlutterActivity
class AgentActivity : FlutterActivity() {
    
    
    private val tag = AgentActivity::class.java.simpleName;
    private val channel = "com.manu.startMainActivity"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    
    
        super.configureFlutterEngine(flutterEngine)
        Log.d(tag,"configureFlutterEngine")
        // 注册MethodChannel,用来监听Flutter页面的方法调用
        MethodChannel(flutterEngine.dartExecutor, channel)
            .setMethodCallHandler {
    
     methodCall: MethodCall, result: MethodChannel.Result ->
                if ("startMainActivity" == methodCall.method) {
    
    
                    MainActivity.startMainActivity(this)
                    result.success("success")
                } else {
    
    
                    result.notImplemented()
                }
            }
    }

    companion object{
    
    
        /**
         * 重新创建NewEngineIntentBuilder才能保证生效
         */
        fun withNewEngine(): MNewEngineIntentBuilder? {
    
    
            return MNewEngineIntentBuilder(AgentActivity::class.java)
        }
    }

    /**
     * 自定义NewEngineIntentBuilder
     */
    class MNewEngineIntentBuilder(activityClass: Class<out FlutterActivity?>?) :
        NewEngineIntentBuilder(activityClass!!)
}

// 同理FlutterFragment也一样
// 省略 ...

withNewEngine 메서드를 다시 작성해야합니다. 그렇지 않으면 Flutter가 네이티브 액티비티로 이동하지 못하고 Flutter 페이지 invokeMethod가 다음과 같이 메서드를 호출합니다.

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
    
    
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Flutter Page"),
            centerTitle: true,
          ),
          body: PageWidget()
      ),
      routes: <String,WidgetBuilder>{
    
    

      },
    );
  }
}

/// Stateful Widget
class PageWidget extends StatefulWidget {
    
    

  @override
  State<StatefulWidget> createState() {
    
    
    return _PageState();
  }
}

/// State
class _PageState extends State<PageWidget> {
    
    
  MethodChannel platform;
  @override
  void initState() {
    
    
    super.initState();
    platform = new MethodChannel('com.manu.startMainActivity');
  }
  @override
  Widget build(BuildContext context) {
    
    
    return RaisedButton(
        onPressed: () {
    
    
          _startMainActivity();
        },
        child:  Text("Flutter to Android"),
    );
  }
  /// 跳转到原生Activity
  void _startMainActivity(){
    
    
    platform.invokeMethod('startMainActivity').then((value) {
    
    
      print("value:startMainActivity");
    }).catchError((e) {
    
    
      print(e.message);
    });
  }
}

또한 Flutter와 네이티브 커뮤니케이션 메커니즘은 후속 기사에서 소개 될 예정이며, 공식 계정의 백그라운드에서 [혼합 개발] 키워드에 답장하여 완성 된 소스 코드를 얻을 수 있습니다. 자세한 내용은 WeChat 공식을 참조하십시오. 계정 .

여기에 사진 설명 삽입

추천

출처blog.csdn.net/jzman/article/details/113487981