【第三章 flutter学习之Dart基础(下)】

一、Mixins

因为mixins使用的条件,随着Dart版本一直在变,这里是Dart2.x中使用mixins的条件:

1、作为mixins的类只能继承自Object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性

例如:C类mixinsA和B类 mixins关键字是with

class A {
  String info="this is A";
  void printA(){
    print("A");
  }
}
class B {
  void printB(){
    print("B");
  }
}
class C with A,B{
}
void main(){
  var c=new C();  
  c.printA();
  c.printB();
  print(c.info);
}

例2:c类继承Person类并mixinsA和B类

class Person{
  String name;
  num age;
  Person(this.name,this.age);
  printInfo(){
    print('${this.name}----${this.age}');
  }
  void run(){
    print("Person Run");
  }
}
class A {
  String info="this is A";
  void printA(){
    print("A");
  }
  void run(){
    print("A Run");
  }
}
class B {  
  void printB(){
    print("B");
  }
  void run(){
    print("B Run");
  }
}
class C extends Person with B,A{
  C(String name, num age) : super(name, age);
}
void main(){  
  var c=new C('张三',20);  
  c.printInfo();
  // c.printB();
  // print(c.info);
  c.run();
}

例3:mixins的实例类型:

mixins的类型就是其超类的子类型。
class A {
  String info="this is A";
  void printA(){
    print("A");
  }
}
class B {
  void printB(){
    print("B");
  }
}
class C with A,B{
}
void main(){  
  var c=new C();  
  print(c is C);    //true
  print(c is A);    //true
  print(c is B);   //true


  // var a=new A();
  // print(a is Object);


}

二、泛型

泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)

	泛型定义
	 getData<T>(T value){
   	   return value;
	  }
  
	void main() {
    指定类型
     // print(getData(21));
    // print(getData('xxx'));
    // getData<String>('你好');
    print(getData<int>(12));
   
 	}

泛型类
class MyList<T> {
  List list = <T>[];
  void add(T value) {
    this.list.add(value);
  }

  List getList() {
    return list;
  }
}

	main() {
	实例化定义好类型
  List list2 = new List<int>.filled(2, 0);
  list2[0] = 12;
  list2[1] = 13;
  print(list2);
 }
泛型接口
定义好一个泛型类 
abstract class Cache<T> {
  getByKey(String key);
  void setByKey(String key, T value);
}
MemoryCache类拿到Cache方法
class MemoryCache<T> implements Cache<T> {
  @override
  getByKey(String key) {
    return null;
  }
  @override
  void setByKey(String key, T value) {
    print("我是内存缓存 把key=${key}  value=${value} -写入到了内存中");
  }
}
void main() {
  // MemoryCache m=new MemoryCache<String>();
  //  m.setByKey('index', '首页数据');

  MemoryCache m = new MemoryCache<Map>();  约束类型
 
  m.setByKey('index', {"name": "张三", "age": 20});
}

三、 自定义库、第三方库、系统库

Dart中的库主要有三种:

    1、我们自定义的库     
          import 'lib/xxx.dart';
    2、系统内置库       
          import 'dart:math';    
          import 'dart:io'; 
          import 'dart:convert';
    3、Pub包管理系统中的库  
        https://pub.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/

        1、需要在自己项目根目录新建一个pubspec.yaml
        2、在pubspec.yaml文件 然后配置名称 、描述、依赖等信息
        3、然后运行 pub get 获取包下载到本地  
        4、项目中引入库 import 'package:http/http.dart' as http; 看文档使用

引入自己的库

class Animal{
  String _name;   //私有属性
  int age; 
  //默认构造函数的简写
  Animal(this._name,this.age);

  void printInfo(){   
    print("${this._name}----${this.age}");
  }

  String getName(){ 
    return this._name;
  } 
  void _run(){
    print('这是一个私有方法');
  }

  execRun(){
    this._run();  //类里面方法的相互调用
  }
}
新建文件定义好数据之后
=====================================
引入调用即可
import 'lib/Animal.dart';
main(){
  var a=new Animal('小黑狗', 20);
  print(a.getName());
}

系统库

// import 'dart:io';
import "dart:math";
main(){
 
    print(min(12,23));

    print(max(12,25));   
}
=================
系统库实现请求数据
import 'dart:io';
import 'dart:convert';
void main() async{
  var result = await getDataFromZhihuAPI();
  print(result);
}
//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
  //1、创建HttpClient对象
  var httpClient = new HttpClient();  
  //2、创建Uri对象
  var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
  //3、发起请求,等待请求
  var request = await httpClient.getUrl(uri);
  //4、关闭请求,等待响应
  var response = await request.close();
  //5、解码响应的内容
  return await response.transform(utf8.decoder).join();
}

导入Pub包管理系统中的库

/*
pub包管理系统:
1、从下面网址找到要用的库
        https://pub.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/
        
2、创建一个pubspec.yaml文件,内容如下
    name: xxx
    description: A new flutter module project.
    dependencies:  
        http: ^0.12.0+2
        date_format: ^1.0.6

3、配置dependencies

4、进入cmd运行pub get 获取远程库

5、看文档引入库使用
*/
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import 'package:date_format/date_format.dart';

main() async {
  // var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";

  //   // Await the http get response, then decode the json-formatted responce.
  //   var response = await http.get(url);
  //   if (response.statusCode == 200) {
  //     var jsonResponse = convert.jsonDecode(response.body);
     
  //     print(jsonResponse);
  //   } else {
  //     print("Request failed with status: ${response.statusCode}.");
  //   }


  
    print(formatDate(DateTime(1989, 2, 21), [yyyy, '*', mm, '*', dd]));

}
冲突解决
当引入两个库中有相同名称标识符的时候,如果是java通常我们通过写上完整的包名路径来指定使用的具体标识符,
甚至不用import都可以,但是Dart里面是必须import的。
当冲突的时候,可以使用as关键字来指定库的前缀。如下例子所示:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.


import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;

main(List<String> args) {
  Person p1=new Person('张三', 20);
  p1.printInfo();


  lib.Person p2=new lib.Person('李四', 20);
  p2.printInfo();

}

部分导入

如果只需要导入库的一部分,有两种模式:
模式一:只导入需要的部分,使用show关键字,如下例子所示:
import 'package:lib1/lib1.dart' show foo;
模式二:隐藏不需要的部分,使用hide关键字,如下例子所示:
 import 'package:lib2/lib2.dart' hide foo;      


// import 'lib/myMath.dart' show getAge;

 import 'lib/myMath.dart' hide getName;

void main(){
//  getName();
  getAge();
}

延迟加载

    也称为懒加载,可以在需要的时候再进行加载。
    懒加载的最大好处是可以减少APP的启动时间。

    懒加载使用deferred as关键字来指定,如下例子所示:

    import 'package:deferred/hello.dart' deferred as hello;

    当需要使用的时候,需要使用loadLibrary()方法来加载:

    greet() async {
      await hello.loadLibrary();
      hello.printGreeting();
    }

四、async和await


/*
async和await
  这两个关键字的使用只需要记住两点:
    只有async方法才能使用await关键字调用方法
    如果调用别的async方法必须使用await关键字


async是让方法变成异步。
await是等待异步方法执行完成。


*/

void main() async{
  var result = await testAsync();
  print(result);

}

//异步方法
testAsync() async{
  return 'Hello async';
}


五、空安全、late、required

1. 空安全

 null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,
 并且额外的好处是可以改善性能。
? 可空类型

例1
String? getData(apiUrl){
  if(apiUrl!=null){
    return "this is server data";
  }
  return null;
}

  // String? str="this is str";

  // str=null;

  // print(str!.length);  


! 类型断言

例2 
void printLength(String? str){ //可空类型
  try {
    print(str!.length);  str不是空则打印长度
  } catch (e) {
     print("str is null"); 
  }
}

2. late 关键字

主要用于延迟初始化。
class Person {
  late String name;
  late int age;
  void setName(String name, int age) {
    this.name = name;
    this.age = age;
  }
  String getName() {
    return "${this.name}---${this.age}";
  }
}

void main(args) {
  Person p = new Person();
  p.setName("张三", 20);
  print(p.getName());
}
不初始化会报错

3. required关键字

主要用于允许根据需要标记任何命名参数(函数或类),
使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。

例
String printUserInfo(String username, {int age=10, String sex="男"}) {//行参    
  return "姓名:$username---性别:$sex--年龄:$age";
}

String printInfo(String username, {required int age, required String sex}) {//行参    
  return "姓名:$username---性别:$sex--年龄:$age";
}

void main(args) {
    print(printUserInfo('张三'));
    print(printUserInfo('张三',age: 20,sex: "女")); 这两个没有标注可传可不传
    //age 和 sex必须传入
    print(printInfo('张三',age: 22,sex: "女"));  //这个必须传
}

4、identical 函数


var o1 = new Object();
var o2 = new Object();

 print(identical(o1,o2));  //false  不共享存储空间
 print(identical(o1,o1));   //true 共享存储空间
 const 声明的值相同的话 会共享一个空间

/*
常量构造函数总结如下几点:

  1、常量构造函数需以const关键字修饰
  2、const构造函数必须用于成员变量都是final的类
  3、如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
  4、实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。
  5、Flutter中const 修饰不仅仅是节省组件构建时的内存开销,Flutter 在需要重新构建组件的时候,由于这个组件是不应该改变的,重新构建没有任何意义,因此 Flutter 不会重建构建 const 组件  
*/

//常量构造函数
class Container{
  final int width;
  final int height;
  const Container({required this.width,required this.height});
}

void main(){

  var c1=Container(width: 100,height: 100);
  var c2=Container(width: 100,height: 100);
  print(identical(c1, c2)); //false

  
  var c3=const Container(width: 100,height: 100);
  var c4=const Container(width: 100,height: 100);
  print(identical(c3, c4)); //true


  var c5=const Container(width: 100,height: 110);
  var c6=const Container(width: 120,height: 100);
  print(identical(c5, c6)); //false
  
}
// 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。





完结撒花✿✿ヽ(°▽°)ノ✿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰太狼大王灬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值