Flutter Android端注册插件流程源码解析
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?) {
//强烈建议放到Application里初始化,初始化一次即可,放这里只是举个例子
FlutterMain.startInitialization(this)
//intent的参数设置必须在super.onCreate之前,因为super.onCreate里会取这些参数
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)
//调用super.onCreate(savedInstanceState)之后flutterView才有值,
//所以如果需要注册插件,则应该放到super.onCreate(savedInstanceState)代码之后才可以
flutterView.enableTransparentBackground()
//如果不需要平台交互的话,只需要上面的代码并在最后加上super.onCreate就可以了
//这里this.registrarFor方法实际调用的是FlutterFragmentActivity里的delegate的registrarFor方法,
//而delegate的registrarFor方法实际调用的是FlutterActivityDelegate里的flutterView.getPluginRegistry().registrarFor方法,
//而FlutterActivityDelegate里的flutterView在调用了这里的super.onCreate(savedInstanceState)才有值,
//所以如果需要注册插件,则应该放到super.onCreate(savedInstanceState)代码之后才可以
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", "接收到了Flutter传递的参数:${methodCall.arguments}")
result.success("$androidMethod ok")
Log.e("Android", "主动调用Flutter的methodInvokeMethodPageState方法")
methodChannel.invokeMethod("methodInvokeMethodPageState", "Android发送给Flutter的参数")
}
}
}
}
复制代码
看其中的这段代码
methodChannel = MethodChannel(
registrar.messenger(),
channelName
)
复制代码
MethodChannel
这里我们传了2个参数,第二个就是一个String类型,我们主要看第一个registrar.messenger()
是什么,这个registrar
是我们调用父类的方法registrarFor(key)
得到的,所以我们去父类查看registrarFor
方法,源码如下:
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() {
this.eventDelegate = this.delegate;
this.viewProvider = this.delegate;
this.pluginRegistry = this.delegate;
}
public FlutterView getFlutterView() {
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);
}
//删掉了这里不需要关心的代码
}
复制代码
可以看到registrarFor
方法调用的是this.pluginRegistry.registrarFor
方法,而this.pluginRegistry
在构造函数里可看到实际上是FlutterActivityDelegate
类的实例,所以我们再去看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() {
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();
boolean retainFlutterNativeView();
}
//删掉了这里不需要关心的代码
}
复制代码
找到其中的registrarFor
方法
public Registrar registrarFor(String pluginKey) {
return this.flutterView.getPluginRegistry().registrarFor(pluginKey);
}
复制代码
发现调用的是this.flutterView.getPluginRegistry().registrarFor(pluginKey)
,我们再去看FlutterView
的源码
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() {
return this.mNativeView;
}
public FlutterPluginRegistry getPluginRegistry() {
return this.mNativeView.getPluginRegistry();
}
public interface Provider {
FlutterView getFlutterView();
}
}
复制代码
找到其中的getPluginRegistry
方法
public FlutterPluginRegistry getPluginRegistry() {
return this.mNativeView.getPluginRegistry();
}
复制代码
this.mNativeView
是FlutterNativeView
的实例,我们再去看FlutterNativeView
类
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() {
return this.mPluginRegistry;
}
public void runFromBundle(FlutterRunArguments args) {
boolean hasBundlePaths = 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(new String[]{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() {
return this.mFlutterJNI;
}
//删掉了不需要关心的代码
}
复制代码
找到其中的getPluginRegistry
方法
@NonNull
public FlutterPluginRegistry getPluginRegistry() {
return this.mPluginRegistry;
}
复制代码
然后再看一下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 new FlutterPluginRegistry.FlutterRegistrar(pluginKey);
}
}
private class FlutterRegistrar implements Registrar {
private final String pluginKey;
FlutterRegistrar(String pluginKey) {
this.pluginKey = pluginKey;
}
public BinaryMessenger messenger() {
return FlutterPluginRegistry.this.mNativeView;
}
public PlatformViewRegistry platformViewRegistry() {
return FlutterPluginRegistry.this.mPlatformViewsController.getRegistry();
}
public FlutterView view() {
return FlutterPluginRegistry.this.mFlutterView;
}
}
}
复制代码
我们看其中的registrarFor方法
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 new FlutterPluginRegistry.FlutterRegistrar(pluginKey);
}
}
复制代码
可以看到FlutterActivity
的子类调用父类的registrarFor时,最终获取到的返回值就是FlutterPluginRegistry.FlutterRegistrar类的实例
到这里我们把整个流程梳理一下
最开始FlutterActivity
的子类调用registrarFor
方法时,最终调用顺序是FlutterActivity
.registrarFor->FlutterActivityDelegate
.registrarFor->(FlutterView
.getPluginRegistry->FlutterNativeView
.getPluginRegistry->返回值FlutterPluginRegistry
)->FlutterPluginRegistry
.registrarFor,最终返回值为FlutterPluginRegistry.FlutterRegistrar
好了,现在注册器的来历我们弄清楚了,那么最开始的FlutterActivity
的子类代码里
methodChannel = MethodChannel(
registrar.messenger(),
channelName
)
复制代码
里面的registrar.messenger()
实际是什么呢,因为FlutterActivity
里的registrarFor
方法最终返回的是FlutterPluginRegistry.FlutterRegistrar
,所以registrar.messenger()
的返回值就是FlutterPluginRegistry.FlutterRegistrar
类里的messenger()
方法的返回值,我们看一下FlutterPluginRegistry.FlutterRegistrar
类里的messenger()
方法
public BinaryMessenger messenger() {
return FlutterPluginRegistry.this.mNativeView;
}
复制代码
返回的是FlutterNativeView
的实例,这个mNativeView
是哪里来的呢?
public FlutterPluginRegistry(FlutterNativeView nativeView, Context context) {
this.mNativeView = nativeView;
this.mAppContext = context;
this.mPlatformViewsController = new PlatformViewsController();
}
复制代码
这个mNativeView
实例就是FlutterNativeView
创建FlutterPluginRegistry
时将自己作为参数传入并赋值的,而FlutterNativeView
是在FlutterActivityDelegate
的onCreate
方法里,由FlutterActivityDelegate
的属性viewFactory
调用createFlutterNativeView
方法(viewFactory是FlutterActivity将自己作为参数传入并赋值)创建并作为参数传入FlutterView
并赋值的,或者是由FlutterView
自己创建的FlutterNative
并赋值的(如果viewFactory.createFlutterNativeView返回值为null)
到这里,我们也就知道了最开始创建通道时的参数registrar.messenger()
到底是什么了,实际就是FlutterNativeView
,那么我们将registrar.messenger()
替换为getFlutterView()
可以吗,答案是可以的,因为FlutterView
实现了接口BinaryMessenger
并且BinaryMessenger
的方法实现都委托给了mNativeView
实例,所以最开始的代码也可以用如下方式实现
methodChannel = MethodChannel(
flutterView,
channelName
)
复制代码
或者
methodChannel = MethodChannel(
flutterView.flutterNativeView,
channelName
)
复制代码
但是用这种方式的话记得提前调用父类的registrarFor
注册方法将自己作为插件注册到系统
作者:o动感超人o
链接:https://juejin.im/post/5d72054ae51d453b386a638a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。