文档章节

在Android和iOS中集成flutter

似水流年0_0
 似水流年0_0
发布于 2018/11/29 18:18
字数 1220
阅读 2805
收藏 49

flutter可能是未来跨平台开发的又一技术框架,那么对于一个app,我们不可能完全用flutter来开发,那么就意味着我们需要在已有的Android和iOS代码中去集成flutter。目前这一技术还处于预览状态,并且还要切换flutter的channel为mater分支。如下,官方原话:

那么我们在集成之前需要查看现在flutter处于什么渠道:

我的是处于master分支,如果你以前没改过的话,应该是beta分支,那么可以执行:

flutter channel master

进行切换。

下面正式开始集成Android和iOS。

Android

首先用Android studio创建一个Android工程,步骤不做介绍了。然后在Android工程的根目录执行一下命令:

flutter create -t module my_flutter

来创建一个flutter的module,成功之后,目录结构如下:

接着我们来修改一下Android功能里的gradle文件:

首先是app的setting.gradle文件,添加如下:

include ':app'
setBinding(new Binding([gradle: this]))                                 
evaluate(new File(                                                      
        settingsDir.parentFile,                                               
        'my_flutter/.android/include_flutter.groovy'                          
))

目的就是去加载指定目录的include_flutter.groovy文件,那么我们查看一下这个文件:

// Generated file. Do not edit.

def scriptFile = getClass().protectionDomain.codeSource.location.path
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile

gradle.include ':flutter'
gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter')

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile()
    gradle.include ":$name"
    gradle.project(":$name").projectDir = pluginDirectory
}

gradle.getGradle().projectsLoaded { g ->
    g.rootProject.afterEvaluate { p ->
        p.subprojects { sp ->
            if (sp.name != 'flutter') {
                sp.evaluationDependsOn(':flutter')
            }
        }
    }
}

其中最重要的一段代码,就是include ':flutter',意思就是flutter这个module要参与编译。

接着在app层级(不是project层)的build.gradle文件中添加依赖:

dependencies {
  implementation project(':flutter')
  :
}

OK配置阶段结束,我们开始先写Android代码,在activity中添加一个button,当我们点击它时,将加载flutter布局,代码如下:

public class MainActivity extends AppCompatActivity {
    private TextView button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
                tx.replace(R.id.container, Flutter.createFragment("route1"));
                tx.commit();

//                View flutterView = Flutter.createView(MainActivity.this,getLifecycle(),"route1");
//                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(100,100);
//                params.leftMargin = 100;
//                params.topMargin = 200;
//                addContentView(flutterView,params);
            }
        });
    }
}

这里有两种实现方式,一种是使用fragment,一种是使用FlutterView。代码中的route1字符串则是flutter代码中定义的,接下来就开始写flutter代码:

import 'dart:ui';
import 'package:flutter/material.dart';

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return SomeWidget();
    case 'route2':
      return SomeWidget();
    default:
      return Center(
        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
      );
  }
}


class SomeWidget extends StatelessWidget{
  @override
    Widget build(BuildContext context) {
      // TODO: implement build
      return Container(
        
        width: 100,
        height: 100,
        color: Color(0xFF00FF00),
        child: Center(
          child: Text("hello",textDirection: TextDirection.ltr,),
        ),
      );
    }
}

这里可以看到对rout1的定义。

写到这里代码部分就完成了,然后运行android项目,就可以看到效果了。

ios

首先也是执行:

flutter create -t module my_flutter

生成一个flutter工程,由于在Android集成中已经做了这一步,故跳过。然后用Xcode创建一个iOS工程,创建完成之后,目录如下:

下面为工程添加flutter的依赖,这里要使用cocoapods,若以前没有安装过,则执行命令:

sudo gem install cocoapods

然后在iOS工程的根目录创建Podfile文件,命令为:

touch Podfile 

然后修改podfile文件,如下:

target 'ios4Flutter' do
platform:ios,'8.0'
 
flutter_application_path = '../my_flutter/'
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
end

其中ios4Flutter为我的iOS工程名,flutter_application_path为flutter工程的根目录。

最后执行:

pod install

完成项目的依赖,效果如下:

之后点击.xcworkSpace文件打开iOS工程,找到Build Phases目录,新建一个Script Phase,粘贴下面的命令:

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed

到text area,如下图:

配置完成之后,⌘B来build工程。如果没有报错,那么部署成功。下面开始写代码:

在AppDelegate.h中:

#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate
@end

AppDelegate.m:

#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins

#include "AppDelegate.h"

@implementation AppDelegate

// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

ViewController.m:

#import <Flutter/Flutter.h>
#import "ViewController.h"

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self
               action:@selector(handleButtonAction)
     forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Press me" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor blueColor]];
    button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
    [self.view addSubview:button];
}

- (void)handleButtonAction {
    FlutterViewController* flutterViewController = [[FlutterViewController alloc] init];
    [flutterViewController setInitialRoute:@"route1"];
    [self presentViewController:flutterViewController animated:false completion:nil];
}
@end

OK,oc代码编写完成,运行app,呈现效果。

Hot restart/reload and debugging Dart code

我们可以运用dart语言的特性实现 hot reload,首先在flutter的根目录执行:

flutter attach

如下:

当运行完app,点击按钮进入flutter的view时,终端状态如下:

当我们再次修改dart代码,保存之后,在命令中输入r即可hot reload。

 

© 著作权归作者所有

共有 人打赏支持
似水流年0_0
粉丝 58
博文 83
码字总数 55847
作品 0
长宁
技术主管
私信 提问
加载中

评论(3)

弱鸡瘦纸
弱鸡瘦纸
看起来不难 一试一堆子配置错误 坑很深
gavinking
gavinking
前瞻性
OSC_官方超管
OSC_官方超管
学习了,看起来流程很简单的样子,有空试试
Google的Flutter工具允许开发者开发跨平台应用

与大多数应用程序开发人员交谈,他们会告诉你,与iOS相比,制作Android应用程序要困难得多,也更复杂,也不那么有趣。实际上,如果你要求报价,这两种软件都将单独定价,因为它们都需要单独的...

问题终结者
01/08
0
0
谷歌Flutter跨平台应用开发SDK迎来首个发行预览版本

谷歌Flutter跨平台应用开发SDK迎来首个发行预览版本 2018-06-22 12:26编辑: 枣泥布丁分类:程序人生来源:程序师 跨平台Google Flutter预览版本 招聘信息: 图像处理及模式识别工程师 C/C+...

枣泥布丁
2018/06/22
0
0
Flutter新锐专家之路:工程研发体系篇

作者:闲鱼技术-正物 写在前面 当前,闲鱼客户端已经实现了基于Flutter的商品详情页的全量重构,线上效果良好。从alpha一路走来,我们遇到了很多问题,或基于原理,或透过社区,或与官方合作...

闲鱼技术
2018/08/06
0
0
深入理解Flutter的编译原理与优化

导读:对于开发者而言,Flutter 工程和我们的 Android/iOS 工程有何差别?Flutter 的渲染和事件传递机制如何工作?构建缓慢或出错又如何去定位,修改和生效呢?凡此种种,都需要对 Flutter ...

程序师
2018/07/07
0
0
深入理解flutter的编译原理与优化

闲鱼技术-正物 问题背景 对于开发者而言,什么是Flutter?它是用什么语言编写的,包含哪几部分,是如何被编译,运行到设备上的呢?Flutter如何做到Debug模式Hot Reload快速生效变更,Release...

闲鱼技术
2018/06/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java12的新特性

Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13的新特性 序 本文主要讲述一下Java12的新特...

go4it
10分钟前
1
0
深入解密比Guava Cache更优秀的缓存-Caffeine

1.前言 读这篇文章之前希望你能好好的阅读: 你应该知道的缓存进化史 和 如何优雅的设计和使用缓存? 。这两篇文章主要从一些实战上面去介绍如何去使用缓存。在这两篇文章中我都比较推荐Caffe...

咖啡拿铁的技术分享
12分钟前
1
0
Java B2B2C多用户商城 springcloud架构 --Eureka服务器搭建及配置

第一步,创建一个普通的springboot项目 以下方法都可以快速创建一个boot项目: 1. 浏览器访问http://start.spring.io/,填写信息,下载zip包,加压到你的ide的工作空间直接使用。 2. 使用ide...

明理萝
24分钟前
0
1
为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作

· Oracle 撒手,宣布对个人用户 (Personal Users) , Java 8 官方支持时间持续到 2020 年 12 月;对商业用户(Commercial Users),2019 年 1 月之后不再提供免费更新。 · 红帽喊话,计划在...

Java填坑路
26分钟前
0
0
在 Ali Kubernetes 系统中,我们这样实践混沌工程

在传统的软件测试中,我们通常通过一个给定的条件来判断系统的反馈,通过断言来判断是否符合预期,测试条件和结果通常比较明确和固定。而混沌工程,是通过注入一些“不确定”因素,象放进了一...

阿里云官方博客
28分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部