19、Flutter - Key & 局部渲染

Key & 局部渲染

 

详细代码参见Demo

Demo地址 -> flutter_testdemo6

 

一、补充:

17、Flutter - Flutter生命周期 & Widget 的生命周期 & Inherited数据传递

生命周期

生命周期就是处理数据
没有监听生命周期的方法就是没有生命周期方法

有状态的Stateful

didChangeDependencies  改变依赖关系
在 init之后会调用一次
然后就是在数据共享  Inherit  的时候才会调用
数据共享就是为了解决有很多层级,需要共享数据的时候,不需要在一层一层的传递,共享数据,都能访问。

状态管理有哪些
数据共享就是状态管理  
状态管理也叫数据管理

element

并不是widget 都是独立渲染(这里说的是独立渲染,Widget是否被渲染是根据Element树来决定的)
特殊的widget 每个
Widget 树在变化的时候,element 树并不一定在变化
Render 的才是真正渲染的树

为什么选用 element 作为 context ?
因为 element 里面持有 widget  和  Render 所以有了Element就同时拥有了Widget 和 Render。Render 里面没有element,再有就是context 的字面意思就是上下文,所以需要拿到更全的数据用来处理。


二、Key

先看一下几个源码

StatelessWidget

abstract class StatelessWidget extends Widget {
  /// Initializes [key] for subclasses.
  const StatelessWidget({ Key key }) : super(key: key);

AppBar

class AppBar extends StatefulWidget implements PreferredSizeWidget {
  AppBar({
    Key key,

Scaffold

class Scaffold extends StatefulWidget {
  const Scaffold({
    Key key,

Text

class Text extends StatelessWidget {
  const Text(
    this.data, {
    Key key,

里面都有一个可选参数  key

 

现在来写个demo验证一下这个key的用途

import 'package:flutter/material.dart';

import 'key_demo2.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: Scaffold(
          body: KeyDemo(),
        ));
  }
}

key_demo.dart

import 'dart:math';

import 'package:flutter/material.dart';

class KeyDemo extends StatefulWidget {
  @override
  _KeyDemoState createState() => _KeyDemoState();
}

class _KeyDemoState extends State<KeyDemo> {
  List<Widget> items = [
//    StlItem1('aaa'),
//    StlItem1('bbb'),
//    StlItem1('ccc'),
//    -------------------------------
//    StfulItem2('aaa'),
//    StfulItem2('bbb'),
//    StfulItem2('ccc'),
    //    -------------key------------------
    StfulItem2('aaa', key: ValueKey('111')),
    StfulItem2('bbb', key: ValueKey('222')),
    StfulItem2('ccc', key: ValueKey('333')),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('KeyDemo'),
      ),
      body: Row(mainAxisAlignment: MainAxisAlignment.center, children: items),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            items.removeAt(0);
          });
        },
      ),
    );
  }
}
//做一个正方形;
// ------------------ StatelessWidget  没问题 ----------------------------
class StlItem1 extends StatelessWidget {
  final title;
  StlItem1(this.title);
//  随机颜色 Random().nextInt(256) 随机正整数 0-255
  final _color = Color.fromRGBO(
      Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1.0);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: _color,
      child: Text(title),
    );
  }
}

如上代码使用StatelessWidget 点击删除item 正常 

// ---------------------- StatefulWidget ----------------------------
class StfulItem2 extends StatefulWidget {
  final title;
//  StfulItem2(this.title);
  StfulItem2(this.title, {Key key}) : super(key: key);

  @override
  _StfulItem2State createState() => _StfulItem2State();
}

class _StfulItem2State extends State<StfulItem2> {
  //  随机颜色 Random().nextInt(256) 随机正整数 0-255
//  如果颜色也写到Widget中就不会出现,删除的时候颜色和文字不对的问题
  final _color = Color.fromRGBO(
      Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1.0);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: _color,
      child: Text(widget.title),
    );
  }
}

 使用StatefulWidget 在Widget里面写_color 看页面效果也是正常的。

但是把_color 写到State里面就出问题了。效果如下

然后加上key

StfulItem2(this.title, {Key key}) : super(key: key);
StfulItem2('aaa', key: ValueKey('111')),
StfulItem2('bbb', key: ValueKey('222')),
StfulItem2('ccc', key: ValueKey('333')),

加上key之后就正常了
在Widget里面是正常的,在State里面就不正常了。猜测应该是颜色错乱了。

看一下源码为什么 StatefulWidget

abstract class StatefulWidget extends Widget {

进入到Widget

abstract class Widget extends DiagnosticableTree {

这里面有个方法

static bool canUpdate(Widget oldWidget, Widget newWidget) {
  return oldWidget.runtimeType == newWidget.runtimeType
      && oldWidget.key == newWidget.key;
}

runtimeType 真实类型

有删除排序等一定要加入key


Flutter使用的时候自己的引擎,将其引擎加入到项目中。这样做有几个好处就是
1、性能更快
2、在iOS和安卓中用都都是自己的不存在过大的差异
3、iOS和安卓在更新的时候对其他影响不大

 

2.2、key分析

Key 本身是一个抽象类
1、LocalKey  

用作diff算法的核心所在!用作Element 和 Widget 进行比较
    Valuekey 

    数字 或 字符等任意类型。以一个数据作为key


    ObjectKey
        上面的代码中的Valuekey 可以换成ObjectKey,包装一个对象 例如: ObjectKey(Text(‘123’))


    UniqueKey 可以保证key的唯一性。返回的是一个Hash,一个随机值,保证唯一。用法:UniqueKey();
        一旦使用,就不存在Element的复用了,一旦刷新所有的Widget都会重新渲染。这个用的不多一般用来强制更新

LocalKey 也是一个抽象类
查看Valuekey 源码

class ValueKey<T> extends LocalKey {
  /// Creates a key that delegates its [operator==] to the given value.
  const ValueKey(this.value);


2、Globakey

可以获取到对应的widget 的state 对象

key_demo2.dart

import 'package:flutter/material.dart';

class GlobalKeyDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GlobalKeyDemo'),
      ),
      body: ChildPage(),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
        },
      ),
    );
  }
}

class ChildPage extends StatefulWidget {
  @override
  _ChildPageState createState() => _ChildPageState();
}

class _ChildPageState extends State<ChildPage> {
  int count = 0;
  String data = 'hello';
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[Text(count.toString()), Text(data)],
      ),
    );
  }
}

 StatelessWidget  添加button,点击去修改StatefulWidget 的话,按我们原来的学习应该是添加button改变的地方必须使用StatefulWidget,被调用刷新的使用StatelessWidget。

但是尽量在末端使用Stateful,也就是树的“叶子”处。因为Stateful变化的时候后面的左右都会被重新渲染

方法一:可以在StatefulWidget 里面加个回调,在StatelessWidget去调用的时候将值传进去

方法二:
GlobalKey 可以获取到对应的Widget 的 State对象

import 'package:flutter/material.dart';

class GlobalKeyDemo extends StatelessWidget {
  final GlobalKey<_ChildPageState> _globalKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GlobalKeyDemo'),
      ),
      body: ChildPage(
        key: _globalKey,
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          _globalKey.currentState.count++;
          _globalKey.currentState.data =
              'old' + _globalKey.currentState.count.toString();
//          局部渲染和跟新
          _globalKey.currentState.setState(() {});
        },
      ),
    );
  }
}

class ChildPage extends StatefulWidget {
  ChildPage({Key key}) : super(key: key);

  @override
  _ChildPageState createState() => _ChildPageState();
}

class _ChildPageState extends State<ChildPage> {
  int count = 0;
  String data = 'hello';
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[Text(count.toString()), Text(data)],
      ),
    );
  }
}

这样就解决了。

最后总结一下:

1、LocalKey 用来获取Widget

2、全局Key

全局Key 用来获取对应的State、Widget、Element

获取的目的是减少渲染复制引擎。比较常见的用来做局部渲染

 

### 回答1: Flutter是Google开源的一款跨平台的UI开发框架,可以快速地构建高质量的移动、Web和桌面应用程序。而Embedded Linux是指Linux操作系统在嵌入式设备中的应用。通过将Flutter与Embedded Linux结合起来,可以让开发者在嵌入式设备上创建漂亮且功能强大的应用程序。 Flutter的跨平台特性使得开发者可以使用相同的代码库在多个平台上运行应用程序,包括嵌入式设备。嵌入式设备通常资源有限,但Flutter的轻量级和高性能使得它非常适合在此类设备上运行。Flutter的热重载功能可以让开发者快速迭代和测试应用程序,提高开发效率。 使用Flutter-Embedded Linux,开发者可以利用Flutter的丰富的UI组件和强大的渲染引擎来创建嵌入式设备上的用户界面。Flutter提供了丰富的UI控件和动画效果,可以实现各种视觉效果和交互体验。Flutter还具备良好的跨平台兼容性和高度定制性,可以适应不同嵌入式设备的各种需求。 除此之外,Flutter-Embedded Linux还提供了与Linux操作系统的良好集成,可以调用底层系统资源和API,如文件系统、网络接口等。这使得开发者可以通过Flutter在嵌入式设备上实现更强大的功能,例如与传感器的交互、与云服务的连接等。 总而言之,Flutter-Embedded Linux是一个强大的开发工具,可以帮助开发者在嵌入式设备中创建高质量的应用程序。它结合了Flutter的跨平台特性和Embedded Linux的优势,为开发者提供了更灵活、高效的开发环境。无论是工业控制、智能家居还是其他嵌入式应用,Flutter-Embedded Linux都能提供良好的开发体验和用户体验。 ### 回答2: Flutter-embedded-linux是指在嵌入式Linux平台上使用Flutter框架进行应用开发的一种技术方案。嵌入式Linux是指在资源有限的嵌入式设备上运行Linux操作系统的系统;而Flutter是一种跨平台的移动应用开发框架,可以同时在Android和iOS上运行。 使用Flutter-embedded-linux可以让开发者在嵌入式Linux平台上开发出跨平台的应用。这样一来,开发者不再需要针对不同的平台编写不同的代码,大大提高了开发效率。同时,Flutter的高性能和优秀的用户体验也被保留在嵌入式设备上。 在使用Flutter-embedded-linux时,开发者需要在嵌入式Linux平台上搭建Flutter的开发环境,包括安装Flutter SDK、配置相关的依赖库等。然后,可以使用Flutter提供的开发工具和API进行应用的开发和调试。 Flutter-embedded-linux可以应用于很多领域,例如智能家居、智能工业设备、嵌入式系统等。开发者可以利用Flutter-embedded-linux开发各种类型的应用,如物联网设备控制应用、工业监控系统、嵌入式音视频播放器等。 需要注意的是,由于嵌入式Linux平台的资源限制,开发者在使用Flutter-embedded-linux时需要特别关注应用的性能和资源消耗情况,避免出现过多的资源占用或性能瓶颈。 总之,Flutter-embedded-linux为开发者在嵌入式Linux平台上开发跨平台应用提供了一种方便、高效、高性能的技术方案,有望在嵌入式设备领域得到广泛应用。 ### 回答3: Flutter-Embedded-Linux是一种使用Flutter框架进行嵌入式开发的技术方案。Flutter是一种跨平台的开源UI框架,可以快速构建高性能、精美的应用程序。而Embedded-Linux则是嵌入式设备常用的操作系统。 通过将Flutter应用程序集成到Linux嵌入式系统中,可以在嵌入式设备上实现高效、流畅和美观的用户界面。Flutter的特点是能够在不同平台上保持一致的用户体验,因此在嵌入式系统上也能够实现类似于移动设备和桌面系统上的应用程序。 使用Flutter-Embedded-Linux进行嵌入式开发有一些优势。首先,Flutter具有快速构建UI界面的能力,可以节省开发时间。其次,Flutter对于动画和渲染效果的支持非常好,可以在嵌入式设备上实现更加流畅和绚丽的动画效果。此外,Flutter还支持热重载功能,可以实时更新应用程序而无需重新启动,极大地提高了开发效率。 然而,使用Flutter-Embedded-Linux也存在一些挑战。嵌入式设备通常资源有限,对占用内存和CPU的要求较高,需要对Flutter应用程序进行优化以提高性能。另外,由于Flutter是基于Dart语言开发的,需要事先熟悉Dart开发语言和Flutter框架的使用。 总之,Flutter-Embedded-Linux是一种用于嵌入式开发的技术方案,可以帮助开发者快速构建高品质的应用程序界面。它在嵌入式设备上的应用可以提供与移动设备和桌面系统相媲美的用户体验。但是,开发者需要注意对资源的合理利用和性能的优化,以确保应用程序在嵌入式设备上能够运行流畅。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值