除去地图、WebView、相机等涉及底层方案的特殊情况外,大部分原生代码能够实现的 UI 效果,完全可以用 Flutter 实现.
使用这种方式对性能造成非常大的影响且不方便维护.
方法通道: 原生逻辑复用
平台视图: 原生视图复用
❝ 官网地址: https://flutter.dev/docs/development/add-to-app
❞
FlutterEngine 文档: https://github.com/flutter/flutter/wiki/Experimental:-Reuse-FlutterEngine-across-screens
FlutterView 文档: https://github.com/flutter/flutter/wiki/Experimental:-Add-Flutter-View
API一会儿就过时了,得去官网看最新的才行.
可以在Android App中开启Flutter的Activity,Flutter的Activity是在另外一个进程,第一次进入特别慢.也可以加入Flutter的View和Fragment
在Android工程下新建一个Flutter的module比较简单直接
Android跳转Flutter,依赖FlutterView.Flutter在FlutterView中建立了自己的导航栈.
通常会将Flutter容器封装成一个独立的Activity或者ViewController. 这样打开一个普通的Activity既是打开Flutter界面了
Flutter页面跳转原生界面,需要利用方法通道,然后用原生去打开响应的界面.
Flutter实例化成本非常高,每启动一个Flutter实例,就会创建一套新的渲染机制,即Flutter Engine,以及底层的Isolate.而这些实例之间的内存是不相互共享的,会带来较大的系统资源消耗.
实际开发中,尽量用Flutter去开发闭环的业务模块.原生跳转过去就行,剩下的全部由Flutter内部完成. 尽量避免Flutter页面回到原生页面,原生页面又启动新的Flutter实例的情况.
Dart的一个库,可以实现在StatelessWidget中刷新数据.跨组件传递数据.全局共享数据.依赖注入
使用Provider后,我们就再也不需要StalefullWidget了.
Provider以InheritedWidget语法糖的方法,通过数据资源封装,数据注入,和数据读写这3个步骤,为我们实现了跨组件(跨页面)之间的数据共享
我们既可以用Provider来实现静态的数据读传递,也可以使用ChangeNotifierProvider来实现动态的数据读写传递,还用通过MultiProvider来实现多个数据资源的共享
Provider.of和Consumer都可以实现数据的读取,并且Consumer还可以控制UI刷新的粒度,避免与数据无关的组件的无谓刷新
封装数据
//定义需要共享的数据模型,通过混入ChangeNotifier管理听众
class CounterModel with ChangeNotifier {
int _count = 0;
//读方法
int get counter => _count;
//写方法
void increment() {
_count++;
notifyListeners();//通知听众刷新
}
}
尽量把数据放到更高的层级
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//通过Provider组件封装数据资源
//因Provider是InheritedWidget的语法糖,所以它是一个Widget
//ChangeNotifierProvider只能搞一个
//MultiProvider可以搞多个
return MultiProvider(
providers: [
//注入字体大小 下个界面读出来
Provider.value(value: 30.0),
//注入计数器实例
ChangeNotifierProvider.value(value: CounterModel())
],
child: MaterialApp(
home: FirstPage(),
),
);
}
}
//示例: 读数据
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
//取出资源 类型是CounterModel
//获取计时器实例
final _counter = Provider.of<CounterModel>(context);
//获取字体大小
final textSize = Provider.of<double>(context);
/*
*
//使用Consumer2获取两个数据资源
Consumer2<CounterModel,double>(
//builder函数以参数的形式提供了数据资源
builder: (context, CounterModel counter, double textSize, _) => Text(
'Value: ${counter.counter}',
style: TextStyle(fontSize: textSize))
)
* 我们最多可以使用到 Consumer6,即共享 6 个数据资源。
* */
return Scaffold(
body: Center(
child: Text(
'Counter: ${_counter.counter}',
style: TextStyle(fontSize: textSize),
),
),
floatingActionButton: FloatingActionButton(
child: Text('Go'),
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => SecondPage())),
),
);
}
}
//示例: 读和写数据
//使用Consumer 可以精准刷新发生变化的Widget
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
//取出数据
//final _counter = Provider.of<CounterModel>(context);
return Scaffold(
//使用Consumer来封装counter的读取
body: Consumer(
//builder函数可以直接获取到counter参数
//Consumer 中的 builder 实际上就是真正刷新 UI 的函数,它接收 3 个参数,即 context、model 和 child
builder: (context, CounterModel counter, _) => Center(
child: Text('Value: ${counter.counter}'),
),
),
floatingActionButton: Consumer<CounterModel>(
builder: (context, CounterModel counter, child) => FloatingActionButton(
onPressed: counter.increment,
child: child,
),
child: Icon(Icons.add),
),
);
}
}
MediaQuery.of(context).size.width
获得屏幕宽度来加载什么布局Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8