移动端框架 4|学习笔记

简介: 快速学习移动端框架 4

开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:移动端框架 4】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/76/detail/15787


移动端框架 4


内容介绍:

一、Shopping List

二、Navigation

三、Networking

四、References

 

一、Shopping List

shopping list是一个stateful,持有这个在购物车里的一个集合,

image.png

当某一次在shopping list上面点击动作时,会调用传进去的_handleCardChanged方法,方法会改变shoppingCard set的内容,在里面add或remove,从程序来看,flutter认为shopping list里面shoppingCard状态不断发生变化,有还是没有,你每次状态的发生变化时,要对整个products里面的每一个product进行重绘,如果状态发生变化,会去重绘一下,将里面的shoppingListItem重绘一遍,一种方案的shopping list认为是否在购物车,这是一个状态,还有一种是shoppinglistItem都是有状态的,状态是inCard,不断的发生变化。

这个是products放在这里,有一个shoppingCard,状态不断发生变化,每一次只要发生变化,products里面的内容就重绘一遍,这是一种套路,这种情况不用去管这个shoppinglistitem的inCard状态要不要发生翻转,实际上是每一次购物车里放的东西,重绘一些shoppinglistItem,对products内容重绘一遍,shoppinglistItem实际不是一开始创建出来有三个products,有三个productsItem,不断的说inCard在翻转,逻辑是有一个shoppinglist,里面有三个products,查看三个products是否在shoppingCard中,如果shoppingcart集合发生变化,重绘所有的products,相当于新绘三个,如果绘制三个inCard状态没有变化,可以复用,有变化就会重绘,是两个这样逻辑,一种是shoppinglistitem里面有一个inCard,认为第一种方案是stateful,ontype时改变一下inCard值,把inCard值取反改变它的值,还有一种是shoppinglistitem本身是无状态的,shoppingList是有状态的,有一个集合在购物车中,集合状态一旦发生变化,会重绘三个item,item一旦被绘制出来,要么新的替代,要么就一直不变,是stateless,状态是不会发生变化,这两种设计方案都可以

if (!inCart)

_shoppingCart.add(product);

else

_shoppingCart.remove(product);

});

}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('shopping List'),

),

body: ListView(

padding: Edgelnsets.symmetric(vertical: 8.0),

children: widget.products .map((Product product) {

return ShoppingListltem(

product: product

inCart: shoppingCart.contains(product),

onCartChanged:__handlecartChanged,

);

}).toList(),

),

);

上面代码是第二种,为什么不能在按下切换inCard值,取反,设置成stateful运行,shoppingitem有多少个商品就有多少个,shoppingList只有一个,有三个stateful不如只有一个stateful,stateful的东西一定要跟踪它的状态,去做setstate操作,从设计的角度说,肯stateful越少越好,当然这两种方案应该都可以实现,只是第二章stateful只有一个,stateful多一个createState,state应该是一个list这样一个处理

 

二、Navigation

image.png

有关屏幕之间来回的切换,即导航动作是如何实现的,在这里面只做导航,按下按钮以后切换到其他页面上,没有什么状态要维护,尽管widget有好几个,全部都是StatelessWidget,在heroAPP的widget种,在build返回MaterialApp,封装好的一种APP,出来之后先看到MainScreen页面,底下定义一个MainScreen,有个脚手架,是list界面的东西.

image.png

上面是AppBar,显示内容是Main Screen

Body是页面内容,希望点击内容之后能跳转到另外一个页面屏幕上,是一个GestureDetector,查看用户上面有没有做这个动作,里面是一个hero,hero是flutter里面预定义好的,在dart中存在,显示一张从网络上抓取的图片,说明页面是从网络上抓取的

image.png

就是这张图片,在图片上按一下,用navigator导航,navigator是定义好的类,在上面直接点一个push,把当前的这个上下文作为参数放入,产生页面的路由,创建Detailscreen返回这个路由,调到Detailscreen上

图片是Detailscreen,有一个Scaffold,Scaffold上面没有AppBar,上面没有蓝颜色这部分,整个是一个body,是一个GestureDetector,居中是一个hero,hero里面是一张图片,图片没有做别的动作,在上面可以继续点击,上边是push,下边是pop,相当于手机页面stuck中的占有和弹出,弹出pop回到之前状态MainScreen,

image.png

两个页面之间再来回的切换,是navigation,看起来的效果像动画一样,在不同屏幕之间来回切换

·Navigate to a new screen and back

class FirstRoute extends StatelessWVidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('First Route'),

),

body: Center(

child: RaisedButton(

child: Text('Open route'),

onPressed: () {

Navigator.push(

context,

MaterialPageRoute(builder: (context) =>SecondRoute()),

);

class SecondRoute extends StatelessWidget {

@override

Widget build(BuildContext context){

return Scaffold(

appBar: AppBar(

title: Text(""Second Route"),

),

body: Center(

child: RaisedButton(

onPressed: () {

Navigator.pop(context);

},

child: Text('Go back!'),

),

),

有关navigation的操作,定义一个firstRoute,这是一个SecondRoute,二者都是StatelessWidget,中间没有状态维护,有一个按钮叫做open route,点击会跳转,跳到SecondRoute上,现在用的方法跟刚才有点差异,要把context传递进去,传给second,这边是RaisedButton,用onPressed,上面是hero,用onTap。把它弹出来,底下有一个文本go back,如图

image.png

点击open route,跳转到第二个页面,点击go back,回到第一个页面,与刚才是类似的,一个是GestureDetector,一个是RaisedButton,不是在整个区域响应按的动作,只在个按钮上响应按的动作两个例子都在说明如何做页面之间的跳转,如何导航到这一边,然后返回

import 'package:flutter/material.dart';

void main() {

runApp(MaterialApp(

title: 'Navigation Basics',

home: FirstRoute(),

));

}

一开始展示firstRoute,刚才看到的在两个页面之间来回弹,如果定义路由时,是在指定页面的类,跳到这个类的一个对象上,实际上语法是创建了一个secondRoute类型的对象,这个对象是没有名字的,没有把它赋给某个变量跳到这个变量,实际上就创建了一个不具名的对象,假设SecondRoute这个Widget创建好几个页面和好几个对象,比如有ABCD四个对象,想让它跳到A对象,下一个可能还有一个Button跳到B对象,是同一个类但是它里面也许有一些参数显示的内容不一样,不同的对象尽管都是SecondRoute这个类的对象

·Navigate with named routes

class FirstScreen extends StatelessWidget {

@override widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('First Screen'),

),

body: Center(

child: RaisedButton(

child: Text('Launch screen'),

onPressed: () {

// Navigate to the second screen using a named route

Navigator.pushNamed(context, ' /second');

},

跳到一个带名字的route上,有一个变化,navigation那里不是push,是pushNamed,跳转过去像一个路径,路径可以确定如何跳转,second screen没做什么变化

import 'package:flutter/material.dart';

void main() {

runApp(MaterialApp(

title: 'Named Routes Demo',

// Start the app with the "/" named route.In this case, the app starts

// on the FirstScreen widget.

initialRoute: /' ,

routes: {

// When navigating to the "/" route, build the FirstScreen widget.

'/': (context) => FirstScreen(),

// When navigating to the "/second" route, build the SecondScreen widget.

'/second': (context) => SecondScreen(),

},

Main函数里面是runApp,MaterialApp,有一个

initialRoute: /' ,

routes: {

定义,跟home谁不一样,initialRoute跳到哪里去,假设都是具名,就会写route的信息,跟这个对应创建一个first screen的对象,Second创建一个second screen对象,'/third': (context) => SecondScreen()也是创建一个second screen,third与second是两个不同的second screen对象,二者是不同的路由,等于现在有两个不同的页面,都是second screen对象,但位置不一样,有两个不同的实例,可以跳到不同的地方去,要用一个具名的路由,它的含义比如书,书的详情可能页面是同一个,只不过里面的一些参数不一样,比如图片、书名和作者不一样,跳到不同的实例上,实际是同一个类的多个对象,要用到具名的路由

·Pass arguments to a named route

class MyApp extends Statelesswidget {

从一个页面跳到另外一个页面想带参数进去,是可以的,定义MyAPP,里面有一个onGenerateRoute,里面setting,在创建具名的路由时,有一些相关的信息可以放到setting中,通setting可以拿到,底下有passArgumentScreen。

PassArgumentsScreen是一个StatelessWidget,路由对应的是passArguments,相当于像UI一样的路由,跳到当前这个页面屏幕上,就是PassArgumentsScreen对应passArguments名字的意思,对passArguments访问要跳到PassArgumentsScreen页面上,这里PassArgumentsScreen是有参数要传进来,title和message,构造器通过required两个inotation表示,必须创建当前的对象,必须传title和message,否则无法创建,build是一个脚手架,是上面的AppBar,里面展示的蓝颜色的内容就是传递进来的title,底下是body,body里面展示的内容是传递进来的message,这就是PassArgumentsScreen,后面还有一个screenarguments,

// You can pass any object to the arguments parameter. In this example,

//create a class that contains both a customizable title and message.

class ScreenArguments {

final string title;

final String message;

ScreenArguments(this.title, this.message);

}

通过screenarguments传递title和message给PassArgumentsScreen,screenarguments相当于一个简单的类,没有扩展,将title和message两个参数封装起来变成一个类,创建screenarguments必须给title和message,传给widget

class MyApp extends Statelesswidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

// Provide a function to handle named routes.Use this function to

//identify the named route being pushed , and create the correctl

//Screen.

onGenerateRoute: (settings) {

//If you push the PassArguments route

if(settings.name==PassArgumentsScreen.routeName){

//cast the arguments to the correct type: ScreenArguments.

final ScreenArguments args = settings.arguments;

在MyAPP里面有一个onGenerateRoute,这个函数是处理带名字的路由,传递进来的settings如果带名字,并且和PassArgumentScreen.routeName就是passArgument相同,意味希望跳到PassArgumentScreen里面去,把settings里面的argument拿出来,创建一个ScreenArguments,就是把settings里面的title和message拿出来创建了一个ScreenArguments

返回一个页面的路由,return MaterialPageRoute,这个路由就要返回刚才看到的,如果确实要跳到PassArgumentScreen,就创建一个PassArgumentScreen,title和message就分别就来自于ScreenArguments里面的title和message,即来自settings里面的argumenta

·Pass arguments to a named route

// The code only supports PassArgumentsScreen.routeName right now.

// Other values need to be implemented if we add them.The assertion

//here will help remind us of that higher up in the call stack, since

//this assertion would otherwise fire somewhere in the framework.

assert(false, 'Need to implement ${settings.name});

return null;

},

title: 'Navigation with Arguments',

home: ylomeScreen(),

routes: {

ExtractArgumentsScreen.routeName: (context)=>

ExtractArgumentsScreen(),

整个home是homeScreen,routes是ExtractArgumentsScreen获取ArgumentsScreen路由的名字,名字对应到ExtractArgumentsScreen页面上,先看HomeScreen

class HomeScreen extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('Home Screen'),

),

body: Center(

child: Column(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

//A button that navigates to a named route that.The named route

//extracts the arguments by itself.

RaisedButton(

child: Text("Navigate to screen that extracts arguments"),

HomeScreen是个脚手架,下面显示home screen, body是居中,对齐,有个按钮,按钮上显示的是

Navigate to screen that extracts arguments

onPressed: () {

//when the user taps the button, navigate to a named route

//and provide the arguments as an optional parameter.

Navigator.pushNamed(

context,

ExtractArgumentsScreen.routeName,

arguments: ScreenArguments(

'Extract Arguments Screen' ,

'This message is extracted in the build method.',

),

按下之后会压进去一个路由,路由要跳到抽取参数的屏幕上,ExtractArgumentsScreen.routeName,传递一个参数,参数是利用ScreeArguments组起来的,Extract Arguments Screen是title,This message is extracted in the build method.是message。

有第二个按钮RaisedBatton,名字为Navigate to a named that accepts arguments,按下之后也需要跳,要跳到PassArgumentScreen页面上,同样传递参数ScreenArgument,HomeScreen如图

image.png

图上面的home screen来自于AppBar,底下整个是一个center居中,按列来算上下排列,有两个按钮,RaisedButton,两个按钮按下后动作不一样,上面按钮按完之后,路由到ExtractArgumentScreen里面去,底下按钮要路由完之后跳到PassArgumentScreen里面去,ExtractArgumentScreen也有个routeName,对应跳到extractArguments中,build不像PassArgumentScreen从构造器里面拿title和message,刚才过来的路由要拿context,context里面拿settings,然后拿arguments,settings和arguments对应

Arguments:ScreenArguments

当路由过来时,Arguments就传过来了,settings是在navigation中传递的信息,在settings取Arguments,通过ModalRoute取settings中的Arguments,

return Scaffold(

appBar: AppBar(

title: Text(args.title),

),

body: Center(

child: Text(args.message),

),

@override

Widget build(BuildContext context) {

return Scaffold(

appBar:AppBar(

title: Text(title),

),

body: Center(

child: Text(message),

}

内容是一样的,都是一个APPBar,显示title,底下的body是message,ExtractArgumentScreen和PassArgumentScreen唯一差异是如何拿到title和message,前面是说从settings里面拿arguments,拿出来之后得到了传递过来的参数,直接显示参数的内容,后面是通过ongenerateRoute函数传递过来的信息,传递给构造器的信息,拿到title和message,赋给自己,ongenerateRoute当产生点击的动作,产生的路由要跳转时,像这种这种信息

PassArgumentsScreen.routeName,

arguments: ScreenArguments(

'Accept Arguments Screen',

'This message is extracted in the onGenerateRoute function.',

封装在settings里面,再创建PassArgumentsScreen,把settings里面拿出来的Argument取出来设给title和message,把参数传给具名路由有两种方式,一种是ExtractArgumentScreen的方式,从上下文的settings里面直接去拿Arguments信息,另一种是定义构造器,在OnGenerateRoute创建参数,从ettings里面直接去拿Arguments信息,通过构造器传递进去,无论是哪一种,从当前页面,无论点击哪一个按钮,走的两种形式无论怎么走,都能跳转到第二个页面,

image.png

第二个页面能够拿到那个页面传递管理信息,无论ExtractArgumentScreen从settings里面拿,

image.png

还是PassArguments,从构造器,从OnGenerateRoute函数里面去拿,前面是从方法直接抽取,后面是从OnGenerateRoute里面拿,这两种方式都实现了一次从MyApp主页home screen里面,两个按钮,home screen里面都传递参数给下一屏,下面的这一屏无论哪种方法,都得到了前面传递过来的参数,从a页面的跳转到b页面之后,或者从a屏幕跳上d屏幕,data是如何传递的,这是一个方向,另外一个方向是b处理完的数据是如何传回给a,把数据怎么返回给a

·Return data from a screen

import 'package:flutter/material.dart';

void main(){

runApp(MaterialApp(

title: 'Returning Data' ,

home: HomeScreen(),

));

}

class HomeScreen extends StatelessWidget {

@override

Widget buid(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(' Returning Data Demo'),),

body: Center(child: SelectionButton(),

);

}

}

@override

Widget build(BuildContext context) {

return RaisedButton(

onPressed:(){

_navigateAndDisplaySelection(context);

},

child: Text('Pick an option, any option!'),

);

}

//A method that launches the SelectionScreen and awaits the result

// from Navigator.pop.

_navigateAndDisplaySelection(BuildContext context) async {

//Navigator.push returns a Future that completes after calling

// Navigator.pop on the Selection Screen.

final result = await Navigator.push(

context,

MaterialPageRoute(builder: (context) => SelectionScreen()),

);

//After the Selection Screen returns a result, hide any previous

// snackbars and show the new result.

Scaffold.of(context)

..removeCurrentSnackBar()

..showSnackBar(SnackBar(content: Text("$result")));

}

}

一个HomeScreen,整个Main里面创建了一个HomeScreen,就是主页,HomeScreen前面是脚手架,底下有body,body有一个SelectionButton,SelectionButton也是一个StatelessWidget,有一个RaisedButton对它的一个封装,当按下之后,调_navigateAndDisplaySelection(context)方法,button显示选择一个选项,任意一个选项

image.png

出来的效果是第一张图Pick an option,any option,当按下_navigateAndDisplaySelection(context)的时候,与底下_navigateAndDisplaySelection(BuildContext context) async {

对应,按下之后要跳转,跳转到SelectionScreen上去

class SelectionScreen extends StatelessWidget {

SelectionSecreen也是一个脚手架,上面是pick an option,底下是按列呈现,呈现前面有按钮,一个按钮是Yep,另外一个是Nope,这就是第二个页面

image.png

两个按钮按下之后,都有一动作,把当前页面pop出去,回到图中第一个页面上,但是回的时候反了一个结果,带第二参数,跟之前的pop不一样,之前的pop只有一个参数,就现有第二个参数,同时带一个值返回,_navigateAndDisplaySelection要把之前selectionScreen压进去,压进去之后在上面会有点击的动作,等待,等可以做其他事情,等到有结果返回,把当前的这个SnackBar移除掉,显示一个新的SnackBar,显示新的SnackBar的新创建一个SnackBar,内容是等的结果,SnackBar在第三张图底下

image.png

返回的result就是显示的内容,如果点Yep!,把当前这一页pop出来,看似回到了第一页,但回来时,因为在这里面按下回调的函数里面,把返回结果拿到后你以SnackBar形式返回的底下去,所以在第三张图看到把数据带回来

前面例子再说数据从a页面带到b页面,刚才是把数据带回到a页面,相当于拿到下一页选的结果,实现了一次数据从下一个跳回到刚才的页面,第一二张图两双方通信图一过去称为参数,图二返回称为结果,双方可以通信,多个页面之间交互时,可以拿到互相之间传递的参数,页面不仅仅是像一些静态页面的跳转,可以把数据进行双向的流动,可以进行操作,即在导航的过程当中,同时拿到双方通信的数据,页面很多显示的内容根据传递的参数和显示的结果决定显示什么,页面才能是动态地

image.png

 

有一个待办事项的列表,有很多to do list,随意点击一个就能进到详情页,详情页展示to do list这一项的详细说明

定义Todo这样一个类

image.png

就是图片中的Todo,表示后面存储的数据,它数据有两个,一个是title,一个是description,比如图中Tod就是title,图二中的一句话就是description,不是界面的内容,只是一个数据封装,是一个普通类,有构造器要传递进来title和description,主页是TodosScreen,TodosScreen里面给一个列表,即TodosScreen要求得到todos参数,todo就是列表,要把列表数据丢给我,列表数据用list.generate生成的一个列表,列表有20个元素,对于每一个元素是i作为参数,都创建一个新的Todo,Todo的title是Todo加上i值,就有了Todo0-Todo19,description是A description of what needs to be done for Todo $i这句话,都差不多,只是后面$i不一样,Main创建了这样一个TodoScreen,把这个20个Todo对象作为这个参数传递给TodoScreen,拿到之后如何build,是一个脚手架,上面是AppBar,是我图一上面蓝色中的Todo部分,Body是list view,列表里面呈现一堆的ListTile,就是图中每一条,ListTile中先用文本显示Todo,每一个Todo的title,就是图中看到每一行,在每一个Todo上面一点击跳转到DetailScreen的页面,跳过去的同时把当前在哪一个界面点的,就把当前这个Todo的元素传过去,作为Todo参数

class DetailScreen extends StatelessWidget {

// Declare a ftreld that holds the Todo.

final Todo todo;

// ln the constructor, require a Todo.

DetailScreen({Key key,@required this.todo}) : super(key: key);

@override

Widget build(BuildContext context) {

// Use the Todo to create the Ul.

return Scaffold(

appBar: AppBar(

title: Text(todo.title),

),

body: Padding(

padding: Edgelnsets.all(16.0),

child: Text(todo.description),

DetailScreen传了一个Todo,把数据发到新的屏上,传到@required this.todo中,开始绘制,脚手架上面显示的todo的title,那在todo4上点就显示todo4,底下显示todo的description,TodoScreen如何把一个具体的一个todo的待办信息传递给DetailScreen,就是把数据发到一个新的屏上,拿到以后做处理。即通过不具名的路由如何把参数传过去,告诉大家通过导航的方式在不同的屏幕之间传递信息,这就是一个具体的例子

看到react、vue、react native、flutter、wechat所有的前端中路由都是一个很重要的东西,如何把这个页面之间来回实现跳转,而在路由里面最重要的是,在页面跳转时怎样把相关的信息带过去,每一个框架都在讲如何实现路由,因为单个页面肯定实现不了所有功能,一定要靠多个页面组合起来完成所有的内容,之间如何路由以及在路由过程当中怎么带数据,包括来回传递数据,都很重要,这就是flutter里面发送数据到新屏幕或者从新的屏幕带出去回来的一个过程

 

三、Networking

·Fetch data from the internet

- To install the http package, add it to the dependencies section of the pubspec.yaml file.

dpendencies:

http: <latest_version>

- Make a network request

Future<http.Response> fetchAlbum() {

return http.get('https://jsonplaceholder.typicode.com/albums/1');}

实现前后台的交互,刚才讲的东西都在前台,后台也是用Fetch这样的方法、这样的API来实现,在flutter事件中,所有的依赖关系是在pubspec.yaml文件里,上一节课讲一个生成一对单词对时用English words库,那个这样加的,当用fetch方式通过网络抓取数据时,用到http包往里面加东西,发请求用http中get或post方法,可以把它封装到一个方法中,返回值是一个future类型,future中封装了http.Response,内容实际上在http.Response,拿future封装了一下,uture封装是一个yep调用,等待get的返回值,这就是一个最简单的通过网络来发送请求的一个方法

·Create an Album class

class Album {

final int userld;

final int id;

final String title;

Album({this.userld, this.id, this.title});

factory Album.fromJson(Map<String, dynamic> json) {

return Album(

userld: json['userld'],

id: json['id'],

title: json['title'],

);

创建一个Album类,封装userld、id、title这样的信息,构造器也有这三个东西,给一个json把它转成Album的一个对象的方法,取传递过来的json对象,json是一个map,就是键值对,取里面的这三个分别赋给它,定义了这样一个Album类,后面要去使用

·Convert the http.Response to an Album

Future<Album> fetchAlbum() async {

final response = await http.get('https://jsonplaceholder.typicode.com/albums/1');

if (response.statusCode == 200) {

// lf the server did return a 200 OK response,

// then parse the JSON.

return Album.fromJson(json.decode(response.body));

}else {

// lf the server did not return a 200 OK response,

// then throw an exception.

throw Exception('Failed to load album');

}

}

定义了一个http.get方法,要到一个远端去拿album的json对象回来,它在一个response中,要判断一下状态码是否为200,200表示ok,只有ok情况下才调album类中的FromJson方法,把传递过来的response里面的内容解析成一个json对象,再从json对象解析成一个Alabama对象,会返回一个包装album的future对象,future是异步的,必须是有返回值future,里面封装album,从远端拿回的json对象用刚才的方法转成album,如果不是200,就报错,这是一个封装,可以从远端拿回一个album,就是一个json对象并且转成了data的album对象

·Fetch the data

- Call the fetch( method in either the initState() or

didChangeDependencies( methods.

class_MyAppState extends State<MyApp>{

Future<Album> futureAlbum;

@override

void initState(){

super.initState();

futureAlbum = fetchAlbum();

}

底下是如何处理对象,比如刚才的Album对象可以封装成state,未来会有一个stateful的widget,持有state,state里面有将来返回的future<Album>对象,在状态初始化时,到远端调fetchAlbum方法,将Album对象赋给futureAlbum对象,希望一开始拿进来赋值

把数据展示出来,text展示里面的内容,里面有数据就展示里面的内容,没有数据就展示error,看到的页面如下图

image.png

图中内容是从远端拿的,这是get

还可以post,刚才从远端拿了数据回来,现在能否把数据发到远端,https://jsonplaceholder.typicode.com/albums这个网站可以让发东西,post发过去,发过去是让用户填的信息,比如填title,把title用jsonEncode一下,作为post方法体发送,发到https://jsonplaceholder.typicode.com/albums这个位置上,会有一个响应,同样放到future里面,未来返回的结果回封装在future对象中,title可能在页面上你画一个书框来了,response拿到之后同样要判断一下,post希望在远端那边创建一个对象,新对象进去,如果返回201,表示创建成功,创业成功=只要把创建好的=对象在response里面,它会返回Album的内容,同样组装成Album对象返回,如果不是201,表示创建失败,

title从哪里来?提供了一个页面column,里面有一个按钮,按钮称为Create Data,按下回调createAlbum,把_controller.text内容作为参数发过去,title就是从这来,按钮的上方有一个文本域,文本域让用户填东西,控制器是controller,里面填的内容是_controller.text,效果如图

image.png

·Display the response on screen

FutureBuilder<Album>(

future: _futureAlbum,

builder: (context, snapshot) {

if (snapshot.hasData) {

return Text(snapshot.data.title);}

else if (snapshot.hasError) {

return Text("${snapshot.error}");

}

return CircularProgressIndicator();

填一个Tom&Jerry,点击会把里面内容拿到,发送到远端插入进去,如果插入进去成功,返回Tom&Jerry结果,看到了一次和远端的服务之间的一次交互,就把数据发走,既能从网络上抓取数据,又能把数据发送给网络,在服务器另外一端,flutter和个bookstore后台就可以这样交互

 

四、References

·Google Flutter

- http://www.flutter.dev

·Flutter Gallery

- https://flutter.github.io/gallery/#/

·Flutter Samples

- https://flutter.github.io/samples/#

·Android Studio: License for package Android SDK Build-Tools 28.0.2 not accepted.

- https://blog.csdn.net/didah/article/details/87894670

·A tour of the Dart language

-https://dart.dev/guides/language/language-tour#class-variables-and-methods

·Dart Language Specification v2.2

-https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf.

·DartPad

- https://dartpad.dev/

·Language samples

- https://dart.dev/sample

·spub.dev

- https://pub.dev/

关于flash的东西非常多,也比较新,而且是Google的东西容易被抢注,如果开发有问题,可能要切换一下源的问题,前提是要用flutter,如果觉得flutter很陌生,还需要有data知识才行,不选用它也可以,目标是一定要开发一个移动端的APP,用什么工具都可以,只是用flutter或者react native,无论用哪一个,应该都是只写一套在不同的手机或者是其他移动设备上都能运行

因为时间的原因,没有运行所有的应用,运行应用其实很简单

image.png

上面把导入的文件全注释了,运行时每次打开一次,底下对应的要打开哪一个,都标注了,运行哪一个时应该打开哪一行或者哪一段,比如ex2,把下面这些都打开,运行1、13、14时都用这一行,可以自行查看,在不同的系统运行效果是一样的,react native或者flutter都可以,我随便选一个都可以,也许flutter未来有很多it大厂,用的比较多,未来对实习或者工作可能更重要,好处更多一点好。

相关文章
|
7月前
|
SQL 安全 算法
移动端安全基础
移动端安全基础
|
小程序 JavaScript 算法
开源轻量级 IM 框架 MobileIMSDK 的微信小程序端已发布!
MobileIMSDK - 微信小程序端是一套基于微信原生 WebSocket 的即时通讯库:
252 0
|
3月前
|
移动开发 应用服务中间件 API
即时通讯框架MobileIMSDK的H5端开发快速入门
即时通讯框架MobileIMSDK的H5端开发快速入门
56 6
即时通讯框架MobileIMSDK的H5端开发快速入门
|
移动开发 前端开发 小程序
移动端常用的四个框架
移动端常用的四个框架
147 0
|
移动开发 前端开发 小程序
移动端最常用的四个框架
移动端最常用的四个框架
133 0
|
存储 移动开发 小程序
开源即时通讯IM框架MobileIMSDK的微信小程序端开发快速入门
开源即时通讯IM框架MobileIMSDK的微信小程序端开发快速入门
335 1
开源即时通讯IM框架MobileIMSDK的微信小程序端开发快速入门
|
Web App开发 小程序 JavaScript
开源即时通讯IM框架MobileIMSDK的Uniapp端开发快速入门
开源即时通讯IM框架MobileIMSDK的Uniapp端开发快速入门
283 0
开源即时通讯IM框架MobileIMSDK的Uniapp端开发快速入门
|
移动开发 编解码 前端开发
移动端H5网页开发必备知识
H5网页开发必备知识
153 0
|
移动开发 小程序 前端开发
前端概念之移动端/小程序
随着智能手机的普及,移动端已经成为了人们最重要的使用场景之一。在这个场景下,前端开发也面临着各种挑战,如不同设备的屏幕尺寸、不同平台的兼容性等。为了解决这些问题,多端/跨端/融合的移动端/小程序的概念应运而生。 多端/跨端/融合 在移动端开发中,我们常常需要考虑到不同平台的适配问题,如iOS、Android等。而多端/跨端/融合的思路就是将这些平台的问题合并在一起,以便更好地解决它们。具体来说,多端/跨端/融合的移动端/小程序是指能够在多个平台上运行的应用程序,如H5、小程序、快应用等。
217 0
|
小程序 JavaScript 算法
开源即时通讯IM框架MobileIMSDK的微信小程序端技术概览
MobileIMSDK - 微信小程序端是一套基于微信原生 WebSocket 的即时通讯库:
202 0