精华内容
下载资源
问答
  • 列表分析(Java实现)

    千次阅读 2017-05-03 21:47:57
    列表分析(Java实现)一、 散列表的原理 散列表是一种空间换时间的存储结构,是在算法中提升效率的一种比较常用的方式。 散列表(哈希表),是指可以通过关键字key直接访问到内容value的一种数据结构。可以一个...

    散列表分析(Java实现)


    一、 散列表的原理

    散列表是一种空间换时间的存储结构,是在算法中提升效率的一种比较常用的方式。

    散列表(哈希表),是指可以通过关键字key直接访问到内容value的一种数据结构。可以一个value对应多个key,但是一个key只能对应一个value,其中是通过key映射到一个位置上,来直接访问value。

    这里写图片描述

    而映射位置的机制,会导致可能不同key指向相同位置,这种现象成为“碰撞”。这对哈希表来说是非常不希望发生的现象。而对key进行处理转换可以避免“碰撞”现象的发生。

    我们通过哈希函数使内容均匀的分配在数据结构中。

    二、常见的哈希函数:

    1. 直接寻址法

    取关键字或关键字的某个线性函数值为散列地址。

    2.数字分析法

    通过对数据的分析,发现数据中冲突较少的部分,用于构造散列地址。

    3.平方取中法

    先求出key的平方值,然后按需要取平方值的中间几位作为散列地址。

    4.取随机数法

    使用rand()等随机函数构造。

    5.除留取余法

    取关键字被某个不大于散列表的表长n的数m除后所得的余数p为三列表地址。

    三、解决“碰撞”的方法

    1.开放地址法

    key哈希后,发现该地值已被占用,可对该地址不断加1,直到遇到一个空的地址。

    2.再哈希法

    发生“碰撞”后,可对key的一部份再进行哈希处理。
    详细分析http://blog.csdn.net/weiyastory/article/details/52069305

    3.链地址法

    链地址法是通过将key映射在同一地址上的value,做成一个链表。这是较常用方法,本文将详细讲解这种方法。

    这里写图片描述

    四、Java以链地址法实现散列表及分析

    注意事项

    • 扩容因子
      散列表的地址使用率越大,发生“碰撞”的可能性就越大,一般在散列表地址使用率达到一定值的时候,就对散列表进行扩容,这个值称为扩容因子,为小数。

    • 关键字key
      关键字可以不为整形,但一般高级语言会把所有类型的key都转换为整形,而Java中有hashCode()方法,可以得到任何类型量的哈希值。

    
    
    import java.util.Objects;
    
    /**
     * Created by max on 17-5-3.
     */
    public class MyHashTable {
    
        private static final int DEFAULT_INITAL_CAPACITY = 5;//定义的是默认长度
    
        private static final float LOAD_FACTOR = 0.75f;//扩容因子
    
        private Entry[] table = new Entry[DEFAULT_INITAL_CAPACITY];//初始化
        private int size =0;//哈系表大小
        private int use =0;//使用的地址数量
    
        private class Entry{
            int key;//关键字
            int value;
            Entry next;//链表
    
            public Entry(int key,int value ,Entry entry)//构造函数
            {
                super();
                this.key = key;
                this.value = value;
                this.next = entry;
            }
        }
    
        public void put(int key,int value){//压入内容
            int index =hash(key);//通过hash方法转换,采用的是直接法
    
            if (table[index]==null)//说明位置未被使用
            {
             table[index] = new Entry(-1,-1,null);
            }
    
            Entry tmp = table[index];
            if (tmp.next == null)//说明位置未被使用
            {
                table[index].next = new Entry(key,value,null);
                size++;
                use++;
                if (use >= table.length*LOAD_FACTOR)//判断是否需要扩容
                {
                    resize();//扩容方法
                }
            }else{//已被使用,则直接扩展链表
                for (tmp = tmp.next;tmp!=null;tmp = tmp.next)
                {
                    int k =tmp.key;
                    if(k==key)
                    {
                        tmp.value = value;
                        return;
                    }
                }
    
                Entry temp = table[index].next;
                Entry newEntry = new Entry(key,value,temp);
                table[index].next = newEntry;
                size++;
            }
    
        }
        public void remove(int key) //删除,链表的中间值删除方法
        {
            int index =hash(key);
            Entry e = table[index];
            Entry pre = table[index];
            if (e!=null&& e.next!=null)
            {
                for (e=e.next;e!=null;pre =e,e =e.next)
                {
                    int k =e.key;
                    if(k==key)
                    {
                        pre.next = e.next;
                        size--;
                        return;
                    }
                }
            }
        }
    
        public int get(int key)//通过key提取value
        {
            int index = hash(key);
            Entry e =table[index];
            if (e!=null&&e.next!=null)
            {
                for (e=e.next;e!=null;e=e.next)
                {
                    int k = e.key;
                    if (k ==key)
                    {
                        return e.value;
                    }
                }
            }
            return -1;
        }
    
        public int size(){//返回元素个数
            return size;
    
        }
    
        public int getLength(){//哈系表大小
            return table.length;
        }
    
    
        private void resize() {
            int newLength = table.length*2;
            Entry[] oldTable = table;
            table = new Entry[newLength];
            use = 0;
            for(int i =0 ;i<oldTable.length;i++)
            {
                if (oldTable[i]!=null&&oldTable[i].next !=null)
                {
                    Entry e = oldTable[i];
                    while(null!=e.next)
                    {
                        Entry next = e.next;
                        int index =hash(next.key);
                        if (table[index]==null)
                        {
                            use++;
                            table[index] = new Entry(-1,-1,null);
                        }
                        Entry temp = table[index].next;
                        Entry newEntry =new Entry(next.key,next.value,temp);
                        table[index].next = newEntry;
    
                        e = next;
                    }
                }
            }
    
        }
    
        private int hash(int key) {//哈希方法
            return key%table.length;
        }
    
    
    
    }
    

    参考 《轻松学算法互联网算法面试宝典》赵烨

    展开全文
  • 本文是一个静态代码分析工具的清单,共有30个工具。包括4个.NET工具、2个Ada工具、7个C++工具、4个Java工具、2个JavaScript工具、1个Opa工具、2个Packaging工具、3个Perl工具、1个Python工具、1个嵌入式工具、2个二...

         

         本文是一个静态代码分析工具的清单,共有30个工具。包括4个.NET工具、2个Ada工具、7个C++工具、4个Java工具、2个JavaScript工具、1个Opa工具、2个Packaging工具、3个Perl工具、1个Python工具、1个嵌入式工具、2个二进制工具、1个静态分析工具


    Fortify SCA


           Fortify SCA 是一个静态的、白盒的软件源代码安全测试工具。它通过内置的五大主要分析引擎:数据流、语义、结构、控制流、配置流等对应用软件的源代码进行静态的分析,分析的过程中与它特有的软件安全漏洞规则集进行全面地匹配、查找,从而将源代码中存在的安全漏洞扫描出来,并给予整理报告。扫描的结果中不但包括详细的安全漏洞的信息,还会有相关的安全知识的说明,以及修复意见的提供

        

             官网:https://fortify.com/


    • Coverity源代码缺陷检测工具

           Coverity能够准确识别出研发工作流中的严重质量缺陷,并且提供可行的修正建议来降低软件错误和安全漏洞的修复成本、时间和风险。Coverity可使用高级源码分析技术在非常复杂的C、C++、Java、Objective-C、Javascript及C#码库中发现最严重的质量缺陷和安全漏洞, Coverity是第一个能够快速、准确分析当今的大规模(几百万、甚至几千万行的代码)、高复杂度代码的工具,Coverity解决了影响源代码分析有效性的很多关键问题:构建集成、编译兼容性、高误报率、有效的错误根源分析等。

       

     官网:https://coverity.com

    ProteCode二级制代码扫描工具

      ProteCode可对应用程序和固件进行扫描,并列出所含代码和库文件相关的软件许可及对应的已知漏洞。ProteCode不仅能揭示开源的和私有的第三方代码和库文件,还能够枚举出对应的CVE(Common Vulnerabilities and Exposures)标识符以及相关的软件许可证。将编译好的二进制文件上传(不需要源代码),仅需花费几分钟时间就可以揭示出你所需要的软件内部运行的信息。解决方案有助于研发团队安全无误地使用和管控第三方代码。在开发和测试流程或法律合规部门管理由于使用第三方代码所产生的风险,其中包括开源、内部开发、外包和商业代码。


    Hex-Rays二进制分析工具

    ­­ 荷兰Hex-Rays公司的二进制分析工具能够将二进制代码转换成分析员们容易可以读取和修改的文本,帮助分析员分析和验证的程序,更快捷的判断软件的有用性和可用性,定位安全问题。


    .NET

    .NET Compiler Platform(代号 Roslyn)

    Roslyn提供有着丰富的代码分析API的开源C#和Visual Basic编译器。它可以使用这些Visual Studio里的API生成代码分析工具。

          官网:https://roslyn.codeplex.com/

    CodeIt.Right

    CodeIt.Right提供一个快速的自动的方法确保你的源代码遵循预先定义的设计和风格准则。它通过以下方式使静态代码分析进入更高水平:即时代码审查、及早发现问题、编码原则、自动代码审查、集成StyleCop检查、报告。


    FxCop

    一个实现.NET静态代码分析的图形用户接口和命令行工具。

    FxCop提供几百种规则实现各种类型的分析。包括:设计、全球化、互操作性、可维护性、灵活性、命名、性能、可移植性、可靠性、安全性,利用率。FxCop的功能完全集成到Visual Studio2010的高级版和最终版中。


    StyleCop

    StyleCop分析C#源代码,强制执行一系列风格和一致性规则。可以在Visual Studio内部运行,也可以集成到MSBuild项目中。StyleCop还可以被集成到很多第三方开发工具中。

    核心原则:

    StyleCop通过为C#代码强制执行一组通用风格规则来体现价值。StyleCop将继续利用一个连续的带有允许的最小规则配置的规则集。开发者可以实现他们自己的规则,只要他们愿意。

    StyleCop拥有和Visual Studio、MSBuild,TFS等无缝集成的能力。开发者可以自由执行自定义代码,将StyleCop集成到其他开发和工具环境,如SDK文档中所述。


     Ada

    AdaControl

    AdaControl是一个免费的(授权)工具,可以检测Ada程序中使用的各种结构。它的首要目标是控制风格和程序规则的正确使用,但是它也可以作为一个强大的工具搜索编程风格或设计模式的各种形式。搜索的元素范围有非常简单的,比如某种实体、声明或语句的出现,也有非常复杂的,比如验证遵守了某种编程模式。


    Fluctuat

    Fluctuat是一抽象解释器,以数字编程(C或Ada)静态分析器为基础,由CEA-LIST的ME ASI(ModElling and Analysis of Systems in Interaction)实验室在2001年开发。给出一组输入和参数,可能带有不确定因素,它会考虑这个程序所有可能的行为,无论是真实的还是有限精度下,并描述这些不同的特性。


     C,C++

    BLAST

    BLAST(Berkeley Lazy Abstraction Software verification Tool伯克利惰性抽象软件验证工具)是一个C语言静态软件验证工具,它可以解决可达性问题,例如是否可以通过一个有效的执行命令从入口点(主程序)到达给定的程序位置。

    安全属性的验证可能降低到可达性,BLAST常常用于核查Linux驱动程序验证项目。

    可以在以下网站下载Linux系统的BLAST源代码或二进制版本。


    Cpplint

    这个项目继续开发cpplint,它是一个C++风格检查器,遵循Google的C++风格指南。提供的cpplint 为PYPI(Python Package Index)包,并添加了几个功能和修复程序。它是google/styleguide的一个分支,希望未来可以合并在一起。


    Coccinelle

    Coccinelle是一个程序匹配和转换引擎。它提供语意修补程序以便在C代码中指定期望的匹配和转换。Coccinelle初始的目的是完成Linux的间接开发。这种开发包括客户端代码中所需要的改变,目的是响应库应用程序接口变化。还可能包括一些修改,例如重命名一个函数、添加一个函数参数,它的值以某种方式被上下文决定、重组数据结构。除了间接开发,Coccinelle还可以成功的寻找和修复系统代码中的错误。


    Frama-C

    Frama-C是一个平台,致力于分析用C语言写的源代码。

    Frama-C集成几个分析技术到一个协作平台中。其包含一组提供核心功能的内核(例如一个C程序的抽象化语法树)和一组被称为插件的分析器。这些插件可以建立在平台中其他插件的计算结果之上。

    归功于这个方法,Frama-C能提供一些复杂的工具,包括:

    • 一个基于抽象解释器的分析器,旨在验证不存在运行时错误;
    • 一个基于最弱前提运算的程序防护框架;
    • 一个程序切片器;
    • 一个验证临时特性的工具;
    • 几个代码开发和相关性分析的工具。

    这些插件共享常见的语言,可以通过ASCL(ANSI/ISO C Specification Language)特性交换信息,还可以通过它们的APIs集合信息。


    Lint

    Lint实用程序尝试检测命名为C程序文件的功能,可能是错误,也可能是不可移植,或者是浪费。同时它也执行比C编译器更严格的类型检查。Lint实用程序运行C预处理器作为它的第一阶段,带有这个预处理器的标志“lint”,其被定义为允许某些有问题的代码被lint更改或跳过。因此,对于所有被lint检查的代码来说这个标志应该被认为是一个预留字。


    Sparse

    Sparse是一个源文件智能语法分析器:它不是编译器(虽然它可以作为一个前端编译器使用),也不是预处理器(虽然它包含部分预处理语句)。

    这意味着它是一个小而简单的库。内容太少是它容易使用的部分原因。它只有一个任务,就是为任意用户创造语法分析树从而进行进一步的分析。它不是分词器,也不是那些通用的上下文无关的语法分析器。事实上,上下文(语意)就是我想说的不仅解决分组标记,而且还有_type_在组中的含义。

    语法分析完成以下5个阶段:完整文件标记化、预处理(可以导致另一个文件进入标记阶段)、语法分析、延长性评估、内联函数扩展和简化树。


    Splint

    Splint是一个辅助注释轻量级静态检查工具,检查C程序的安全漏洞和代码错误。作为一个更好的lint,使用Splint毫不费力。如果投入额外的工作添加注释到程序中,Splint可以执行比任何标准lint能完成的更强的检查。

     Java

    Checkstyle

    Checkstyle是一个开发工具,可以帮助程序员编写Java代码,并使其遵守编码标准。它自动执行检查Java代码的过程,使人们从这种无聊但是重要的任务中解放出来。对于那些想要执行代码标准的项目,这是非常理想的。

    Checkstyle是高配置的,几乎可以支持任何代码标准。


    FindBugs

    FindBugs是一个使用静态分析寻找Java代码中错误的程序。


    KeY

    传统的说,Key过去是一个Java程序验证工具。虽然现在这仍然是它的主要应用之一,但是这些年来它已经成长为一个拥有各种领域应用的程序验证平台。当前最重要的应用是:

    • 程序验证(独立的图形用户界面、Eclipse集成、KeYHoare)
    • 调试(符号执行调试器)
    • 信息流分析(安全)
    • 测试用例产生(KeYTestGen)

    我们一直致力于让Key框架更容易被其他程序访问。例如,在另一个工具的后台可以很容易的将Key当成一个符号执行引擎使用。正在进行的工作示例有Java编译器的建造,是一个基于Key创建的符号执行树。


    Soot

    最初,Soot开始于一个Java优化框架,到目前为止,来自世界各地的研究人员和从业人员使用Soot分析、装备、优化和可视化Java和Android应用。它提供四种中间格式分析和转化Java字节码:

    • Baf:一个字节码的简化格式,操作简单。
    • Jimple:一个适合优化的3-地址类型中间格式。
    • Shimple:Jimple的一个SSA变化格式。
    • Grimp:一个适合反编译和代码检查的Jimple合集版本。


     JavaScript

    JSHint

    JSHint是一个社区驱动工具,它检测JavaScript代码中的错误和潜在问题。例如语法错误,隐性类型转换错误,变量泄漏等等。值得注意的是,静态代码分析可以定位许多不同类型的错误,但是它不能检测出你的程序是不是正确、快速或者有没有内存泄漏。应该结合像JSHint这样的工具和单元功能测试一起审查代码。

    JSHint非常灵活,使用者可以轻松的在期望的代码执行环境中调整它。


    JSLint

    JSLint本身是一个JavaScript程序,它可以寻找Javascript程序中的错误,是一个代码质量工具。

    JSLint扫描JavaScript源文件,寻找错误,并返回描述问题的信息和其在程序中的大概位置。这些问题不一定是语法错误,虽然经常是这样。JSLint还查看一些风格习惯和结构问题。它不能证明你的代码是正确的,只是提供另一双眼睛去帮助发现问题。

    JSLint定义了一个专业的JavaScript子集,一个比ECMAScrip程序语言标准(管理JavaScript的文件)更严格的语言。它会驳回大多数合法程序,是一个更高的标准。


    6 Opa

    Opa是一个用于网站开发的函数程序设计语言,编译为JavaScript。Opa包括两部分:第一,是一个来自Opa语言的编译器,功能类似JavaScript的语法但是有很多增强功能。第二,是一个JavaScript库,在运行时使用。

    Opa包括它自己的静态分析器。作为一种以网站应用开发为目的的语言,强大的静态类型编译器检查高级网站数据类型的有效性,默认阻止许多漏洞,比如XSS攻击和数据库代码注入。


    7 Packaging

    Lintian

    Lintian是一个静态分析工具,用于寻找Debian基础包中的错误、违反规则和其他的问题。它可以处理二进制Debian包(.deb)、微型/安装程序包(.udeb)、Debian源程序包(.dsc)和(有限程度的)变更文件。


    Rpmlint

    Rpmlint是一个检查Rpm包中常见错误的工具。经常被用在上传之前测试单个软件包和指定文件或者检查整个分布。默认情况下执行所有可用的检查,但是专项检查可以使用命令行参数实现。

    被检查的文件可以是一个Rpm软件包文件、一个指定文件或一个目录。如果是目录,递归搜索Rpm和指定文件进行检查。特殊值是指在标准输入中被读取的结果被当作单个指定文件内容处理。


    Perl

    Perl::Critic

    Perl::Critic是一个可扩展的框架,对Perl源代码创建和应用编码标准。本质上,它是一个静态源代码分析引擎。Perl::Critic分布着大量的Perl::Critic::Policy模块,它们试图执行各种编码规则。大多数规则模块以Damian Conway的书《Perl Best Practices》为基础。然而Perl::Critic不限于PBP这本书,甚至支持与Conway相矛盾的规则。你可以通过Perl::Critic接口启用、禁用和自定义这些规则。你也可以创造适合自己的新规则模块。


    PerlTidy

    Perltidy是一个Perl脚本,它缩进和重新格式化Perl脚本,使它们更容易阅读。如果你编写或者花很多时间读Perl脚本,你可能觉得它是有帮助的。

    格式化可以使用命令行参数控制。

    Perltidy可以输出置标语言和源代码。

    除了重新格式化脚本,Perltidy可以很好的帮助追踪下面这些错误,缺少或多余的括号、参数和方括号,因为它非常擅长定位错误。


    Padre

    Padre是一个Perl集成开发环境,或换句话说是一个新手Perl程序员易于使用的文本编辑器,但是同时支持大型多语言和多技术项目。

    我们的主要目的是创造一个无语伦比的环境来学习Perl,创建Perl脚本、模块和分布,提供一个可扩展的插件系统以支持添加相关功能和语言,同时支持高级开发者在任何地方使用这个编辑器。

    它也提供静态代码分析来检查常见的初级错误。


    Python

    Pylint

    Pylint是一个Python源代码分析器,它可以查找编程错误,帮助推行编码标准并嗅探代码异味(在Martin Fowler的重构书中定义)。

    Pylint有许多默认启用的规则,因为方法太多所以不能把它们全部压制在一个最小程序中。它是高度可配置的,处理程序可以在代码中控制它。另外,还可以写一些插件添加自己的检查。


    展开全文
  • ios编程 @property的属性列表分析 2013-05-30 00:35 54人阅读 评论(0) 收藏 举报 propertyiOScopy 很多网友在学习Objective - c的时候,都会对@property的使用方法感到困惑。但是呢,@property又是...
     

    ios编程 @property的属性列表分析

     54人阅读 评论(0) 收藏 举报
    很多网友在学习Objective - c的时候,都会对@property的使用方法感到困惑。但是呢,@property又是我们最常使用的以一种机制,很多人在抄写ios编程实战代码时,对于“@property(strong,nonatomic),@property(weak,nonatomic)"完全搞不懂,只能长叹:这是啥,这又是啥?由于市场上基础教程的书对@property的属性列表解释很少,ios大腕又懒得详细解释,所以笔者将把属性列表拆成若干个方面,用几篇博客分别解释,以求朋友间的交流,指教。
    好,下面我们就进入正题。今天要讲的是大家最常见的字符串属性变量,我们经常使用使用下面类似的语句:
    @property (copy,nonatomic) NSString *name;//括号里的属性列表没有顺序,可随意修改
    这条语句就等价于;
     - (void) setName: (NSString *) theName
    {
    if(theName != name){
    [name release]
    name = [theName copy];
    }
    }
    那么为什么要使用copy呢,如果直接使用下面的语句,结果又将如何?
    - (void) setName: (NSString *) theName
    {
    name = theName;
    }
    结果是 name 和 theName 指向同一个对象。当在调用 setName: 方法之后,如果 theName 的值被修改,那么, name 的值也将被修改,这显然不是我们想要的结果。所以,用用 copy 来拷贝 theName 的值到 name 上,其完成功能就是调用一个 alloc 方法来创建一个新的字符串对象(使用 initWithString:theName)。
    也许有些朋友对这句话产生疑问:这显然不是我们想要的结果,何以见得呢。因为这种结果,创建的字符串占用的是同一堆内存空间。后果就是:如果一个字符串已经被一个名称所引用,则以后再有相同的字符串声明时,就不会重新开辟空间,而继续使用开辟好的堆内存,也就是所谓的共享设计。对于初学者来说,还是采用创建一个字符串,就开辟一个内存空间比较好。
    那 nonatomic 又有神马作用呢?在多线程程序中,两个或多个线程可能在同一个时间执行同一个代码,同一个属性。为了防止这种现象的发生,开发人员可以使用互斥锁。nonatomic 的意思是不需要使用互斥锁,atomic 是使用互斥锁。Objective - c  的缺省选项是 atomic 。如果你的程序并没有使用多线程,可以把互斥锁设置为 nonatomic。
    这是由于 nonatomic 

    PS: 本人正在学习IOS6实战开发,本身也是小白,上述博文多有不足之处,欢迎朋友们指正。也希望朋友们能多多交流,把自己编程的疑惑心得写出来,大家共同进步嘛。在后续的日子,笔者会根据实战开发中的错误,每天写点心得的,请赐教!
    展开全文
  • Launcher3向上滑动显示应用列表分析

    千次阅读 2019-04-15 20:31:19
    Android7.0的代码开始,Launcher3可以在Hotseat的区域通过向上滑动打开应用列表界面。本文我们就来详细分析下这个过程吧。 一开始以为是Hotseat里面有onTouchEvent相关的逻辑处理,但是查看代码发现里面基本没有...

    Android7.0的代码开始,Launcher3可以在Hotseat的区域通过向上滑动打开应用列表界面。本文我们就来详细分析下这个过程吧。

    一开始以为是Hotseat里面有onTouchEvent相关的逻辑处理,但是查看代码发现里面基本没有相关的事件处理逻辑,所以我们只能看下布局文件了,由事件分发的机制我们知道,如果子view不拦截处理事件,则它就会向下传递给父容器处理。Hotseat的父容器就是DragLayer。DragLayer不仅有拖拽事件的处理,还把Hotseat的滑动事件传递给AllAppsTransitionController处理。

    packages\apps\Launcher3\src\com\android\launcher3\dragndrop\DragLayer.java
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            ...
    
            if (mDragController.onInterceptTouchEvent(ev)) {
                mActiveController = mDragController;
                return true;
            }
    
            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && mAllAppsController.onInterceptTouchEvent(ev)) {
                mActiveController = mAllAppsController;
                return true;
            }
    
            ...
            return false;
        }

    DragLayer中先判断此事件是否被拖拽事件消费,如果没有再给AllAppsTransitionController处理。其中通过修改FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP,就可以定制化是否允许向上滑动显示应用列表界面。

    packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsTransitionController.java
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            ...
            if (mNoIntercept) {
                return false;
            }
            mDetector.onTouchEvent(ev);
            if (mDetector.isSettlingState() && (isInDisallowRecatchBottomZone() || isInDisallowRecatchTopZone())) {
                return false;
            }
            return mDetector.isDraggingOrSettling();
        }

    函数一开始是一大段用来计算mNoIntercept变量的,当mNoIntercept为真就不拦截此事件,要滑动显示应用列表就必须拦截事件,所以会调VerticalPullDetector的onTouchEvent()方法。我们来看下VerticalPullDetector的主要代码:

    packages\apps\Launcher3\src\com\android\launcher3\allapps\VerticalPullDetector.java
        enum ScrollState {
            IDLE,
            DRAGGING,      // onDragStart, onDrag
            SETTLING       // onDragEnd
        }
        ...    
        interface Listener {
            void onDragStart(boolean start);
            boolean onDrag(float displacement, float velocity);
            void onDragEnd(float velocity, boolean fling);
        }
        ...
        public boolean onTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDownX = ev.getX();
                    mDownY = ev.getY();
                    mLastDisplacement = 0;
                    mDisplacementY = 0;
                    mVelocity = 0;
    
                    if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
                        setState(ScrollState.DRAGGING);
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    mDisplacementX = ev.getX() - mDownX;
                    mDisplacementY = ev.getY() - mDownY;
                    computeVelocity(ev);
                    Log.i(TAG,"moving mDisplacementY=" +mDisplacementY+",mDisplacementX=" +mDisplacementX);
                    // handle state and listener calls.
                    if (mState != ScrollState.DRAGGING && shouldScrollStart()) {
                        setState(ScrollState.DRAGGING);
                    }
                    if (mState == ScrollState.DRAGGING) {
                        reportDragging();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    // These are synthetic events and there is no need to update internal values.
                    if (mState == ScrollState.DRAGGING) {
                        setState(ScrollState.SETTLING);
                    }
                    break;
                ...
            }
            // Do house keeping.
            mLastDisplacement = mDisplacementY;
            mLastY = ev.getY();
            return true;
        }

    可以看到VerticalPullDetector类有一个接口,还有一个枚举变量,并且AllAppsTransitionController实现了VerticalPullDetector的Listener接口。接下来我们就来看下这些接口方法的调用和状态的管理过程。在MotionEvent.ACTION_DOWN处理过程中,先记录下初始位置(mDownX,mDownY),在MotionEvent.ACTION_MOVE中计算移动的距离mDisplacementX,mDisplacementY,计算出滑动速度,然后调用setState()。setState方法的作用一是设置新的状态,二是根据状态回调AllAppsTransitionController的相应方法。最后调用reportDragging()从而调用AllAppsTransitionController的onDrag()方法。

    packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsTransitionController.java
        @Override
        public void onDragStart(boolean start) {
            mCaretController.onDragStart();
            cancelAnimation();
            mCurrentAnimation = LauncherAnimUtils.createAnimatorSet();
            mShiftStart = mAppsView.getTranslationY();
            preparePull(start);
        }

    可以看到onDragStart()是一些初始化的操作,重新创建了一个mCurrentAnimation对象。比较简单,主要的还是onDrag()方法里面调用的setProgress()方法。

    packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsTransitionController.java
       /**
         * @param progress       value between 0 and 1, 0 shows all apps and 1 shows workspace
         */
        public void setProgress(float progress) {
            float shiftPrevious = mProgress * mShiftRange;
            mProgress = progress;
            float shiftCurrent = progress * mShiftRange;
    
            float workspaceHotseatAlpha = Utilities.boundToRange(progress, 0f, 1f);
            float alpha = 1 - workspaceHotseatAlpha;
            float interpolation = mAccelInterpolator.getInterpolation(workspaceHotseatAlpha);
    
            int color = (Integer) mEvaluator.evaluate(mDecelInterpolator.getInterpolation(alpha),
                    mHotseatBackgroundColor, mAllAppsBackgroundColor);
            int bgAlpha = Color.alpha((int) mEvaluator.evaluate(alpha,
                    mHotseatBackgroundColor, mAllAppsBackgroundColor));
    
            mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha));
            mAppsView.getContentView().setAlpha(alpha);
            mAppsView.setTranslationY(shiftCurrent);
    
            if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
                mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y, -mShiftRange + shiftCurrent,
                        interpolation);
            } else {
                mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y,
                        PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent),
                        interpolation);
            }
    
            if (mIsTranslateWithoutWorkspace) {
                return;
            }
            mWorkspace.setWorkspaceYTranslationAndAlpha(
                    PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), interpolation);
    
            if (!mDetector.isDraggingState()) {
                mContainerVelocity = mDetector.computeVelocity(shiftCurrent - shiftPrevious,
                        System.currentTimeMillis());
            }
    
            mCaretController.updateCaret(progress, mContainerVelocity, mDetector.isDraggingState());
            updateLightStatusBar(shiftCurrent);
        }

    setProgress()方法还是比较好理解的,根据progress的值计算出相对应的颜色、透明度,偏移量,并且设置到相应的view上面。

    最后,我们要分析的ACTION_UP事件了。在事件处理中调用setState(ScrollState.SETTLING),从而调用AllAppsTransitionController的onDragEnd()方法。

    packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsTransitionController.java
        public void onDragEnd(float velocity, boolean fling) {
            if (mAppsView == null) {
                return; // early termination.
            }
            if (fling) {//是否是快速滑动事件
                if (velocity < 0) { //表示向上滑动
                    calculateDuration(velocity, mAppsView.getTranslationY());
    
                    if (!mLauncher.isAllAppsVisible()) {
                        mLauncher.getUserEventDispatcher().logActionOnContainer(
                                LauncherLogProto.Action.FLING,
                                LauncherLogProto.Action.UP,
                                LauncherLogProto.HOTSEAT);
                    }
                    mLauncher.showAppsView(true /* animated */,
                            false /* updatePredictedApps */,
                            false /* focusSearchBar */);
                } else {
                    calculateDuration(velocity, Math.abs(mShiftRange - mAppsView.getTranslationY()));
                    mLauncher.showWorkspace(true);
                }
                // snap to top or bottom using the release velocity
            } else {
                Log.i(TAG,"onDragEnd mShiftRange / 2 =" + mShiftRange / 2+",getTranslationY="+ mAppsView.getTranslationY());
                if (mAppsView.getTranslationY() > mShiftRange / 2) { //说明在一半以下
                    calculateDuration(velocity, Math.abs(mShiftRange - mAppsView.getTranslationY()));
                    mLauncher.showWorkspace(true);
                } else {
                    calculateDuration(velocity, Math.abs(mAppsView.getTranslationY()));
                    if (!mLauncher.isAllAppsVisible()) {
                        mLauncher.getUserEventDispatcher().logActionOnContainer(
                                LauncherLogProto.Action.SWIPE,
                                LauncherLogProto.Action.UP,
                                LauncherLogProto.HOTSEAT);
                    }
                    mLauncher.showAppsView(true, /* animated */
                            false /* updatePredictedApps */,
                            false /* focusSearchBar */);
                }
            }
        }

    函数一开始先判断是否是快速滑动事件,如果是就看是否已经处于应用列表界面,如果不是就调用Launcher的showAppsView()方法显示应用列表,否则调用showWorkspace()来显示workspace。其中calculateDuration()是根据当前距离计算出动画的执行时间mAnimationDuration。如果不是快速滑动事件则判断当前滑动的距离是否滑过了一半,如果是则触发相应逻辑,之后走的流程类似。我们以滑动打开应用列表来分析,滑动显示workspace走的类似的流程,还请大家自己分析。showAppsView()中会调用showAppsOrWidgets方法。

    packages\apps\Launcher3\src\com\android\launcher3\Launcher.java
        private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) {
            ...
            if (toState == State.APPS) {
                mStateTransitionAnimation.startAnimationToAllApps(mWorkspace.getState(), animated,focusSearchBar);
            } else {
                mStateTransitionAnimation.startAnimationToWidgets(mWorkspace.getState(), animated);
            }
            ...
        }
    
    packages\apps\Launcher3\src\com\android\launcher3\LauncherStateTransitionAnimation.java
        public void startAnimationToAllApps(final Workspace.State fromWorkspaceState,
                final boolean animated, final boolean startSearchAfterTransition) {
            ...
            int animType = CIRCULAR_REVEAL;
            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
                animType = PULLUP;
            }
            // Only animate the search bar if animating from spring loaded mode back to all apps
            startAnimationToOverlay(fromWorkspaceState,
                    Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, animType, cb);
        }

    很显然我们是到APPS界面,toState肯定等于State.APPS也就是会进入startAnimationToOverlay()逻辑。

    packages\apps\Launcher3\src\com\android\launcher3\LauncherStateTransitionAnimation.java
        private void startAnimationToOverlay(
                final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
                final View buttonView, final BaseContainerView toView,
                final boolean animated, int animType, final PrivateTransitionCallbacks pCb) {
            final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
            ...
            final View contentView = toView.getContentView();
            playCommonTransitionAnimations(toWorkspaceState, fromView, toView,
                  animated, initialized, animation, layerViews);
            ...
            if (animType == CIRCULAR_REVEAL) {
                ...
            } else if (animType == PULLUP) {
                ...
                boolean shouldPost = mAllAppsController.animateToAllApps(animation, revealDurationSlide);
                ...
                final AnimatorSet stateAnimation = animation;
                final Runnable startAnimRunnable = new Runnable() {
                    public void run() {
                        // Check that mCurrentAnimation hasn't changed while
                        // we waited for a layout/draw pass
                        if (mCurrentAnimation != stateAnimation)
                            return;
    
                        dispatchOnLauncherTransitionStart(fromView, animated, false);
                        dispatchOnLauncherTransitionStart(toView, animated, false);
    
                        // Enable all necessary layers
                        for (View v : layerViews.keySet()) {
                            if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
                                v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                            }
                            if (Utilities.ATLEAST_LOLLIPOP && v.isAttachedToWindow()) {
                                v.buildLayer();
                            }
                        }
    
                        toView.requestFocus();
                        stateAnimation.start();
                    }
                };
                mCurrentAnimation = animation;
                if (shouldPost) {
                    toView.post(startAnimRunnable);
                } else {
                    startAnimRunnable.run();
                }
            }
        }

    总的来说就是创建了一个AnimatorSet,然后先播放State状态改变的动画,再调用mAllAppsController.animateToAllApps()播放workspace到列表界面的动画。这其中会调用AllAppsTransitionController的animateToAllApps方法,里面有动画结束的监听,当动画结束时会调用Detector的finishedScrolling()方法更改State状态为ScrollState.IDLE。

    好了,整个过程我们就分析了一遍了。由于本人知识水平有限,难免有写的不对的地方,还请大家指正。

    展开全文
  • List Parsers列表分析器List Parsers are generated by the special predefined parser generator object list_p, which generates parsers recognizing list structures of the type列表分析器生成自特殊
  • 网易相册列表分析

    万次阅读 2007-03-02 15:14:00
    我是通过抓包和文件调用跟踪分析,来摸清网易相册的列表方式的。值得注意的是,网易相册的相片地址列表并不是由服务器处理后再发过来的,而是通过脚本控制,服务器只是发个框架和一些控制脚本过来~~~ 用 FireFox 2.0...
  • 获取控件属性列表分析

    千次阅读 2013-06-05 17:04:19
    可见flist[0].PropType的TTypeKind类型描述就是要分析处理,也就是TTypeKind类型 tkClass, tkMethod,tkEnumeration、tkSet 事件,类属性(字体)函数,枚举、集合 type TAnchors = set of TAnchorKind; ...
  • 将真正的Request URL与版面列表抓取的主题列表结果比对 发现请求构成 http://www.newsmth.net/nForum/board/[BoardName]?ajax&amp;amp;amp;p=[page] Boardname为版面列表中获取的URL page 为...
  • 反射相关类Method接口列表分析

    千次阅读 2015-05-13 10:38:44
    Method对象表示一个类方法,保存着方法的相关信息,可以动态的进行方法调用... 其次,后面的args当然就是这个方法的参数列表了,注意参数的对应问题。  第三,就是这个调用的等价调用是obj.methodName(args)。
  • 源码 https://github.com/Zyn0423/crawler-.git 源码
  • 5 LINGO的错误列表 6 致谢 7 更多推荐 今天老板安排了一个任务,让自己建立一个最经典的CVRP模型,然后用LINGO把建立的模型给求解出来;LINGO只是听说过,从来没有真正使用过,运筹学课程也是混着过来的,...
  • FreeRTOS时间管理--两个延时列表分析

    千次阅读 2018-01-20 15:00:26
    并使用延时列表指针pxDelayedTaskList和溢出延时列表指针pxOverflowDelayedTaskList分别指向上面的延时列表1和延时列表2(在创建任务时将延时列表指针指向延时列表)。 Note: 上面的两个延时列表指针变量和两个...
  • 网易相册列表分析 (转)

    千次阅读 2007-03-07 13:21:00
    我是通过抓包和文件调用跟踪分析,来摸清网易相册的列表方式的。值得注意的是,网易相册的相片地址列表并不是由服务器处理后再发过来的,而是通过脚本控制,服务器只是发个框架和一些控制脚本过来~~~ 用 FireFox 2.0...
  • 大致分析了一下,可分为硬件、软件两方面问题 一、硬件: 1、装配工艺:有的朋友拿到手的产品屏幕边框的缝隙较大。这应该可以要求换货;  有的朋友发现自己的宝贝边框有松动,估计自己动下手可以解决这个问题; ...
  • 列表的性能分析

    2018-12-09 16:36:20
    1 前言 平均查找长度(ASL)用来度量散...分析:不同冲突处理方法、装填因子对效率的影响 2 线性探测法的查找性能 可以证明,线性探测法的期望探测次数 满足下列公式: 当α= 0.5时, 插入操作和不成功查找的期...
  • 微信好友列表数据结构分析

    千次阅读 2020-02-23 10:43:08
    目录PC HOOKHook方法获取列表内存访问方式获取数据分析结构猜想结论得出结论追溯根节点代码实现拓展声明 PC HOOK Hook方法获取列表 6B259EF7 |. 8D45 08 lea eax,[arg.1] 6B259EFA |. C645 FC 01 mov byte ptr ss:...
  • 获取QQ好友列表接口分析

    千次阅读 2018-12-13 13:01:07
    获取QQ好友列表接口分析地址:http://s.web2.qq.com/api/get_user_friends2 提交方式:Post POST参数: r={"h":"hello","vfwebqq":"d820f5515bb0a6c64de6a885217adff3b5e...
  • Android短信列表源码分析

    千次阅读 2014-10-28 20:58:15
    6572_message_conversationList_详细分析
  • 语义分析 (2012) Baselines and Bigrams: Simple, Good Sentiment and Topic Classification Very elegant paper, illustrating that simple Naive Bayes models with bigram features can outperform more ...
  • 语义分析 (2013) Semantic Parsing on Freebase from Question-Answer Pairs ???? ???? Proposes an elegant technique for semantic parsing that learns directly from question-answer pairs, without the need...
  • Redis列表对象之linkedlist和ziplist实现原理分析前言列表对象linkedlistlinkedlist存储结构ziplistziplist存储结构entry存储结构prevlenencodingentry-dataziplist数据示例ziplist连锁更新问题linkedlist和ziplist...
  • 自然语言处理语义分析论文列表

    万次阅读 2019-12-13 12:13:02
    sentiment analysis 2018 Targeted Aspect-Based Sentiment Analysis via Embedding Commonsense Knowledge into an Attentive LSTM [Paper] [Review] Yukun Ma, Haiyun Peng, Erik Cambria, AAAI, 2018 ...
  • 今天我们来看看社区中用户列表时如何展现的,主要是分析分页机制是如何实现的。进入用户列表界面的方法是用webmasetr(社区管理员,密码:12345)登录,然后点击社区首页右上角的管理即可。 展现的界面如下: 该...
  • 乘法散列表分析

    千次阅读 2013-08-22 23:35:45
    构造乘法散列表的乘法方法包含了两个步骤: 1. 用关键字 K 乘上常数 A (0 2. 然后再用 m 乘以这个值,再向下去整 总之散列函数为: h(k) = |_ (m*(k*Amod1)) _|   这里对m没有太大的要求,一般选择他为2的某个幂...
  • linux 信号列表分析

    千次阅读 2012-04-23 15:24:25
    我们运行如下命令,可看到Linux支持的信号列表: ~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) ...
  • ​ 散列表查找性能分析总结

    千次阅读 2015-12-28 22:59:47
    列表,也叫哈希表,英文名是HashTable。是数据结构里面“查找”目录下的一个子知识点。如果散列表没有冲突,则散列查找是我们介绍的所有查找效率...2.数字分析法。3.平方取中法。4.折叠法。5.除留余数发。6.随机数...
  • diff.js 列表对比算法 源码分析

    千次阅读 2017-09-12 11:50:03
    diff.js列表对比算法 源码分析 npm上的代码可以查看 (https://www.npmjs.com/package/list-diff2) 源码如下: 1 /** 2 * 3 * @param {Array} oldList 原始列表 4 * @param {Array} newList 新列表 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,148
精华内容 12,859
关键字:

列表分析