当前位置: 首页 > >

现有Android项目中集成Flutter/Flutter混合开发实战(二):FlutterActivity源码分析

发布时间:

二.集成Flutter
2.通过继承FlutterActivity等组件集成

需要说明的是,我最后在通过route添加不同flutter界面的地方失败了,目前没有找到好的解决办法,如果有人研究过这个,希望可以指出我的错误,帮我解决。


第一篇文章中详细介绍了如何将FlutterView添加到Android原生页面布局中。


(PS:有小伙伴在评论里说,可以设置监听来达到原生控件和FlutterView同时加载的效果,的确是一个可以优化的点,谢谢您的帮助!)


第二种方式是通过继承FlutterActivity、FlutterFragment及FlutterFragmentActivity。





public class FlutterExtendActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}复制代码

但是目前有个问题没有解决,是这样的:


这样创建的Activity中的Flutter界面是default值,也就是空值返回的界面,但我们不可能永远通过默认的initialRoute来添加FlutterView。


如果在FlutterActivity的onCreate中更改route值呢?





@Override
protected void onCreate(Bundle savedInstanceState) {
FlutterMain.startInitialization(getApplicationContext());
super.onCreate(savedInstanceState);
getFlutterView().setInitialRoute("flutter_activity");
复制代码


失败了。







getFlutterView().pushRoute("flutter_activity");
复制代码


也失败了。




--------------------------------------------------------------------


↑这两张图其实是同一张...反正都不成功


主要原因是,super.onCreate之后,FlutterActivity已经创建好了布局,而且我们的这个Activity中又没有setContentView()的实现,设置route的操作不能挪到super.onCreate()前面。




我查看了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 FlutterView createFlutterView(Context context) {
return null;
}

public FlutterNativeView createFlutterNativeView() {
return null;
}

public boolean retainFlutterNativeView() {
return false;
}
}复制代码



可以看出FlutterActivity实际是继承了Activity,实现了FlutterView.Provider、


PluginRegistry、ViewFactory三个接口。


但是FlutterActivity的三个在实例化时候的变量都指向了一个FlutterActivityDelegate对象,也就是说,它代理了FlutterActivity几乎所有的动作。


三个接口大致内容如下:


(1).FlutterView.Provider





public interface Provider {
FlutterView getFlutterView();
}复制代码


FlutterView.Provider是一个接口,提供了getFlutterView()抽象方法


那么FlutterActivity的具体实现呢?





public FlutterView getFlutterView() {
return this.viewProvider.getFlutterView();
}复制代码

但是viewProvider又指向了这个FlutterActivityDelegate;


(2).PluginRegistry





public interface PluginRegistry {
PluginRegistry.Registrar registrarFor(String var1);

boolean hasPlugin(String var1);

T valuePublishedByPlugin(String var1);

public interface PluginRegistrantCallback {
void registerWith(PluginRegistry var1);
}

public interface ViewDestroyListener {
boolean onViewDestroy(FlutterNativeView var1);
}

public interface UserLeaveHintListener {
void onUserLeaveHint();
}

public interface NewIntentListener {
boolean onNewIntent(Intent var1);
}

public interface ActivityResultListener {
boolean onActivityResult(int var1, int var2, Intent var3);
}

public interface RequestPermissionsResultListener {
boolean onRequestPermissionsResult(int var1, String[] var2, int[] var3);
}
}复制代码

(3).ViewFactory





public interface ViewFactory {
FlutterView createFlutterView(Context var1);

FlutterNativeView createFlutterNativeView();

boolean retainFlutterNativeView();
}复制代码


具体实现:





public FlutterView createFlutterView(Context context) {
return null;
}
public FlutterNativeView createFlutterNativeView() {
return null;
}
public boolean retainFlutterNativeView() {
return false;
}复制代码

也就是...这个接口的实现基本没有什么意义.


所以我们还是要看FlutterActivityDelegate这个类和它的实例究竟做了什么.





protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.eventDelegate.onCreate(savedInstanceState);
}复制代码


调用了eventDelegate.onCreate(),我们可以顺藤摸瓜看看它的onCreate()





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);
}

}
}复制代码


FlutterView是由FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView)?这个构造方法new出来的。


实际上,





@NonNull
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);
//↓这里还是调用了FlutterView的三个参数构造
final FlutterView flutterView = new FlutterView(activity, null, nativeView) {
private final BasicMessageChannel lifecycleMessages = new BasicMessageChannel<>(this, "flutter/lifecycle", StringCodec.INSTANCE);
@Override
public void onFirstFrame() {
super.onFirstFrame();
setAlpha(1.0f);
}
}复制代码




我们之前使用的Flutter.createView()显然也是调用了这个构造。但是createView()有一个String类型的initialRoute参数,FlutterActivity中调用的构造则没有。我猜想,会不会提供了更改Route的方式呢?





private boolean loadIntent(Intent intent) {
String action = intent.getAction();
if ("android.intent.action.RUN".equals(action)) {
String route = intent.getStringExtra("route");
//获取Intent中传递的route
String appBundlePath = intent.getDataString();
if (appBundlePath == null) {
appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
}

if (route != null) {
this.flutterView.setInitialRoute(route);
}
//如果route值不为空,则将它设置给flutterview

this.runBundle(appBundlePath);
return true;
} else {
return false;
}
}复制代码


FlutterActivityDelegate中有这个方法,从这个Activity跳转过来的Intent中可以获取route,key值为"route",如果route不为空的话,就给这个FlutterView设置一个initialRoute。出于这样的思路,我在跳转本Activity的时候,传递一个在Flutter中定义好页面的route值进去怎么样?


做了一下尝试,





findViewById(R.id.btn_flutter_acty).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, FlutterExtendActivity.class).putExtra("route","flutter1"));
}
});复制代码


结果是失败了,跳转后页面上出现的FlutterView仍然是传default时返回的页面.




额,由于今天没有什么时间了,所以就写这么多。确实人菜话多,而且今天也没有什么进展(MethodChannel实现通信成功了,不过明天再写吧)今天就卡在了这个FlutterActivity上,不知道明天能找到什么解决办法...请大家见谅。







转载于:https://juejin.im/post/5c7629cce51d453f0d440530



友情链接: