(2) How does the Activity jump to the Flutter page, and how does the PageFlutterActivity. Kt class in the Flutter page pass

PageFlutterActivity.kt

package com.liuhc.myapplication

import android.os.Bundle
import android.util.Log
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterMain
import org.json.JSONObject

/** * liuhc * 标 志 : 2019-09-04 on 23:30 */
class PageFlutterActivity : FlutterActivity() {

    private lateinit var methodChannel: MethodChannel

    override fun onCreate(savedInstanceState: Bundle?). {
        // It is highly recommended that we initialize it once in Application, just for example
        FlutterMain.startInitialization(this)
        // Intent parameters must be set before super.oncreate because super.oncreate takes those parameters
        intent.action = "android.intent.action.RUN"
        val channelName = "channelName_PageFlutterActivity"
        val androidMethod = "methodName_PageFlutterActivity"
        val jsonObject = JSONObject()
        jsonObject.put("path"."InvokeMethodPage")
        jsonObject.put("title"."PageFlutterActivity")
        jsonObject.put("channelName", channelName)
        jsonObject.put("androidMethod", androidMethod)
        intent.putExtra("route", jsonObject.toString())
        super.onCreate(savedInstanceState)
        // flutterView will have a value after calling super.oncreate (savedInstanceState).
        // If you need to register a plug-in, you should place it after the super.onCreate(savedInstanceState) code
        flutterView.enableTransparentBackground()
        // If you don't need platform interaction, just use the code above and add super.oncreate at the end
        // This. RegistrarFor actually calls the delegate registrarFor method in the FlutterFragmentActivity.
        / / the delegate registrarFor method in the actual call is FlutterActivityDelegate flutterView. GetPluginRegistry () registrarFor method,
        // FlutterActivityDelegate flutterView has a value only after calling super.onCreate(savedInstanceState).
        // If you need to register a plug-in, you should place it after the super.onCreate(savedInstanceState) code
        val key = "PageFlutterActivity"
        if (this.hasPlugin(key)) return
        val registrar = this.registrarFor(key)
        methodChannel = MethodChannel(
            registrar.messenger(),
            channelName
        )
        methodChannel.setMethodCallHandler { methodCall, result ->
            if (methodCall.method == androidMethod) {
                Log.e("Android"."Parameters passed by Flutter are received:${methodCall.arguments}")
                result.success("$androidMethod ok")
                Log.e("Android"."Take the initiative to call Flutter methodInvokeMethodPageState method")
                methodChannel.invokeMethod("methodInvokeMethodPageState"."Parameters Android sends to Flutter")}}}}Copy the code

Look at this code right here

methodChannel = MethodChannel(
    registrar.messenger(),
    channelName
)
Copy the code

The registrar/messenger() method is registrarFor(key), the registrar/messenger(key) method is registrarFor(key), the registrar method is registrarFor(key), the registrar method is registrarFor(key), the registrar method is registrarFor(key), the registrar method is registrarFor(key). So we go to the parent class to check the registrarFor method, the source code is as follows:

FlutterActivity

public class FlutterActivity extends Activity implements Provider.PluginRegistry.ViewFactory {
    private static final String TAG = "FlutterActivity";
    private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this.this);
    private final FlutterActivityEvents eventDelegate;
    private final Provider viewProvider;
    private final PluginRegistry pluginRegistry;

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

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

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

    public final Registrar registrarFor(String pluginKey) {
        return this.pluginRegistry.registrarFor(pluginKey);
    }
    // Delete unnecessary code here
}
Copy the code

Can see registrarFor method calls are enclosing pluginRegistry. RegistrarFor method, and enclosing pluginRegistry can be seen in the constructor is actually FlutterActivityDelegate instance of a class, So let’s go back to the source code for FlutterActivityDelegate

FlutterActivityDelegate

public final class FlutterActivityDelegate implements FlutterActivityEvents.Provider.PluginRegistry {
    private static final String SPLASH_SCREEN_META_DATA_KEY = "io.flutter.app.android.SplashScreenUntilFirstFrame";
    private static final String TAG = "FlutterActivityDelegate";
    private static final LayoutParams matchParent = new LayoutParams(-1, -1);
    private final Activity activity;
    private final FlutterActivityDelegate.ViewFactory viewFactory;
    private FlutterView flutterView;
    private View launchView;

    public FlutterActivityDelegate(Activity activity, FlutterActivityDelegate.ViewFactory viewFactory) {
        this.activity = (Activity)Preconditions.checkNotNull(activity);
        this.viewFactory = (FlutterActivityDelegate.ViewFactory)Preconditions.checkNotNull(viewFactory);
    }

    public FlutterView getFlutterView(a) {
        return this.flutterView;
    }

    public boolean hasPlugin(String key) {
        return this.flutterView.getPluginRegistry().hasPlugin(key);
    }

    public Registrar registrarFor(String pluginKey) {
        return this.flutterView.getPluginRegistry().registrarFor(pluginKey);
    }

    public void onCreate(Bundle savedInstanceState) {
        if (VERSION.SDK_INT >= 21) {
            Window window = this.activity.getWindow();
            window.addFlags(-2147483648);
            window.setStatusBarColor(1073741824);
            window.getDecorView().setSystemUiVisibility(1280);
        }

        String[] args = getArgsFromIntent(this.activity.getIntent());
        FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
        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())) {
            String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
            if(appBundlePath ! =null) {
                this.runBundle(appBundlePath); }}}private boolean loadIntent(Intent intent) {
        String action = intent.getAction();
        if ("android.intent.action.RUN".equals(action)) {
            String route = intent.getStringExtra("route");
            String appBundlePath = intent.getDataString();
            if (appBundlePath == null) {
                appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
            }

            if(route ! =null) {
                this.flutterView.setInitialRoute(route);
            }

            this.runBundle(appBundlePath);
            return true;
        } else {
            return false; }}private void runBundle(String appBundlePath) {
        if (!this.flutterView.getFlutterNativeView().isApplicationRunning()) {
            FlutterRunArguments args = new FlutterRunArguments();
            ArrayList<String> bundlePaths = new ArrayList();
            bundlePaths.add(appBundlePath);
            args.bundlePaths = (String[])bundlePaths.toArray(new String[0]);
            args.entrypoint = "main";
            this.flutterView.runFromBundle(args); }}public interface ViewFactory {
        FlutterView createFlutterView(Context var1);

        FlutterNativeView createFlutterNativeView(a);

        boolean retainFlutterNativeView(a);
    }
    // Delete unnecessary code here
}
Copy the code

Find the registrarFor method

public Registrar registrarFor(String pluginKey) {
    return this.flutterView.getPluginRegistry().registrarFor(pluginKey);
}
Copy the code

Found that call is this. FlutterView. GetPluginRegistry () registrarFor (pluginKey), then we go to see a flutterView source

FlutterView

public class FlutterView extends SurfaceView implements BinaryMessenger.TextureRegistry {
    private FlutterNativeView mNativeView;

    public FlutterView(Context context) {
        this(context, (AttributeSet)null);
    }

    public FlutterView(Context context, AttributeSet attrs) {
        this(context, attrs, (FlutterNativeView)null);
    }

    public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
        super(context, attrs);
        this.nextTextureId = new AtomicLong(0L);
        this.mIsSoftwareRenderingEnabled = false;
        this.onAccessibilityChangeListener = new OnAccessibilityChangeListener() {
            public void onAccessibilityChanged(boolean isAccessibilityEnabled, boolean isTouchExplorationEnabled) {
                FlutterView.this.resetWillNotDraw(isAccessibilityEnabled, isTouchExplorationEnabled); }}; Activity activity = getActivity(this.getContext());
        if (activity == null) {
            throw new IllegalArgumentException("Bad context");
        } else {
            if (nativeView == null) {
                this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
            } else {
                this.mNativeView = nativeView;
            }

            this.dartExecutor = this.mNativeView.getDartExecutor();
            this.flutterRenderer = new FlutterRenderer(this.mNativeView.getFlutterJNI());
            this.mIsSoftwareRenderingEnabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled();
            this.mMetrics = new FlutterView.ViewportMetrics();
            this.mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density;
            this.setFocusable(true);
            this.setFocusableInTouchMode(true);
            this.mNativeView.attachViewAndActivity(this, activity);
            this.mSurfaceCallback = new Callback() {
                public void surfaceCreated(SurfaceHolder holder) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());
                }

                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
                }

                public void surfaceDestroyed(SurfaceHolder holder) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceDestroyed(); }};this.getHolder().addCallback(this.mSurfaceCallback);
            this.mActivityLifecycleListeners = new ArrayList();
            this.mFirstFrameListeners = new ArrayList();
            this.navigationChannel = new NavigationChannel(this.dartExecutor);
            this.keyEventChannel = new KeyEventChannel(this.dartExecutor);
            this.lifecycleChannel = new LifecycleChannel(this.dartExecutor);
            this.localizationChannel = new LocalizationChannel(this.dartExecutor);
            this.platformChannel = new PlatformChannel(this.dartExecutor);
            this.systemChannel = new SystemChannel(this.dartExecutor);
            this.settingsChannel = new SettingsChannel(this.dartExecutor);
            PlatformPlugin platformPlugin = new PlatformPlugin(activity, this.platformChannel);
            this.addActivityLifecycleListener(platformPlugin);
            this.mImm = (InputMethodManager)this.getContext().getSystemService("input_method");
            PlatformViewsController platformViewsController = this.mNativeView.getPluginRegistry().getPlatformViewsController();
            this.mTextInputPlugin = new TextInputPlugin(this.this.dartExecutor, platformViewsController);
            this.androidKeyProcessor = new AndroidKeyProcessor(this.keyEventChannel, this.mTextInputPlugin);
            this.androidTouchProcessor = new AndroidTouchProcessor(this.flutterRenderer);
            this.mNativeView.getPluginRegistry().getPlatformViewsController().attachTextInputPlugin(this.mTextInputPlugin);
            this.sendLocalesToDart(this.getResources().getConfiguration());
            this.sendUserPlatformSettingsToDart(); }}public FlutterNativeView getFlutterNativeView(a) {
        return this.mNativeView;
    }

    public FlutterPluginRegistry getPluginRegistry(a) {
        return this.mNativeView.getPluginRegistry();
    }

    public interface Provider {
        FlutterView getFlutterView(a); }}Copy the code

Find the getPluginRegistry method

public FlutterPluginRegistry getPluginRegistry(a) {
    return this.mNativeView.getPluginRegistry();
}
Copy the code

This. MNativeView is an instance of FlutterNativeView. Let’s look at the FlutterNativeView class

FlutterNativeView

public class FlutterNativeView implements BinaryMessenger {
    private static final String TAG = "FlutterNativeView";
    private final FlutterPluginRegistry mPluginRegistry;
    private final DartExecutor dartExecutor;
    private FlutterView mFlutterView;
    private final FlutterJNI mFlutterJNI;
    private final Context mContext;
    private boolean applicationIsRunning;

    public FlutterNativeView(@NonNull Context context) {
        this(context, false);
    }

    public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
        this.mContext = context;
        this.mPluginRegistry = new FlutterPluginRegistry(this, context);
        this.mFlutterJNI = new FlutterJNI();
        this.mFlutterJNI.setRenderSurface(new FlutterNativeView.RenderSurfaceImpl());
        this.dartExecutor = new DartExecutor(this.mFlutterJNI);
        this.mFlutterJNI.addEngineLifecycleListener(new FlutterNativeView.EngineLifecycleListenerImpl());
        this.attach(this, isBackgroundView);
        this.assertAttached();
    }

    @NonNull
    public FlutterPluginRegistry getPluginRegistry(a) {
        return this.mPluginRegistry;
    }

    public void runFromBundle(FlutterRunArguments args) {
        booleanhasBundlePaths = args.bundlePaths ! =null&& args.bundlePaths.length ! =0;
        if (args.bundlePath == null && !hasBundlePaths) {
            throw new AssertionError("Either bundlePath or bundlePaths must be specified");
        } else if((args.bundlePath ! =null|| args.defaultPath ! =null) && hasBundlePaths) {
            throw new AssertionError("Can't specify both bundlePath and bundlePaths");
        } else if (args.entrypoint == null) {
            throw new AssertionError("An entrypoint must be specified");
        } else {
            if (hasBundlePaths) {
                this.runFromBundleInternal(args.bundlePaths, args.entrypoint, args.libraryPath);
            } else {
                this.runFromBundleInternal(newString[]{args.bundlePath, args.defaultPath}, args.entrypoint, args.libraryPath); }}}/ * *@deprecated* /
    @Deprecated
    public void runFromBundle(String bundlePath, String defaultPath, String entrypoint, boolean reuseRuntimeController) {
        this.runFromBundleInternal(new String[]{bundlePath, defaultPath}, entrypoint, (String)null);
    }

    private void runFromBundleInternal(String[] bundlePaths, String entrypoint, String libraryPath) {
        this.assertAttached();
        if (this.applicationIsRunning) {
            throw new AssertionError("This Flutter engine instance is already running an application");
        } else {
            this.mFlutterJNI.runBundleAndSnapshotFromLibrary(bundlePaths, entrypoint, libraryPath, this.mContext.getResources().getAssets());
            this.applicationIsRunning = true; }}@UiThread
    public void send(String channel, ByteBuffer message) {
        this.dartExecutor.send(channel, message);
    }

    @UiThread
    public void send(String channel, ByteBuffer message, BinaryReply callback) {
        if (!this.isAttached()) {
            Log.d("FlutterNativeView"."FlutterView.send called on a detached view, channel=" + channel);
        } else {
            this.dartExecutor.send(channel, message, callback); }}@UiThread
    public void setMessageHandler(String channel, BinaryMessageHandler handler) {
        this.dartExecutor.setMessageHandler(channel, handler);
    }

    FlutterJNI getFlutterJNI(a) {
        return this.mFlutterJNI;
    }
    // Delete unnecessary code
}
Copy the code

Find the getPluginRegistry method

@NonNull
public FlutterPluginRegistry getPluginRegistry(a) {
    return this.mPluginRegistry;
}
Copy the code

Then take a look at the code for FlutterPluginRegistry

FlutterPluginRegistry

public class FlutterPluginRegistry implements PluginRegistry.RequestPermissionsResultListener.ActivityResultListener.NewIntentListener.UserLeaveHintListener.ViewDestroyListener {
    private static final String TAG = "FlutterPluginRegistry";
    private Activity mActivity;
    private Context mAppContext;
    private FlutterNativeView mNativeView;
    private FlutterView mFlutterView;
    private final PlatformViewsController mPlatformViewsController;
    private final Map<String, Object> mPluginMap = new LinkedHashMap(0);
    private final List<RequestPermissionsResultListener> mRequestPermissionsResultListeners = new ArrayList(0);
    private final List<ActivityResultListener> mActivityResultListeners = new ArrayList(0);
    private final List<NewIntentListener> mNewIntentListeners = new ArrayList(0);
    private final List<UserLeaveHintListener> mUserLeaveHintListeners = new ArrayList(0);
    private final List<ViewDestroyListener> mViewDestroyListeners = new ArrayList(0);

    public FlutterPluginRegistry(FlutterNativeView nativeView, Context context) {
        this.mNativeView = nativeView;
        this.mAppContext = context;
        this.mPlatformViewsController = new PlatformViewsController();
    }

    public FlutterPluginRegistry(FlutterEngine engine, Context context) {
        this.mAppContext = context;
        this.mPlatformViewsController = new PlatformViewsController();
    }

    public boolean hasPlugin(String key) {
        return this.mPluginMap.containsKey(key);
    }

    public Registrar registrarFor(String pluginKey) {
        if (this.mPluginMap.containsKey(pluginKey)) {
            throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
        } else {
            this.mPluginMap.put(pluginKey, (Object)null);
            return newFlutterPluginRegistry.FlutterRegistrar(pluginKey); }}private class FlutterRegistrar implements Registrar {
        private final String pluginKey;

        FlutterRegistrar(String pluginKey) {
            this.pluginKey = pluginKey;
        }

        public BinaryMessenger messenger(a) {
            return FlutterPluginRegistry.this.mNativeView;
        }

        public PlatformViewRegistry platformViewRegistry(a) {
            return FlutterPluginRegistry.this.mPlatformViewsController.getRegistry();
        }

        public FlutterView view(a) {
            return FlutterPluginRegistry.this.mFlutterView; }}}Copy the code

We look at the registrarFor method

public Registrar registrarFor(String pluginKey) {
    if (this.mPluginMap.containsKey(pluginKey)) {
        throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
    } else {
        this.mPluginMap.put(pluginKey, (Object)null);
        return newFlutterPluginRegistry.FlutterRegistrar(pluginKey); }}Copy the code

Can see FlutterActivity subclass call the superclass registrarFor, eventually get to the return value is the FlutterPluginRegistry. FlutterRegistrar instances of the class

Here we go through the whole process

When a subclass of FlutterActivity initially calls the registrarFor method, Final call order is FlutterActivity registrarFor – > FlutterActivityDelegate. RegistrarFor – > (FlutterView. GetPluginRegistry – > FlutterNative The getPluginRegistry – > return value FlutterPluginRegistry) – > FlutterPluginRegistry. RegistrarFor, Eventually return values for FlutterPluginRegistry FlutterRegistrar

Okay, now that we know where the registry came from, the original FlutterActivity subclass code

methodChannel = MethodChannel(
    registrar.messenger(),
    channelName
)
Copy the code

Inside of the registrar. Messenger () and what is actual, because FlutterActivity registrarFor method finally returned is FlutterPluginRegistry FlutterRegistrar, So the registrar. Messenger (). The return value is the FlutterPluginRegistry FlutterRegistrar messenger in class () method return values, We see FlutterPluginRegistry FlutterRegistrar messenger in the class () method

public BinaryMessenger messenger(a) {
    return FlutterPluginRegistry.this.mNativeView;
}
Copy the code

It returns an instance of the FlutterNativeView. Where did the mNativeView come from?

public FlutterPluginRegistry(FlutterNativeView nativeView, Context context) {
    this.mNativeView = nativeView;
    this.mAppContext = context;
    this.mPlatformViewsController = new PlatformViewsController();
}
Copy the code

This mNativeView instance is the one that FlutterNativeView passed itself as a parameter and assigned when it created FlutterPluginRegistry. And the FlutterNativeView is in the FlutterActivityDelegate onCreate method, FlutterActivityDelegate is created and passed as a parameter by calling the createFlutterNativeView method from the FlutterActivityDelegate property viewFactory (the viewFactory is where FlutterActivity passes itself as a parameter and assigns a value) ErView and assignment, or created by him FlutterView FlutterNative and assignment (if viewFactory createFlutterNativeView return value is null.)

The registrar.messenger() parameter at the beginning of the channel creation is the FlutterNativeView, Would it be ok to replace registrar. Messenger () with getFlutterView()? Yes, Since FlutterView implements interface BinaryMessenger and BinaryMessenger method implementations are delegated to mNativeView instances, the initial code can also be implemented as follows

methodChannel = MethodChannel(
    flutterView,
    channelName
)
Copy the code

or

methodChannel = MethodChannel(
    flutterView.flutterNativeView,
    channelName
)
Copy the code

But remember to register yourself as a plug-in by calling the parent’s registrarFor method in advance


Welcome to the Flutter development group 457664582. Click join to learn and discuss Flutter