FlutterFlutter学习Flutter

Flutter笔记--Flutter页面嵌入Android Ac

2019-01-11  本文已影响522人  ywy_袁滚滚

前言

 implementation project(':flutter')
package com.ywy.androidwithflutter

import android.os.Bundle
import android.view.View
import android.widget.FrameLayout
import io.flutter.app.FlutterFragmentActivity
import io.flutter.facade.Flutter

class MainFlutterActivity : FlutterFragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_flutter)
        val mFlutterView: View = Flutter.createView(this, lifecycle, "main_flutter")
        val mParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT)
        addContentView(mFlutterView, mParams)
    }
}
package com.ywy.androidwithflutter

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val dumpIntent = Intent(this, MainFlutterActivity::class.java)
        btnJumpToFlutter.setOnClickListener { startActivity(dumpIntent) }
    }
}
01-08 17:08:07.813 7220-7220/com.ywy.androidwithflutter E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.ywy.androidwithflutter, PID: 7220
                                                                          java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ywy.androidwithflutter/com.ywy.androidwithflutter.MainFlutterActivity}: java.lang.IllegalStateException: ensureInitializationComplete must be called after startInitialization
                                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
                                                                              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
                                                                              at android.app.ActivityThread.-wrap11(Unknown Source:0)
                                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:105)
                                                                              at android.os.Looper.loop(Looper.java:164)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:6541)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
                                                                           Caused by: java.lang.IllegalStateException: ensureInitializationComplete must be called after startInitialization
                                                                              at io.flutter.view.FlutterMain.ensureInitializationComplete(FlutterMain.java:178)
                                                                              at io.flutter.app.FlutterActivityDelegate.onCreate(FlutterActivityDelegate.java:152)
                                                                              at io.flutter.app.FlutterFragmentActivity.onCreate(FlutterFragmentActivity.java:89)
                                                                              at com.ywy.androidwithflutter.MainFlutterActivity.onCreate(MainFlutterActivity.kt:12)
                                                                              at android.app.Activity.performCreate(Activity.java:6975)
                                                                              at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
                                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
                                                                              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
                                                                              at android.app.ActivityThread.-wrap11(Unknown Source:0) 
                                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
                                                                              at android.os.Handler.dispatchMessage(Handler.java:105) 
                                                                              at android.os.Looper.loop(Looper.java:164) 
                                                                              at android.app.ActivityThread.main(ActivityThread.java:6541) 
                                                                              at java.lang.reflect.Method.invoke(Native Method) 
                                                                              at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package io.flutter.app;

import android.app.Activity;
import android.app.Application;
import android.support.annotation.CallSuper;
import io.flutter.view.FlutterMain;

public class FlutterApplication extends Application {
    private Activity mCurrentActivity = null;

    public FlutterApplication() {
    }

    @CallSuper
    public void onCreate() {
        super.onCreate();
        FlutterMain.startInitialization(this);
    }

    public Activity getCurrentActivity() {
        return this.mCurrentActivity;
    }

    public void setCurrentActivity(Activity mCurrentActivity) {
        this.mCurrentActivity = mCurrentActivity;
    }
}

class MainFlutterActivity : FlutterFragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        FlutterMain.startInitialization(applicationContext)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_flutter)
        val mFlutterView: View = Flutter.createView(this, lifecycle, "main_flutter")
        val mParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT)
        addContentView(mFlutterView, mParams)
    }
}
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
        // counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
      routes: <String, WidgetBuilder>{
        "main_flutter": (context) => MyHomePage()
      },
    );
  }
}
  routes: <String, WidgetBuilder>{
        "main_flutter": (context) => MyHomePage(),
        "route_key": (context) => ANewPage()
      }
public class FlutterFragmentActivity extends FragmentActivity implements Provider, PluginRegistry, ViewFactory {
    private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
    private final FlutterActivityEvents eventDelegate;
    private final Provider viewProvider;
    private final PluginRegistry pluginRegistry;

    public FlutterFragmentActivity() {
        this.eventDelegate = this.delegate;
        this.viewProvider = this.delegate;
        this.pluginRegistry = this.delegate;
    }

    public FlutterView getFlutterView() {
        return this.viewProvider.getFlutterView();
    }

    public FlutterView createFlutterView(Context context) {
        return null;
    }

    public FlutterNativeView createFlutterNativeView() {
        return null;
    }

    public boolean retainFlutterNativeView() {
        return false;
    }

    public final boolean hasPlugin(String key) {
        return this.pluginRegistry.hasPlugin(key);
    }

    public final <T> T valuePublishedByPlugin(String pluginKey) {
        return this.pluginRegistry.valuePublishedByPlugin(pluginKey);
    }

    public final Registrar registrarFor(String pluginKey) {
        return this.pluginRegistry.registrarFor(pluginKey);
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.eventDelegate.onCreate(savedInstanceState);
    }

    protected void onDestroy() {
        this.eventDelegate.onDestroy();
        super.onDestroy();
    }

    public void onBackPressed() {
        if(!this.eventDelegate.onBackPressed()) {
            super.onBackPressed();
        }

    }

    protected void onStop() {
        this.eventDelegate.onStop();
        super.onStop();
    }

    protected void onPause() {
        super.onPause();
        this.eventDelegate.onPause();
    }

    protected void onPostResume() {
        super.onPostResume();
        this.eventDelegate.onPostResume();
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        this.eventDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(!this.eventDelegate.onActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        }

    }

    protected void onNewIntent(Intent intent) {
        this.eventDelegate.onNewIntent(intent);
    }

    public void onUserLeaveHint() {
        this.eventDelegate.onUserLeaveHint();
    }

    public void onTrimMemory(int level) {
        this.eventDelegate.onTrimMemory(level);
    }

    public void onLowMemory() {
        this.eventDelegate.onLowMemory();
    }

    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        this.eventDelegate.onConfigurationChanged(newConfig);
    }
}
  //只有一个方法,提供获取FlutterView
   public interface Provider {
        FlutterView getFlutterView();
    }

// 用于插件注册,这里的插件注册在之后的flutter和android native通讯中会用到,当然flutter与ios通讯方式也差不多
public interface PluginRegistry {
    // 注册一个插件
    PluginRegistry.Registrar registrarFor(String var1);
    // 是否有这个插件
    boolean hasPlugin(String var1);
    // 插件发布的值
    <T> T valuePublishedByPlugin(String var1);

    //插件生命周期回调
    public interface PluginRegistrantCallback {
        void registerWith(PluginRegistry var1);
    }

    //视图销毁的回调
    public interface ViewDestroyListener {
        boolean onViewDestroy(FlutterNativeView var1);
    }

   //下面的都是在Activity中熟悉的回调
    
    //用户主动离开activity时会调用,比如切任务或者按home键,必须是用户主动的
    public interface UserLeaveHintListener {
        void onUserLeaveHint();
    }
   
    // 当activity 重新启动的时候调用
    public interface NewIntentListener {
        boolean onNewIntent(Intent var1);
    }
    
    //获取activity的返回值的回调
    public interface ActivityResultListener {
        boolean onActivityResult(int var1, int var2, Intent var3);
    }

  //请求权限的回调
    public interface RequestPermissionsResultListener {
        boolean onRequestPermissionsResult(int var1, String[] var2, int[] var3);
    }

    /// 插件的注册者
    public interface Registrar {
        //插件的宿主activity
        Activity activity();
        //插件的上下文 Application Context.
        Context context();
        //当前活动的context
        Context activeContext();
       //返回 BinaryMessenger 主要用来注册Platform channels
        BinaryMessenger messenger();
        //返回 TextureRegistry,从里面可以拿到SurfaceTexture 
        TextureRegistry textures();
        /// 获取视图
        FlutterView view();
        //返回Asset资源对应的路径
        String lookupKeyForAsset(String var1);
       //返回Asset资源对应的路径
        String lookupKeyForAsset(String var1, String var2);
        //插件发布一个值,与上面的valuePublishedByPlugin对应
        PluginRegistry.Registrar publish(Object var1);
        
       //下面的都是添加上面的回调监听
        PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener var1);

        PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener var1);

        PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener var1);

        PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener var1);
        
        PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener var1);
    }
}
  public static FlutterView createView(@NonNull final Activity activity, @NonNull final Lifecycle lifecycle, final String initialRoute) {
    FlutterMain.startInitialization(activity.getApplicationContext());
    FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), null);
    final FlutterNativeView nativeView = new FlutterNativeView(activity);
    final FlutterView flutterView = new FlutterView(activity, null, nativeView) {
      //other code
};
   if (initialRoute != null) {
      flutterView.setInitialRoute(initialRoute);
    }
    flutterView.setAlpha(0.0f);
    return flutterView;
  }
   public static void startInitialization(Context applicationContext) {
        //调用两个参数的方法
        startInitialization(applicationContext, new FlutterMain.Settings());
    }

    public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {
        if(Looper.myLooper() != Looper.getMainLooper()) {
            throw new IllegalStateException("startInitialization must be called on the main thread");
        } else if(sSettings == null) {
            //执行完FlutterMain.startInitialization(activity.getApplicationContext());之后,sSettings 不为null
            sSettings = settings;
            long initStartTimestampMillis = SystemClock.uptimeMillis();
            initConfig(applicationContext);
            initAot(applicationContext);
            initResources(applicationContext);
            System.loadLibrary("flutter");
            long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
            nativeRecordStartTimestamp(initTimeMillis);
        }
    }
public static void ensureInitializationComplete(Context applicationContext, String[] args) {
        if(Looper.myLooper() != Looper.getMainLooper()) {
            throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
        } else if(sSettings == null) {
          //重点看这里,当sSettings 为空的时候报错
            throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");
        } else if(!sInitialized) {
           //other code
        }
    }
 public void onCreate(Bundle savedInstanceState) {
        //other code

        String[] args = getArgsFromIntent(this.activity.getIntent());
        //最终找到元凶 ,在这里也调用了该方法,所以需要在super.onCreate()之前调用FlutterMain.startInitialization(getApplicationContext())
        FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
      
      //创建flutterView ,注意viewFactory.createFlutterView默认返回的是null
        this.flutterView = this.viewFactory.createFlutterView(this.activity);
        if(this.flutterView == null) {
            //默认走该流程
            FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
            this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
            this.flutterView.setLayoutParams(matchParent);
            this.activity.setContentView(this.flutterView);
            this.launchView = this.createLaunchView();
            if(this.launchView != null) {
                this.addLaunchView();
            }
        }

        if(!this.loadIntent(this.activity.getIntent())) {
            if(!this.flutterView.getFlutterNativeView().isApplicationRunning()) {
                String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
                if(appBundlePath != null) {
                    FlutterRunArguments arguments = new FlutterRunArguments();
                    arguments.bundlePath = appBundlePath;
                    arguments.entrypoint = "main";
                    this.flutterView.runFromBundle(arguments);
                }
            }

        }
    }
public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry, AccessibilityStateChangeListener {
  //other code
   private final MethodChannel mFlutterLocalizationChannel;
    private final MethodChannel mFlutterNavigationChannel;
    private final BasicMessageChannel<Object> mFlutterKeyEventChannel;
    private final BasicMessageChannel<String> mFlutterLifecycleChannel;
    private final BasicMessageChannel<Object> mFlutterSystemChannel;
    private final BasicMessageChannel<Object> mFlutterSettingsChannel;
 

    public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
   //other code

        this.mFlutterNavigationChannel = new MethodChannel(this, "flutter/navigation", JSONMethodCodec.INSTANCE);
 
    }


    public void setInitialRoute(String route) {
        this.mFlutterNavigationChannel.invokeMethod("setInitialRoute", route);
    }

    public void pushRoute(String route) {
        this.mFlutterNavigationChannel.invokeMethod("pushRoute", route);
    }

    public void popRoute() {
        this.mFlutterNavigationChannel.invokeMethod("popRoute", (Object)null);
    }

    //other code

}
  if (initialRoute != null) {
      flutterView.setInitialRoute(initialRoute);
    }
 public void setInitialRoute(String route) {
        this.mFlutterNavigationChannel.invokeMethod("setInitialRoute", route);
    }

 /// A JSON [MethodChannel] for navigation.
  ///
  /// The following incoming methods are defined for this channel (registered
  /// using [MethodChannel.setMethodCallHandler]):
  ///
  ///  * `popRoute`, which is called when the system wants the current route to
  ///    be removed (e.g. if the user hits a system-level back button).
  ///
  ///  * `pushRoute`, which is called with a single string argument when the
  ///    operating system instructs the application to open a particular page.
  ///
  /// See also:
  ///
  ///  * [WidgetsBindingObserver.didPopRoute] and
  ///    [WidgetsBindingObserver.didPushRoute], which expose this channel's
  ///    methods.
  static const MethodChannel navigation = MethodChannel(
      'flutter/navigation',
      JSONMethodCodec(),
  );

  SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);

  Future<dynamic> _handleNavigationInvocation(MethodCall methodCall) {
    switch (methodCall.method) {
      case 'popRoute':
        return handlePopRoute();
      case 'pushRoute':
        return handlePushRoute(methodCall.arguments);
    }
    return Future<dynamic>.value();
  }

/// The [MaterialApp] configures the top-level [Navigator] to search for routes
/// in the following order:
///
///  1. For the `/` route, the [home] property, if non-null, is used.
///
///  2. Otherwise, the [routes] table is used, if it has an entry for the route.
///
///  3. Otherwise, [onGenerateRoute] is called, if provided. It should return a
///     non-null value for any _valid_ route not handled by [home] and [routes].
///
///  4. Finally if all else fails [onUnknownRoute] is called.
///
/// If a [Navigator] is created, at least one of these options must handle the
/// `/` route, since it is used when an invalid [initialRoute] is specified on
/// startup (e.g. by another application launching this one with an intent on
/// Android; see [Window.defaultRouteName]).
///
/// This widget also configures the observer of the top-level [Navigator] (if
/// any) to perform [Hero] animations.
///
/// If [home], [routes], [onGenerateRoute], and [onUnknownRoute] are all null,
/// and [builder] is not null, then no [Navigator] is created.

class MaterialApp extends StatefulWidget {
//other code

/// {@macro flutter.widgets.widgetsApp.home}
  final Widget home;

  /// The application's top-level routing table.
  ///
  /// When a named route is pushed with [Navigator.pushNamed], the route name is
  /// looked up in this map. If the name is present, the associated
  /// [WidgetBuilder] is used to construct a [MaterialPageRoute] that performs
  /// an appropriate transition, including [Hero] animations, to the new route.
  ///
  /// {@macro flutter.widgets.widgetsApp.routes}
  final Map<String, WidgetBuilder> routes;

  /// {@macro flutter.widgets.widgetsApp.initialRoute}
  final String initialRoute;

  /// {@macro flutter.widgets.widgetsApp.onGenerateRoute}
  final RouteFactory onGenerateRoute;

  /// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
  final RouteFactory onUnknownRoute;


}
  1. 对于'/'路由,如果[home]属性配置不为空,首先使用
  2. 对于非'/'路由,优先使用[routes]配置的(如果它包含路由的条目的话)
  3. 否则,如果[onGenerateRoute]提供了一个有效的没有被[home]和[routes]处理的路由,调用
  4. 最后,如果前面的寻找都失败了,调用[onUnknownRoute]
  5. 如果所有的都失败了,将不会进行导航
  6. 从其它应用启动时指定了无效的[initialRoute],默认使用 ' / '路由
 /// {@template flutter.widgets.widgetsApp.initialRoute}
  /// The name of the first route to show, if a [Navigator] is built.
  ///
  /// Defaults to [Window.defaultRouteName], which may be overridden by the code
  /// that launched the application.
  ///
  /// If the route contains slashes, then it is treated as a "deep link", and
  /// before this route is pushed, the routes leading to this one are pushed
  /// also. For example, if the route was `/a/b/c`, then the app would start
  /// with the three routes `/a`, `/a/b`, and `/a/b/c` loaded, in that order.
  ///
  /// If any part of this process fails to generate routes, then the
  /// [initialRoute] is ignored and [Navigator.defaultRouteName] is used instead
  /// This can happen if the app is started with an intent that specifies
  /// a non-existent route.
  /// The [Navigator] is only built if routes are provided (either via [home],
  /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
  /// [initialRoute] must be null and [builder] must not be null.

  /// {@endtemplate}
  final String initialRoute;
  /// The route or path that the embedder requested when the application was
  /// launched.
  ///
  /// This will be the string "`/`" if no particular route was requested.
  ///
  /// ## Android
  ///
  /// On Android, calling
  /// [`FlutterView.setInitialRoute`](/javadoc/io/flutter/view/FlutterView.html#setInitialRoute-java.lang.String-)
  /// will set this value. The value must be set sufficiently early, i.e. before
  /// the [runApp] call is executed in Dart, for this to have any effect on the
  /// framework. The `createFlutterView` method in your `FlutterActivity`
  /// subclass is a suitable time to set the value. The application's
  /// `AndroidManifest.xml` file must also be updated to have a suitable
  /// [`<intent-filter>`](https://developer.android.com/guide/topics/manifest/intent-filter-element.html).
  ///
  /// See also:
  ///
  ///  * [Navigator], a widget that handles routing.
  ///  * [SystemChannels.navigation], which handles subsequent navigation
  ///    requests from the embedder.
  String get defaultRouteName => _defaultRouteName();
  String _defaultRouteName() native 'Window_defaultRouteName';

待解决问题

扩展

上一篇下一篇

猜你喜欢

热点阅读