赞
踩
前面一篇介绍了承载Flutter的Activity的初始化过程,通过分析FlutterActivityDelegate我们知道了FlutterView是真正运行Flutter App的地方,所以这一篇文章主要来看一看FlutterView的功能。
先看一下FlutterView的UML图。
private final DartExecutor dartExecutor; private final NavigationChannel navigationChannel; private final KeyEventChannel keyEventChannel; private final LifecycleChannel lifecycleChannel; private final SettingsChannel settingsChannel; private final SystemChannel systemChannel; private final InputMethodManager mImm; private final TextInputPlugin mTextInputPlugin; private final AndroidKeyProcessor androidKeyProcessor; private final SurfaceHolder.Callback mSurfaceCallback; private final ViewportMetrics mMetrics; private final AccessibilityManager mAccessibilityManager; private final MethodChannel mFlutterLocalizationChannel; private final List<ActivityLifecycleListener> mActivityLifecycleListeners; private final List<FirstFrameListener> mFirstFrameListeners; private final AtomicLong nextTextureId = new AtomicLong(0L); private FlutterNativeView mNativeView; private final AnimationScaleObserver mAnimationScaleObserver; private boolean mIsSoftwareRenderingEnabled = false; // using the software renderer or not private InputConnection mLastInputConnection;
上面列举出了FlutterView中的成员变量,大致分类:
简单的从类的结构来看Flutter主要提供了和Flutter交互的的能力,以及为Flutter提供了Android系统的一些信息。
flutterView = viewFactory.createFlutterView(activity);
if (flutterView == null) {
FlutterNativeView nativeView = viewFactory.createFlutterNativeView();
flutterView = new FlutterView(activity, null, nativeView);
flutterView.setLayoutParams(matchParent);
activity.setContentView(flutterView);
launchView = createLaunchView();
if (launchView != null) {
addLaunchView();
}
}
在FlutterActivity初始化的时候,会通过FlutterActivityDelegate来初始化Flutter Engine,然后就会创建FlutterView。主要看看FlutterView的构造函数
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView)
这个构造函数内容比较多,我们分段来看:
如果外部没有传入FlutterNativeView,内部会自动创建一个。看似只有一行带代码,其实里面做了很多事情。
Activity activity = (Activity) getContext();
if (nativeView == null) {
mNativeView = new FlutterNativeView(activity.getApplicationContext());
} else {
mNativeView = nativeView;
}
FlutterNativeView实现了BinaryMeeenger接口, 先看一下创建的过程:
public FlutterNativeView(Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.setRenderSurface(new RenderSurfaceImpl());
mFlutterJNI.setPlatformMessageHandler(new PlatformMessageHandlerImpl());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
mMessageHandlers = new HashMap<>();
}
主要创建了FlutterPluginRegistry和FlutterJNI对象,这是FlutterNativeView最重要的两个成员变量:
创建完这2个对象之后,调用了FlutterJNI下面的个方法,这3个方法创建了3个内部类实例,设置给了FlutterJNI的成员变量。 使用这3个成员变量的方法并没有被java代码调用,注释上写被native调用,应该是在C++层的Engine被调用。主要是一些Flutter Engine通知Android 程序一些事件,比如渲染第一帧、Flutter发送过来的消息、Engine的生命周期。
public void setRenderSurface(@Nullable FlutterRenderer.RenderSurface renderSurface) {
this.renderSurface = renderSurface;
}
public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) {
this.platformMessageHandler = platformMessageHandler;
}
public void addEngineLifecycleListener(@NonNull EngineLifecycleListener engineLifecycleListener) {
engineLifecycleListeners.add(engineLifecycleListener);
}
然后调用了attach方法
private void attach(FlutterNativeView view, boolean isBackgroundView) {
mFlutterJNI.attachToNative(isBackgroundView);
}
内部还是调用FlutterJNI的方法,最终调用了native的方法获得了一个nativePlatformViewId
@UiThread
public void attachToNative(boolean isBackgroundView) {
ensureNotAttachedToNative();
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}
private native long nativeAttach(FlutterJNI flutterJNI, boolean isBackgroundView);
mIsSoftwareRenderingEnabled = mNativeView.getFlutterJNI().nativeGetIsSoftwareRenderingEnabled(); mAnimationScaleObserver = new AnimationScaleObserver(new Handler()); mMetrics = new ViewportMetrics(); mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density; setFocusable(true); setFocusableInTouchMode(true); mNativeView.attachViewAndActivity(this, activity); mSurfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface()); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceChanged(width, height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceDestroyed(); } }; getHolder().addCallback(mSurfaceCallback); mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mActivityLifecycleListeners = new ArrayList<>(); mFirstFrameListeners = new ArrayList<>();
这里比较杂,主要做了几件事:
dartExecutor = new DartExecutor(mNativeView.getFlutterJNI()); // Configure the platform plugins and flutter channels. navigationChannel = new NavigationChannel(dartExecutor); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); systemChannel = new SystemChannel(dartExecutor); settingsChannel = new SettingsChannel(dartExecutor); mFlutterLocalizationChannel = new MethodChannel(this, "flutter/localization", JSONMethodCodec.INSTANCE); PlatformPlugin platformPlugin = new PlatformPlugin(activity); MethodChannel flutterPlatformChannel = new MethodChannel(this, "flutter/platform", JSONMethodCodec.INSTANCE); flutterPlatformChannel.setMethodCallHandler(platformPlugin); addActivityLifecycleListener(platformPlugin); mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); mTextInputPlugin = new TextInputPlugin(this); androidKeyProcessor = new AndroidKeyProcessor(keyEventChannel);
这一部分创建了很多平台使用的channel,用于和Flutter之间通信,而且大多数的channel都传入了一个DartExecutor对象,它实现了BinaryMessenger接口,具有和Flutter通信的能力,所以这些Platform相关的Channel并没有使用FlutterNativeView 作为Messenger, 而是使用了DartExecutor, 他提供了执行指定Dart代码的能力(通过DartEntrypoint指定要执行的方法和代码的位置)。
public class DartExecutor implements BinaryMessenger
最后使用上面的channel把相关的一些信息传递给了Flutter(Dart)
setLocales(getResources().getConfiguration());
sendUserPlatformSettingsToDart();
创建了FlutterView,通过FlutterViewNative、FlutterJNI 、Flutter Channel, 当前的FlutterView或者说当前的Activity已经具有了和Flutter Engine交互的能力。接下来就是运行Flutter程序。
args.bundlePaths = bundlePaths.toArray(new String[0]);
args.entrypoint = "main";
flutterView.runFromBundle(args);
FlutterActivityDelegate中通过调用FlutterView的runFromBundle方法来执行。
private void preRun() {
resetAccessibilityTree();
}
private void postRun() {
}
public void runFromBundle(FlutterRunArguments args) {
assertAttached();
preRun();
mNativeView.runFromBundle(args);
postRun();
}
FlutterView里调用的是FlutterNativeView的方法
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"); } if (hasBundlePaths) { runFromBundleInternal(args.bundlePaths, args.entrypoint, args.libraryPath); } else { runFromBundleInternal(new String[] {args.bundlePath, args.defaultPath}, args.entrypoint, args.libraryPath); } }
这里主要检查了一下传入的参数,必须传递bundle文件路径和entrypoint 。使用runFromBundleInternal来处理。
private void runFromBundleInternal(String[] bundlePaths, String entrypoint,
String libraryPath) {
assertAttached();
if (applicationIsRunning)
throw new AssertionError(
"This Flutter engine instance is already running an application");
mFlutterJNI.runBundleAndSnapshotFromLibrary(
bundlePaths,
entrypoint,
libraryPath,
mContext.getResources().getAssets()
);
applicationIsRunning = true;
}
最终调用FlutterJNI让Engine来运行Flutter bundle。Flutter就会开始执行Dart程序,在FlutterView的SurfaceView绘制 UI。
FlutterView作为运行Flutter程序的容器,还有许多重要的功能,下面只简单的列举,因为每一个部分都是可以单独去研究的。
FlutterActivityDelegate会把Activity的生命周期都通知给FlutterView,所以FlutterView也有类似的声明周期的回调方法。在回调方法中FlutterView通过LifecycleChannel把生命周期的信息同步给了Flutter。
public void onPause() {
lifecycleChannel.appIsInactive();
}
public void onPostResume() {
updateAccessibilityFeatures();
for (ActivityLifecycleListener listener : mActivityLifecycleListeners) {
listener.onPostResume();
}
lifecycleChannel.appIsResumed();
}
public void onStop() {
lifecycleChannel.appIsPaused();
}
FlutterView重写了触屏相关的事件,中间收集了一些点击信息,最后都通过FlutterJNI().dispatchPointerDataPacket 发送给了Flutter, 这些后续研究触屏事件是在具体研究。
@Override public boolean onTouchEvent(MotionEvent event) { if (!isAttached()) { return false; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { requestUnbufferedDispatch(event); } final int kPointerDataFlagBatched = 1; int pointerCount = event.getPointerCount(); ByteBuffer packet = ByteBuffer.allocateDirect(pointerCount * kPointerDataFieldCount * kPointerBytesPerField); packet.order(ByteOrder.LITTLE_ENDIAN); int maskedAction = event.getActionMasked(); int pointerChange = getPointerChangeForAction(event.getActionMasked()); if (maskedAction == MotionEvent.ACTION_DOWN || maskedAction == MotionEvent.ACTION_POINTER_DOWN) { addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, packet); } else if (maskedAction == MotionEvent.ACTION_UP || maskedAction == MotionEvent.ACTION_POINTER_UP) { for (int p = 0; p < pointerCount; p++) { if (p != event.getActionIndex()) { if (event.getToolType(p) == MotionEvent.TOOL_TYPE_FINGER) { addPointerForIndex(event, p, kPointerChangeMove, kPointerDataFlagBatched, packet); } } } addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, packet); } else { for (int p = 0; p < pointerCount; p++) { addPointerForIndex(event, p, pointerChange, 0, packet); } } if (packet.position() % (kPointerDataFieldCount * kPointerBytesPerField) != 0) { throw new AssertionError("Packet position is not on field boundary"); } mNativeView.getFlutterJNI().dispatchPointerDataPacket(packet, packet.position()); return true; } @Override public boolean onHoverEvent(MotionEvent event) { if (!isAttached()) { return false; } boolean handled = handleAccessibilityHoverEvent(event); if (!handled) { // TODO(ianh): Expose hover events to the platform, // implementing ADD, REMOVE, etc. } return handled; } @Override public boolean onGenericMotionEvent(MotionEvent event) { if (!event.isFromSource(InputDevice.SOURCE_CLASS_POINTER) || event.getActionMasked() != MotionEvent.ACTION_HOVER_MOVE || !isAttached()) { return super.onGenericMotionEvent(event); } int pointerChange = getPointerChangeForAction(event.getActionMasked()); ByteBuffer packet = ByteBuffer.allocateDirect( event.getPointerCount() * kPointerDataFieldCount * kPointerBytesPerField); packet.order(ByteOrder.LITTLE_ENDIAN); // ACTION_HOVER_MOVE always applies to a single pointer only. addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, packet); if (packet.position() % (kPointerDataFieldCount * kPointerBytesPerField) != 0) { throw new AssertionError("Packet position is not on field boundary"); } mNativeView.getFlutterJNI().dispatchPointerDataPacket(packet, packet.position()); return true; }
FlutterView实现了BinaryMessenger接口,但是内部实际是调用FlutterNativeView的方法。关于和Flutter通信,后面也会单独研究。
@Override public void send(String channel, ByteBuffer message) { send(channel, message, null); } @Override public void send(String channel, ByteBuffer message, BinaryReply callback) { if (!isAttached()) { Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel); return; } mNativeView.send(channel, message, callback); } @Override public void setMessageHandler(String channel, BinaryMessageHandler handler) { mNativeView.setMessageHandler(channel, handler); }
对于FlutterNativeView来说,它是调用了FlutterJNI.dispatchPlatformMessage来发送消息
public void send(String channel, ByteBuffer message, BinaryReply callback) { if (!isAttached()) { Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel); return; } int replyId = 0; if (callback != null) { replyId = mNextReplyId++; mPendingReplies.put(replyId, callback); } if (message == null) { mFlutterJNI.dispatchEmptyPlatformMessage(channel, replyId); } else { mFlutterJNI.dispatchPlatformMessage( channel, message, message.position(), replyId ); } }
这一篇主要介绍了FlutterView初始化的流程和其他一些功能。FlutterView是比较重要的一个类:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。