Flutter三棵树系列之详解各种Key

简介

key是widget、element和semanticsNode的唯一标识,同一个parent下的所有element的key不能重复,但是在特定条件下可以在不同parent下使用相同的key,比如page1和page2都可以使用ValueKey(1)

常用key的UML关系图如上,整体上key分为两大类-LocalKey和GlobalKey,这两个key都是抽象类,LocalKey的实现类有 ValueKey、ObjectKey和UniqueKey,GlobalKey实现类有LabeledGlobalKey和GlobalObjectKey。

Key

@immutable
abstract class Key {
  const factory Key(String value) = ValueKey<String>;


  @protected
  const Key.empty();
}

Key是所有key的基类,内部实现了一个工厂构造函数,默认创建String类型的ValueKey。内部还是先了一个empty的构造函数,主要是给子类用的。

LocalKey

abstract class LocalKey extends Key {
  const LocalKey() : super.empty();
}

LocalKey没有实际作用,主要是用来区分GlobalKey的,其具体的实现类有ValueKey、ObjectKey、UniqueKey。

ValueKey

class ValueKey<T> extends LocalKey {
  const ValueKey(this.value);


  final T value;


  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is ValueKey<T>
        && other.value == value;
  }


  @override
  int get hashCode => hashValues(runtimeType, value);

内部维护了泛型类型的value属性,并实现了==和hashCode方法。只要两个ValueKey的value属性相等,那么就认为两个Key相等。

ObjectKey

class ObjectKey extends LocalKey {
  const ObjectKey(this.value);


  final Object? value;


  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is ObjectKey
        && identical(other.value, value);
  }


  @override
  int get hashCode => hashValues(runtimeType, identityHashCode(value));

ObjectKey是继承自LocalKey的,可以将其理解成泛型类型为Object的ValueKey。但是注意两者的方法是不一样的,ValueKey根据value的值是否相等来判断ValueKey是否相等(相当于java的equals方法),而ObjectKey根据indentical方法(判断两个引用是否指向同一个对象,相当于java的操作符)来判断两个ObjectKey是否相等的。

UniqueKey

class UniqueKey extends LocalKey {
  UniqueKey();


  @override
  String toString() => '[#${shortHash(this)}]';
}

唯一的key,其并未重写==和hashCode方法,所有它只和自己相等。注意看UniqueKey的构造函数,并没有像上面介绍的几个key的构造函数一样使用const修饰,这样做的目的是为了进一步保证UniqueKey的唯一性。这样在调用Element的updateChild方法时,此方法内部调用的Widget.canUpdate方法就会始终返回false,从而每次都会创建新的child element。

所以,如果你想让某一个widget每一次都不复用old element,而是去重新创建新的element,那么就给他添加UniqueKey吧。

const是编译时常量,在编译期,其值就已经确定。背后利用的类似于常量池的概念,被const修饰的对象会保存在常量池中,后面会对其进行复用。如果UniqueKey构造函数添加了const关键词,那么有如下代码 var k1 = const UniqueKey(); var k2 = const UniqueKey(); 此时k1==k2永远为true,就不能保证其唯一性。

GlobalKey

GlobalKey是全局唯一的,其默认实现是LabeledGlobalKey,所以每次创建的都是新的GlobalKey。所有的GlobalKey都保存在BuildOwner类中的一个map里,此map的key为GlobalKey,此map的value则为GlobalKey关联的element。

对于GlobalKey,需要知道如下几点:

  • 当拥有GlobalKey的widget从tree的一个位置上移动到另一个位置时,需要reparent它的子树。为了reparent它的子树,必须在一个动画帧里完成从旧位置移动到新位置的操作。
  • 上面说到的reparent操作是昂贵的,因为要调用所有相关联的State和所有子节点的deactive方法,并且所有依赖InheritedWidget的widget去重建。
  • 不要在build方法里创建GlobalKey,性能肯定不好,而且也容易出现意想不到的异常,比如子树里的GestureDetector可能会由于每次build时重新创建GlobalKey而无法继续追踪手势事件。
  • GlobalKey提供了访问其关联的Element和State的方法。

下面看下其源码:

abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
  ///这里的debugLabel仅仅为了debug时使用
  factory GlobalKey({ String? debugLabel }) => LabeledGlobalKey<T>(debugLabel);


  ///给子类使用的
  const GlobalKey.constructor() : super.empty();


  Element? get _currentElement => WidgetsBinding.instance!.buildOwner!._globalKeyRegistry[this];


  BuildContext? get currentContext => _currentElement;


  Widget? get currentWidget => _currentElement?.widget;


  T? get currentState {
    final Element? element = _currentElement;
    if (element is StatefulElement) {
      final StatefulElement statefulElement = element;
      final State state = statefulElement.state;
      if (state is T)
        return state;
    }
    return null;
 

其和Key类差不多,也有一个工厂构造函数,默认创建的是LabeledGlobalKey,其构造函数的debugLabel仅仅是为了debug时使用,并不会用来标识element。

如何获取其关联的element?从源码来看,其直接访问的是BuildOwner里用来保存GlobalKey和Element对应关系的map。获取到了其关联的element,那么就能获取到其对应的widget以及state,详细的可以看上面的源码。

需要注意的是其并没有重写==和hashCode方法,构造函数也没有被const修饰,这也就使LabeledGlobalKey天然就是全局唯一的。

LabeledGlobalKey

这是GlobalKey的默认实现,内部仅有一个debugLabel属性,其他的也没啥。

class LabeledGlobalKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
  // ignore: prefer_const_constructors_in_immutables , never use const for this class
  LabeledGlobalKey(this._debugLabel) : super.constructor();


  final String? _debugLabel;
}

GlobalObjectKey

class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
  const GlobalObjectKey(this.value) : super.constructor();


  final Object value;


  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is GlobalObjectKey<T>
        && identical(other.value, value);
  }


  @override
  int get hashCode => identityHashCode(value);

特殊的GlobalKey,重写了==和hashCode方法,内部维护了一个Object对象,通过判断此Object是否指向同一块内存地址来判断两个GlobalObjectKey是否相等。

GlobalKey被要求全局唯一,其默认实现LabeledGloalKey因为其并没有重写==和hashCode方法,也不支持const构造函数,所以天然是全局唯一的。但是GlobalObjectKey不然,如果有两个或者多个地方使用到了拥有同一个Object的GlobalObjectKey,那么就不能保证其全局唯一性,造成程序出错。此时,可以继承GlobalObjectKey,实现一个private的内部类,比如:

class _MyGlobalObjectKey extends GlobalObjectKey {
  const _MyGlobalObjectKey(Object value) : super(value);
}

总结

  • Flutter里的key分为两类,一类是LocalKey,实现类有ValueKey、ObjectKey、UniqueKey;一类是GlobalKey,实现类有LabeledGlobalKey、GlobalObjectKey。
  • Key是所有keys类的基类,其默认实现是String类型的ValueKey。
  • 相同parent下的key是不能一样的,比如不能再同一个page里使用VlaueKey(1),但是不同parent下是可以存在一样的key的,比如在两个界面里都使用ValueKey(1)。
  • UniqueKey只和自己相等,其并没有重写==和hashCode方法,也没有const修饰的构造函数。当调用Element的updateChild方法时,Widget.canUpdate肯定返回false,所以如果你想让widget每次都去创建新的element而不复用old element,那么就给此widget使用UniqueKey。
  • GlobalKey的默认实现是LabeledGlobalKey,其没有实现==和hashCode方法,也没有const修饰的构造函数,所以肯定能保证其全局唯一性。
  • 所有的GlobalKey都保存在BuildOwner类中,其内部维护了一个map用来保存GlobalKey与其对应的Element。
  • GlobalObjectKey是特殊的GlobalKey,内部维护了一个Object属性,并实现了==和hashCode方法,通过判断runtimeType以及Object属性是否一致来判断两个GlobalObjectKey是否相等。
  • 使用GlobalObjectKey时,为了保证GlobalObjectKey的全局唯一性,最佳实践是继承自GlobalObjectKey实现一个private的内部类,可以有效避免多人开发时可能造成的GlobalObjectKey冲突的问题。

作者:京东物流 沈明亮

内容来源:京东云开发者社区

本文转载于网络 如有侵权请联系删除

相关文章

  • 大数据开发工程师需要具备哪些技能?[通俗易懂]

    大家好,又见面了,我是你们的朋友全栈君。目录:1.典型需求2.40K以上专家必备技能3.项目中的迷宫场景部件制作4.Hadoop生态核心原理一、典型需求(互联网公司)二、40K以上专家必备技能三、大数从业者角色分类四、Hadoop生态核心原理1.大数据整体画像数据流程 数据技术 2.大数据平台整体画像大数据平台逻辑划分 数据相关的工具、产品和技术:比如批量数据采集传输的Sqoop、离线数据处理的Hadoop和Hive、实时流处理的Storm和Spark以及数据分析的R语言等。数据资产:不仅包含公司业务本身产生和沉淀的数据,还包括公司运作产生的数据(如财务、行政),以及从外界购买交换或者爬虫等而来的数据等。数据管理:有了数据工具,也有了数据资产,但是还必须对它们进行管理才能让数据产生最大价值并最小化风险,因此数据平台通常还包括数据管理的相关概念和技术,如数据仓库、数据建模、数据质量、数据规范、数据安全和元数据管理等。如果你对大数据开发感兴趣,想系统学习大数据的话,可以加入大数据技术学习交流扣扣君羊:522189307从数据处理的时效性划分 (1)离线数据平台。(2)实时数据平台。和离线数

  • 备份数据到同一实例下的其他数据库操作

    会用到锁,其实也还好,没必要用到就尽量不要用。#!/bin/sh mysql-uroot-p8rKSwodBFkcteU8h2>/dev/null-e"flushtableswithreadlock;" mysql-uroot-p8rKSwodBFkcteU8h2>/dev/null-e"createdatabasebolo_bak;" tbname=$(mysql-uroot-p8rKSwodBFkcteU8h2>/dev/null-e"SELECTtable_namefrominformation_schema.tableswhereTABLE_SCHEMA='bolo'") foriin$tbname;do mysql-uroot-p8rKSwodBFkcteU8hbolo_bak2>/dev/null-e"createtable$ilikebolo.$i" mysql-uroot-p8rKSwodBFkcteU8hhellodb_bak2>/d

  • 《手把手教你》系列技巧篇(十八)-java+ selenium自动化测试-元素定位大法之By css中卷(详细教程)

    1.简介按计划今天宏哥继续讲解倚天剑-css的定位元素的方法:ID属性值定位、其他属性值定位和使用属性值的一部分定位(这个类似xpath的模糊定位)。2.常用定位方法(8种)(1)id (2)name (3)classname (4)tagname (5)linktext (6)partiallinktext (7)xpath (8)cssselector(今天讲解)3.自动测试实战以百度首页为例,将CSS的各种定位方法一一讲解和分享一下。3.1大致步骤1.访问度娘首页。2.通过CSS定位到元素,点击一下。3.2使用ID属性值定位元素使用ID属性值定位元素,以‘标签’开头,先指定一个HTML标签,然后加上一个“#”符号,跟上id的属性值。具体格式为:xxx.By.cssSelector("标签#ID属性值")复制具体例子:xxx.By.cssSelector("input#btn")复制具体步骤:在被测试百度网页中,按照宏哥在5.2中的方法(1)查找输入框并输入“北京宏哥”,(2)查找“百度一下”按钮,(3)点击“百度一下”按钮。CSS表达式:(

  • CODING DevOps 高可用实践,保障服务稳定的“定海神针”

    对于软件研发团队而言,服务的稳定性是非常重要,它与生产经营、用户留存都密切相关。而CODING作为面向软件研发团队的研发协作管理平台,与客户的业务生产更是密不可分。如何为客户提供高可用、不间断的服务体验,如何多层面、多渠道来保障CODING本身的服务稳定性,成为了CODING发展道路上不懈的追求。背靠腾讯云,充分利用云上能力CODING作为一站式云端开发平台,从诞生之初就生长在云端,充分利用腾讯云的能力为客户提供弹性可靠的服务。比如,CODING持续集成的编译池基于CVM进行架构,保障用户极速构建无需等待;制品库充分利用对象存储COS及CDN极速能力,为广大客户提供了全球一致的拉取及响应。CODING通过对云能力的充分利用,保障客户软件开发过程的可靠。严谨的发布流程,践行最佳实践CODING团队平均每周进行上百次更新发布,以快速响应客户需求。在频繁变更的场景下,为了避免变更引起的业务故障,CODING团队从变更流程上进行了诸多保障措施。CODING提供Testing和Staging两个测试环境,Testing环境由开发团队自行维护,Staging环境由公司统一维护,与线上环境最为接近。

  • C语言---递归反向输出任意长度的字符串

    (该字符串可以包含空格和回车!) 【题目要求】 编写一个递归函数,实现将输入的任意长度的字符串反向输出的功能。 例如输入字符串:ABCD,输出字符串:DCBA。【题目分析】 应用递归的思想有时可以很轻松地解决一些看似不太容易实现的功能。 本题就是利用递归方法解决这类问题的一个代表。要将一个字符串反向地输出,一般采用的方法是将该字符串存放到一个数组中,然后将数组元素反向地输出即可。 这样需要一个存储空间,而且字符串的长度无法自由掌握,因为数组是一种静态数据结构。如果选用动态生成的顺序表或者链表来存放字符串,那么实现起来会比较麻烦,特别是如果把字符串存放到单向链表中,反向输出是非常困难的。 如何才能输入任意长度的字符串,然后将其反向输出呢? 可以通过一个递归的方法巧妙地实现这个功能。 算法描述如下:print(){ 输入字符串的一个字符a: if(a!='#')print(); if(a!='#')then输出该字符a; }复制在该算法中,字符串的结束标志为#,并且#不作为字符串中的内容输出。首先输入字符串的一个字符,存放到变量a中:然后递归地调用函

  • ssm 找不到配置文件项目结构

    项目结构由于想把mybatis的mapper文件和dao层放到一起所以在pom中添加了所以编译时会忽略resources文件中的配置文件,所以pom.xml的<build>标签中修改为<!--指定mapper存放路径--> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!--指定配置文件存放路径--> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include>

  • 【Linux】学习笔记(四) Linux 文件操作

    Linux目录结构是规定好了的FHS标准FHS(英文:FilesystemHierarchyStandard中文:文件系统层次结构标准),多数Linux版本采用这种文件组织形式,FHS定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。 实验楼学习笔记切换目录cd命令.表示当前目录..表示上一级目录-表示上一次所在目录~通常表示当前用户的home目录使用pwd命令可以获取当前所在路径(绝对路径)ls-a可以查看当前目录下全部文件在进行目录切换的过程中使用Tab键自动补全,可避免输入错误 连续按两次Tab可以显示全部候选结果。 文件基本操作1.新建1.1新建文件touch文件名复制1.2新建文件夹mkdir文件夹名复制用-p参数,同时创建父目录(如果不存在该父目录),如下我们同时创建一个多级目录(这在安装软件、配置安装路径时非常有用) mkdir-pfather/son/grandson复制2.复制cp命令2.1复制文件cptestfather/son/grandson复制2.2复制文件夹加入-r或-R参数mkdirfamily cp-rfatherf

  • 用Jaeger做数据分析|跟踪告诉我们更多!

    作者:PavolLoffay我将直接切入主题,Jaeger目前只可视化收集来自测仪应用程序的数据。它不执行任何后处理(除了服务依赖关系图)或任何计算,以从它收集的跟踪中获得其他有趣的指标或特性。这是一个遗憾,因为跟踪包含了所有遥测信号中最丰富的信息!在Jaeger中,我们希望解决这个问题,并为数据科学家和操作人员提供一个平台,以验证一个假设,并最终回答是什么导致停机或为什么系统以某种方式运行的问题。除了随需应变的事件调查外,目标还包括从Jaeger作为标准Jaeger部署的一部分收集的所有跟踪信息中获得见解。因此,让我们先看看一些用例,然后再看看技术细节。指标在我们深入研究平台概述之前,我想讨论一下从跟踪中可以派生出哪些指标标准。当然,不同的后处理工作将产生不同结构的结果,但现在我们只看一下指标,因为指标系统可以直接使用这些指标,所以解决方案不需要任何自定义存储和表示层。网络延迟服务A和服务B之间的网络延迟。跟踪包含关于请求/事务的端到端信息。通过做一些最小的计算,我们能够获得客户机和服务器调用之间的网络延迟。结果可以导出为直方图,并按客户端和服务器服务标签进行划分。示例生成的Prom

  • MethSurv——一个优秀的TCGA甲基化分析工具

    谈起TCGA分析工具,我知道你肯定要说什么GEPIA,cbioportal……,但是TCGA甲基化呢?这些碉堡的神器瞬间就黯然失色了吧,数风流神器,还看白介素同学推荐,首先来看下今天要分享的神器有哪些NB功能吧:MethSurv网页地址:https://biit.cs.ut.ee/methsurv/感兴趣的基因甲基化位点与预后的关系,生存曲线:一键出图,甲基化分布情况:超级酷的小提琴图,展示甲基化与感兴趣的临床表现之间的关系:高颜值图片全部可用直接下载,放到自己的paper中的,计算出HR,提供一系列其它数据库的链接,genecards,COSMIC,GO数据库等。还可根据染色体选择分析:分析感兴趣的基因甲基化在多肿瘤中的关系,随时出图KMplot提供各种肿瘤中的Topbiomarker还有惊喜,超酷的热图免费送,自动出图,可以拿去发表了本科研神器还提供数据下载,即甲基化位点在TCGA肿瘤中的预后分析,单因素和多因素都有,且提供TCGA甲基化数据的矩阵数据,已经处理好了,拿来即用!好了,今天的内容就分享到这,想要这个神器嘛???

  • 对某网的一次渗透测试纪实

    文章转自:先知社区作者:Ph3mf0lk地址:https://xz.aliyun.com/t/4694最近一个月学着去挖洞,混了快2个月的补天。还是有挺多收获的。这里记录一个昨天对某人才网的渗透测试。从逻辑越权,xss,弱口令等到getshell,控制数据库.....新人第一次写稿,有不足的地方恳请师傅们指出 目标站点我就以www.xxx.com代替1.逻辑越权 这个人才网有个人用户和企业用户,企业用户注册需要提供营业执照等等。然后只有企业用户才能下载人才简历,查看各个求职者的详细信息,比如身份证号码,联系方式等等。 我们先注册一个个人用户,然后登陆 我们可以看到下面有个"最新人才"的栏目点更多,我们可以看到有大约有3w多简历我们先随便点一个人的简历可以看到当我们是个人用户时已经可以看见这个求职者的很多信息了,但是身份证信息和联系方式作为个人用户是看不见的然后我们尝试点一下下载简历:果然只有企业用户才能下载。 这时候我想起了在各大平台看见的逻辑漏洞的总结,于是尝试用burp抓包来看看有没有可能越权成为企业用户 我们对下载简历抓包我们可以看到那个eid是我们查看的这个

  • 春节充电系列:李宏毅2017机器学习笔记14之无监督学习:词嵌入表示(Word Embedding)

    【导读】我们在上一节的内容中已经为大家介绍了台大李宏毅老师的机器学习课程的无监督学习:主成分分析(PCA),这一节将主要针对讨论unsupervisedlearning-wordembedding。本文内容涉及机器学习中半监督学习wordembedding的若干主要问题:wordembedding的含义,prediction-based,languagemodel以及wordembedding拓展。话不多说,让我们一起学习这些内容吧春节充电系列:李宏毅2017机器学习课程学习笔记01之简介春节充电系列:李宏毅2017机器学习课程学习笔记02之Regression春节充电系列:李宏毅2017机器学习课程学习笔记03之梯度下降春节充电系列:李宏毅2017机器学习课程学习笔记04分类(Classification)春节充电系列:李宏毅2017机器学习课程学习笔记05之Logistic回归春节充电系列:李宏毅2017机器学习课程学习笔记06之深度学习入门春节充电系列:李宏毅2017机器学习课程学习笔记07之反向传播(BackPropagation)春节充电系列:李宏毅2017机器学习课程学习笔

  • Mongodb中经常出现的错误 child process failed, exited with error number

    异常处理汇总-服务器http://www.cnblogs.com/dunitian/p/4522983.html异常处理汇总-数据库系列http://www.cnblogs.com/dunitian/p/4522990.html情况不唯一,这边只能当参考,大致就是这么几种解决思路childprocessfailed,exitedwitherrornumber1childprocessfailed,exitedwitherrornumber48childprocessfailed,exitedwitherrornumber100

  • 欢迎来到被容器技术改变的世界!

    如果你将容器整合到构建工作流程中,我们未来的多云环境的所有要素都开始落实到位。 现代应用程序取得发展很大程度上归功于方兴未艾的开发运营(DevOps)潮流以及由此带来的各种自动化工具。如今,广大开发人员在考虑问题时需要着眼于使用的工具以及这些工具从最初设想到实际应用程序的整个流程中如何协同使用,而不是仅仅着眼于编写代码。容器是这种新工作流程中最重要的新工具之一。诸如Docker之类的新技术帮助我们获得关键服务后,将它们从底层基础设施中抽象出来。这种方法让我们得以重新思考如何部署应用程序,以及如何才能充分地利用云基础设施。完整的基础设施在亚马逊公司近日于伦敦召开的一次大会上,AWS的一位用户描述了他的团队如何处理应用程序的更新:他们不是简单地推送更改后的代码,而是让构建过程的输出成为“完整的基础设施”。只有该基础设施部署并测试完毕后,他才会切换到DNS,让它成为一个活动系统。这种方法具有诸多优点,尤其是让你可以在投入运行的头几天当中将旧的虚拟基础设施当成备用系统,之后再删除。推出完整的基础设施这一想法最初看起来似乎很奇怪,但是当你考虑了云部署的经济性后,它比部署更新要来得省钱多了。它还意

  • 【学术】强化学习系列(下):贝尔曼方程

    在前一篇文章中,我们学习了马尔可夫决策和强化学习框架的一些主要组成部分。在本文中,我们将建立在这一理论上,学习价值函数和贝尔曼方程。 回报和返还(return) 正如前面所讨论的,强化学习agent如何最大化累积未来的回报。用于描述累积未来回报的词是返还,通常用R表示。我们还使用一个下标t来表示某个时间步长的返还。在数学符号中,它是这样的:如果我们让这个级数趋于无穷,那么我们最终会得到无限的返还,这对于问题的定义并没有太大意义。因此,只有在我们期望返还的级数终止时,这个方程才有意义。我们将这种总是终止的任务称为“插曲式”(episodic)。纸牌游戏是解释“插曲式”问题的好例子。“插曲”开始于对每个人发牌,并且不可避免地会随着游戏规则的不同而结束。然后,下一“插曲”又开始了另一回合的游戏。相比使用未来的累积回报作为返还,更常见的是使用未来的累积折现回报(cumulativediscountedreward):其中0<γ<1。以这种方式定义返还的两个好处是,返还在无穷级数中得到了很好的定义,而且它把更大的权重给了更早的回报,这意味着我们更关心即将得到的回报,而不是将来会得到更

  • 数组逆序排列输出

    输入一组整,将这组数组从大到小逆序排列,并按照指定格式输出。 输入格式: 一行一组数据 输出格式: 指定的格式输出逆序 输入样例: 12345678 复制   输出样例: 8->7->6->5->4->3->2->1复制 ss=input() lt=ss.split() lt.sort(reverse=True) print('->'.join(lt))复制   诚者,君子之所守也。

  • 操作系统(二)

    3存储管理 逻辑地址与物理地址 逻辑地址,用户编程使用的地址空间 物理地址,程序执行使用的地址空间 地址转换:将逻辑地址转换为物理地址 主存复用 多道程序设计需要复用主存 按照分区复用: 主存划分为多个固定/可变尺寸的分区 一个程序/程序段占用一个分区 按照页架复用: 主存划分成多个固定大小的页架 一个程序/程序段占用多个页架 段式程序设计:把一个程序设计成多个段,代码段、数据段、堆栈段、等等 存储管理 段式存储管理:段式二维逻辑地址空间的程序占用多个主存可变分区 页式存储管理:一维逻辑地址空间的程序占用多个主存页架区 段页式存储管理:段式二维逻辑地址空间的程序占用多个主存页架区 存储保护 为避免主存中的多个进程相互干扰,必须对主存中的程序和数据进行保护 私有主存区中的信息:可读可写 公共区中的共享信息:根据授权 非本进程信息:不可读写 CPU检查是否允许访问,不允许则产生地址保护异常 虚拟存储 引入原因: 用户编写程序必须考虑主存容量限制 多道程序设计的道数受到限制 可行原因: 程序运行局部性原

  • fcitx 无法启动

    困扰了好久的问题,终于解决了。 问题描述: 在fcitx的输入法配置栏里,输入法列表是空的,使用Ctrl+space无法启用任何的输入法,   当然此截图中的是有的,这是问题已经解决后的状态了。 解决方法也是简单暴力: 将.config/fcitx目录删除就一切搞定。 参考此帖:http://www.findspace.name/easycoding/148  

  • Sanic十九:Sanic 扩展之sanic-openapi生成接口文档之doc提供的一些装饰器

      sanic-openapi除了可以使用app.config来指定一些基础的配置外,sanic-openapi.doc还提供了很多装饰器用法的配置,导入doc模块   1、exclude(True):用此装饰器修饰的路由将不会显示在Swagger中   2、summary():添加接口的概述   3、description():接口描述   4、tag():接口分组,默认情况下,接口会根据蓝图名分组,当没有指定时,会用default   5、operation():Sanic默认会用路由修饰的函数名作为路由的终结点,可以用operation来指定终结点名称   6、consumes():指定参数类型和参数示例 查询字符串参数 header参数 body参数   7、produces():200状态的响应示例   8、response():其他响应,当同时使用了response和produces时,200的响应使用produces设置的值 &

  • js对象属性值初始化封装函数

    在平常做项目的过程中,总是会遇到需要对一个已经定义过的对象的属性值进行初始化,且对象的属性值的类型有多种(string、number、array、object、boolean),为了方便自己就简单封装了一个函数。 objInit(obj){ for(letkeyinobj){ switch(typeofobj[key]){ case'string': obj[key]=''; break; case'number': obj[key]=0; break; case'object': if(obj[key]instanceofArray){ obj[key]=[] }else{ this.objInit(obj[key]); } break; case'boolean': obj[key]=true; break; } } returnobj; };复制     

  • Redis基本数据类型常用命令

    简介 Redis是一个高性能的key-value数据库。Redis对数据的操作都是原子性的。 优缺点 优点: 基于内存操作,内存读写速度快。 Redis是单线程的,避免线程切换开销及多线程的竞争问题。单线程是指在处理网络请求(一个或多个redis客户端连接)的时候只有一个线程来处理,redis运行时不只有一个线程,数据持久化或者向slave同步aof时会另起线程。 支持多种数据类型,包括String、Hash、List、Set、ZSet等。 支持持久化。Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免数据丢失问题。 redis采用IO多路复用技术。多路指的是多个socket连接,复用指的是复用一个线程。redis使用单线程俩轮询描述符,将数据库的开、关、读、写都转换成了时间。多路复用主要有三种技术:select、poll、epoll。epoll是最新的也是目前最好的多路复用技术。 缺点:对join或其他结构化查询的支持就比较差。 io多路复用 应用场景 缓存热点数据,缓解数据库的压力 利用Redis中原子性的自增操作,可以用于实现计算器的功能,比如统计用户点赞数、

  • 模板自定义函数 template function

    sqlite3中的日期默认是UTC,当日期字段的默认值是CURRENT_TIMESTAMP时,这个日期和北京时间CST少了8小时。网上建议说数据库里用UTC,读取数据时再转换为当地时间。 web页面中的日期如创建日期通常是需要“格式化”一下的,否则显示出来是这个样子: 2017-08-1708:50:37+0000UTC复制 在gotemplate中可以使用管道,自定义一个日期函数即可。其实这个函数很简单,关键就是要用Local函数: funcformatDate(ttime.Time)string{ layout:="2006-01-02" returnt.Local().Format(layout) }复制 还要记住一点:给模板中增加的自定义函数要在解析html文件前调用! funcMap:=template.FuncMap{ "fdate":formatDate,"fdatetime":formatDateTime } t,err:=template.New("employees.html").Funcs(funcMap).ParseFiles("employees.h

相关推荐

推荐阅读