1️⃣Flutter中的UIView相当于什么?
在iOS中,您在UI中创建的大部分内容都是使用视图对象完成的,这些视图对象是UIView类的实例。这些可以充当其他UIView类的容器,它们构成了你的布局。
在Flutter中,与UIView相当的粗糙部分就是一个Widget。小部件并不完全映射到iOS视图,但是当您熟悉Flutter的工作方式时,可以将它们视为“您声明和构建UI的方式”。
但是,这些与UIView有一些不同之处。首先,小部件具有不同的生命周期:它们是不可变的,只有在它们需要改变时才存在。每当小部件或其状态发生变化时,Flutter的框架就会创建一个新的小部件实例树。相比之下,iOS视图在更改时不会被重新创建,而是它是一个可变实体,只能绘制一次,在使用setNeedsDisplay()失效之前不会重绘。
此外,与UIView不同,Flutter的小部件很轻便,部分原因是它们的不变性。因为它们本身并不是视图,也不是直接绘制任何东西,而是描述UI和它的语义,它们在实际视图对象下面“膨胀”。
如果您希望根据进行HTTP调用后收到的数据动态更改UI,请使用StatefulWidget。 在HTTP调用完成之后,告诉Flutter框架小部件的状态已更新,以便它可以更新UI。
2️⃣Text 在flutter中是属于 StatelessWidget
3️⃣我如何动画一个小工具?myapp02
在iOS中,您通过在视图上调用animate(withDuration:animations :)方法来创建动画。在Flutter中,使用动画库将小部件封装在动画小部件中。
4️⃣在Flutter中,使用一个AnimationController,它是一个可以暂停,寻找,停止和反转动画的动画。它需要一个Ticker,用于在vsync发生时发出信号,并在每帧运行时在0和1之间产生线性插值。然后,您创建一个或多个动画并将它们附加到控制器。
例如,您可以使用CurvedAnimation沿插值曲线实现动画。从这个意义上讲,控制器是动画进程的“主”源,CurvedAnimation计算替换控制器默认线性运动的曲线。与小部件一样,Flutter中的动画也用于合成。
在构建小部件树时,将Animation分配给小部件的动画属性(例如FadeTransition的不透明度),并通知控制器启动动画。
5️⃣绘制
在iOS上,您使用CoreGraphics在屏幕上绘制线条和形状。 Flutter拥有基于Canvas类的不同API,还有两个可以帮助您绘制的类:CustomPaint和CustomPainter,后者实现了您的算法以绘制到画布。
Flutter的绘图原理,Flutter框架直接使用Skia引擎来渲染,因此能够控制渲染帧数,从而实现高帧速率。
6️⃣我如何编写异步代码? myapp03
Dart有一个单线程执行模型,支持Isolates(一种在另一个线程上运行Dart代码的方式),一个事件循环和异步编程。 除非您生成隔离,否则您的Dart代码将在主UI线程中运行,并由事件循环驱动。 Flutter的事件循环相当于iOS主循环 - 即连接到主线程的Looper。
Dart的单线程模型并不意味着您需要将所有操作都作为导致UI冻结的阻止操作运行。 相反,使用Dart语言提供的异步工具(例如async / await)来执行异步工作。
由于Flutter是单线程的并且运行事件循环(如Node.js),因此您不必担心线程管理或产生后台线程。 如果您正在执行I / O绑定工作(如磁盘访问或网络调用),那么您可以安全地使用async / await并完成。 另一方面,如果您需要进行计算密集型工作以保持CPU繁忙,则您需要将其移至隔离区以避免阻塞事件循环。
7️⃣但是,有时您可能正在处理大量数据,并且UI挂起。 在Flutter中,使用隔离可利用多个CPU内核来执行长时间运行或计算密集型任务。myapp04
隔离区是独立的执行线程,不会与主执行内存堆共享任何内存。 这意味着你不能从主线程访问变量,或者通过调用setState()来更新你的UI。 隔离对他们的名字是真实的,并且不能共享内存(例如以静态字段的形式)。
以下示例以简单的隔离方式显示如何将数据共享回主线程以更新UI。myapp4
loadData() async {
ReceivePort receivePort = new ReceivePort();
await Isolate.spawn(dataLoader, receivePort.sendPort);
// The 'echo' isolate sends its SendPort as the first message
SendPort sendPort = await receivePort.first;
List msg = await sendReceive(sendPort, "https://jsonplaceholder.typicode.com/posts");
setState(() {
widgets = msg;
});
}
// The entry point for the isolate
static dataLoader(SendPort sendPort) async {
// Open the ReceivePort for incoming messages.
ReceivePort port = new ReceivePort();
// Notify any other isolates what port this isolate listens to.
sendPort.send(port.sendPort);
await for (var msg in port) {
String data = msg[0];
SendPort replyTo = msg[1];
String dataURL = data;
http.Response response = await http.get(dataURL);
// Lots of JSON to parse
replyTo.send(json.decode(response.body));
}
}
Future sendReceive(SendPort port, msg) {
ReceivePort response = new ReceivePort();
port.send([msg, response.sendPort]);
return response.first;
}
这里,dataLoader()是在它自己的独立执行线程中运行的Isolate。 在隔离区中,您可以执行更多CPU密集型处理(例如解析大型JSON),或执行计算密集型数学(如加密或信号处理)。
8️⃣network requests
如何显示长时间运行任务的进度? myapp05
在Flutter中,使用ProgressIndicator小部件。 通过控制何时通过布尔标志呈现,以编程方式显示进度。 告诉Flutter在长时间运行的任务开始前更新其状态,并在结束后隐藏它。
9️⃣项目结构,本地化,依赖性和资产
1 Json文件加载 :
导入pubspec.yaml头文件
然后使用AssetBundle从代码访问它:
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
Future loadAsset() async {
return await rootBundle.loadString('my-assets/data.json');
}
2 对于图像,Flutter遵循一种简单的基于密度的格式,如iOS。 图片资产可能是1.0x,2.0x,3.0x或任何其他乘数。 所谓的devicePixelRatio表示单个逻辑像素中物理像素的比例。
资产位于任意文件夹中 - Flutter没有预定义的文件夹结构。 您在pubspec.yaml文件中声明资产(包含位置),Flutter将其拾取。
例如,要将名为my_icon.png的图像添加到您的Flutter项目中,您可能决定将其存储在任意称为图像的文件夹中。 将基础图像(1.0x)放置在图像文件夹中,并将其他变体放在以相应比率乘数命名的子文件夹中
3 本地化
默认情况下,Flutter仅支持US字符串。 如果您需要添加对其他语言的支持,请包含flutter_localizations包。 您可能还需要添加Dart的intl包以使用i10n机器,例如日期/时间格式。
dependencies:
# ...
flutter_localizations:
sdk: flutter
intl: "^0.15.6"
要使用flutter_localizations包,请在应用部件上指定localizationsDelegates和supportedLocales:
import 'package:flutter_localizations/flutter_localizations.dart';
new MaterialApp(
localizationsDelegates: [
// Add app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('he', 'IL'), // Hebrew
// ... other locales the app supports
],
// ...
)
4 Cocoapods的等价物是什么?我如何添加依赖关系?
在iOS中,您可以通过添加到Podfile来添加依赖项。 Flutter使用Dart的构建系统和Pub包管理器来处理依赖关系。这些工具将原生Android和iOS包装应用程序的构建委托给相应的构建系统。
虽然在您的Flutter项目的iOS文件夹中有一个Podfile,但只有在您添加每个平台集成所需的本地依赖项时才使用它。通常,使用pubspec.yaml在Flutter中声明外部依赖关系。酒吧是寻找Flutter优质包装的好地方。
5 国际化https://flutter.io/tutorials/internationalization
🔟ViewControllers
1 在iOS中,您可以覆盖ViewController的方法以捕获视图本身的生命周期方法,或者在AppDelegate中注册生命周期回调。 在Flutter中,您既没有概念,但是可以通过挂接到WidgetsBinding观察者并监听didChangeAppLifecycleState()更改事件来监听生命周期事件。
🔟1️⃣Layouts
在iOS中,您可能会在UITableView或UICollectionView中显示一个列表。 在Flutter中,你有一个类似的使用ListView的实现。 在iOS中,这些视图具有用于决定行数的委托方法,每个索引路径的单元格以及单元格的大小。
由于Flutter的不可变小部件模式,您将小部件列表传递给您的ListView,并且Flutter负责确保滚动快速而平稳。
1 列表demo myapp06
2 我如何知道哪个列表项被点击?
在iOS中,您可以实现委托方法tableView:didSelectRowAtIndexPath :. 在Flutter中,使用由传入的小部件(the passed-in widgets)提供的触摸处理。
3 动态更新 list列表 myapp07
在iOS中,您更新列表视图的数据,并使用reloadData方法通知表或集合视图。
在Flutter中,如果您要更新setState()内部的小部件列表,您很快就会发现数据不会在视觉上发生变化。 这是因为当调用setState()时,Flutter渲染引擎会查看小部件树以查看是否有任何更改。 当它到达你的ListView时,它执行==检查,并确定两个ListView是相同的。 没有任何改变,所以不需要更新。
为了更新ListView的一个简单方法,在setState()中创建一个新List,并将旧列表中的数据复制到新列表中。 虽然这种方法很简单,但不推荐用于大数据集
推荐的,高效的和有效的方式来建立一个列表使用ListView.Builder。 当您拥有动态列表或包含大量数据的列表时,此方法非常有用。
Scorllview 也可以使用ListView来实现
触摸监听事件
在iOS中,您将GestureRecognizer附加到视图以处理点击事件。 在Flutter中,添加触摸监听器有两种方式:
1如果小部件支持事件检测,则将函数传递给它,并在函数中处理事件。 例如,RaisedButton小部件有一个onPressed参数:
@override
Widget build(BuildContext context) {
return new RaisedButton(
onPressed: () {
print("click");
},
child: new Text("Button"),
);
}
2如果Widget不支持事件检测,则将该Widget封装在GestureDetector中,并将函数传递给onTap参数。
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new GestureDetector(
child: new FlutterLogo(
size: 200.0,
),
onTap: () {
print("tap");
},
),
),
);
}
}
访问本地GPS ,相机 ,三方登录 一般都是使用插件的形式
官网原文链接传送 点我