Flutter开发(八):Flutter线程与异步UI

1.异步代码

2.后台开线程执行代码

3.网络请求

4.长时间的任务添加进度条

1.异步代码

在 Android 中,不开线程,所有代码都走主线程执行;在 Flutter 也是一样,不开线程,Dart 代码永远主线程执行。

我们可以通过 async / await 来实现异步操作,比如网络请求:

  loadData() async {
    String url="https://xx";
    http.Response response = await http.get(url);
    setState(() {
      widgets = json.decode(response.body);
    });
  }

await 网络请求完成,调用 setState() 更新 UI。

下面的例子,请求网络并且展示数据,需要在 pubspec.yaml 添加依赖:

dependencies:
#  加这一行
  http: ^0.12.0+1
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

添加完记得点击 Pub get :

添加下面的代码,注意里面的包引入变化:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List widgets = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    loadData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: widgets.length,
        itemBuilder: (BuildContext context,int position){
          print("itemBuilder方法");
          return getRow(position);
        },
      ),
    );
  }

  getRow(int i) {
    return Padding(
          padding: EdgeInsets.all(10.0),
          child: Text("Row ${widgets[i]["title"]} "),
        );
  }

  loadData() async {
    String url="https://jsonplaceholder.typicode.com/posts";
    http.Response response = await http.get(url);
    setState(() {
      widgets = json.decode(response.body);
    });
  }
}

新版本运行的时候可能有下面的报错:

方法点击这个:Flutter Error: Cannot run with sound null safety, because the following dependencies don‘t support_wuqingsen1的博客-CSDN博客

2.后台开线程执行代码

一般访问磁盘、网络请求或做 I/O 操作,可以用 async / await 来完成。

如果执行长时间复杂任务,可以用 Isplate 避免阻塞 event loop。

在 Flutter 中,async 关键字把方法声明为异步方法,通过 await 关键字等待该异步方法执行完成。

Isolate 是分离的运行线程,并且不和主线程共享内存。也不能访问主线程中的变量和更新 UI 。

下面简单展示, Isolate 把数据返回给主线程更新 UI ,了解就可以,不用完全理解,后面用的多了自然就理解了:

import 'dart:convert';
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List widgets = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    loadData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: widgets.length,
        itemBuilder: (BuildContext context,int position){
          print("itemBuilder方法");
          return getRow(position);
        },
      ),
    );
  }

  getRow(int i) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Text("Row ${widgets[i]["title"]} "),
    );
  }

  loadData() async {
    //ReceivePort接受传入消息
    ReceivePort receivePort = ReceivePort();
    //创建生成与当前Isolate共享代码的Isolate
    await Isolate.spawn(dataLoader, receivePort.sendPort);

    //流的第一个元素
    SendPort sendPort = await receivePort.first;
    //第一个元素回收后监听会关闭,所以要新创建一个ReceivePort接受传入消息
    ReceivePort response = ReceivePort();
    //向第一个ReceivePort发送异步消息
    sendPort.send(["https://jsonplaceholder.typicode.com/posts",response.sendPort]);
    //获取发送来的数据
    List msg = await response.first;

    setState((){
      widgets = msg;
    });
  }

  //
  static dataLoader(SendPort sendPort) async{
    ReceivePort port = ReceivePort();

    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);
      replyTo.send(json.decode(response.body));
    }
  }
}

3.网络请求

实现网络请求,上面已经说明了;

 需要在 pubspec.yaml 添加依赖:

dependencies:
#  加这一行
  http: ^0.12.0+1
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

添加完记得点击 Pub get :

代码中先引入包:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

实现网络请求的方法: 

  loadData() async {
    String url="https://jsonplaceholder.typicode.com/posts";
    http.Response response = await http.get(url);
    setState(() {
      widgets = json.decode(response.body);
    });
  }

4.长时间的任务添加进度条

Flutter 中,对应的 widget 叫 ProgressIndicator。通过布尔 flag 控制展示进度,开始任务更新进度条。结束后隐藏。

import 'dart:convert';
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List widgets = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    loadData();
  }

  showLoadingDialog() {
    return widgets.length == 0;
  }

  getBody() {
    if (showLoadingDialog()) {
      return getProgressDialog();
    } else {
      return getListView();
    }
  }

  getProgressDialog() {
    return Center(child: CircularProgressIndicator());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: getBody());
  }

  ListView getListView() => ListView.builder(
      itemCount: widgets.length,
      itemBuilder: (BuildContext context, int position) {
        print("itemBuilder方法");
        return getRow(position);
      });

  getRow(int i) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Text("Row ${widgets[i]["title"]} "),
    );
  }

  loadData() async {
    String url = "https://jsonplaceholder.typicode.com/posts";
    http.Response response = await http.get(url);
    setState(() {
      widgets = json.decode(response.body);
    });
  }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值