skywang 2017-04-22T02:54:59+00:00 kuiwu-wang@163.com 博客目录(持续更新中...) 2100-01-01T00:01:00+00:00 skywang http://wangkuiwu.github.com/2100/01/01/index

本文是目录索引

目录
第1部分 Linux
第2部分 Java
第3部分 数据结构和算法
第4部分 设计模式

第1部分 Linux

Linux学习基础篇01 双系统中ubuntu的安装方法
Linux学习基础篇02 ubuntu的配置(一) 启用root登录界面
Linux学习基础篇02 ubuntu的配置(二) 设置默认开机选项
Linux学习基础篇02 ubuntu的配置(三) 开机自动挂载磁盘分区
Linux学习基础篇02 ubuntu的配置(四) 终端快捷键和常用配置
Linux学习基础篇02 ubuntu的配置(五) 工作区和自定义快捷键
Linux学习基础篇03 ubuntu软件(一) 必备软件
Linux学习基础篇03 ubuntu软件(二) JDK
Linux学习基础篇03 ubuntu软件(三) 串口工具minicom
Linux学习基础篇03 ubuntu指令和技巧(一) 常用指令汇总
Linux学习基础篇03 ubuntu指令和技巧(二) 网络相关的指令
Linux学习基础篇03 ubuntu指令和技巧(三) 内容查看和文件查找
Linux学习基础篇03 ubuntu指令和技巧(四) 文件的权限
Linux学习基础篇03 ubuntu指令和技巧(五) 用户和用户组的相关操作
Linux学习基础篇03 ubuntu指令和技巧(六) 压缩和解压
Linux学习基础篇03 ubuntu指令和技巧(七) 挂载,卸载,重新分区和格式化
Linux学习基础篇03 ubuntu指令和技巧(八) Jar包

Linux bash总结(一) 基础部分
Linux bash总结(二) 高级部分
Linux bash总结(三) 实战

vim(编辑器之神)01基础篇(一) vim入门
vim(编辑器之神)01基础篇(二) vim模式解析
vim(编辑器之神)01基础篇(三) vim指令补充说明
vim(编辑器之神)02配置篇(一) 基本配置
vim(编辑器之神)02配置篇(二) 插件

第2部分 Java

Java 随机数
Java引用总结--StrongReference、SoftReference、WeakReference、PhantomReference
Java Annotation认知(包括框架图、详细介绍、示例说明)
Java 反射机制(包括组成、结构、示例说明等内容)

Java 字符串系列01 String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别
Java 字符串系列02 StringBuilder详解
Java 字符串系列03 StringBuffer详解

Java异常(一) Java异常简介及其架构
Java异常(二) 《Effective Java》中关于异常处理的几条建议
Java异常(三) 《Java Puzzles》中关于异常的几个谜题

Java 时间相关内容的目录(Category)
Java 时间相关内容01 Calendar
Java 时间相关内容02 万年历和自定义Calendar接口
Java 时间相关内容03 Date
Java 时间相关内容04 DateFormat
Java 时间相关内容05 SimpleDateFormat
Java 时间相关内容06 Locale
Java 时间相关内容07 Time

Java 集合系列目录(Category)
Java 集合系列01之 总体框架
Java 集合系列02之 Collection架构
Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
Java 集合系列09之 Map架构
Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例
Java 集合系列13之 WeakHashMap详细介绍(源码解析)和使用示例
Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
Java 集合系列15之 Set架构
Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例
Java 集合系列17之 TreeSet详细介绍(源码解析)和使用示例
Java 集合系列18之 Iterator和Enumeration比较
Java 集合系列扩展(一) Comparable和Comparator比较
Java 集合系列扩展(二) hashCode()和equals()的若干问题解答

java io系列01之 IO框架
java io系列02之 ByteArrayInputStream详解
java io系列03之 ByteArrayOutputStream详解
java io系列04之 管道(PipedOutputStream和PipedInputStream)详解
java io系列05之 ObjectInputStream和ObjectOutputStream详解
java io系列06之 序列化(Serializable和Externalizable)详解
java io系列07之 FileInputStream和FileOutputStream详解
java io系列08之 File详解
java io系列09之 FileDescriptor详解
java io系列10之 FilterInputStream详解
java io系列11之 FilterOutputStream详解
java io系列12之 BufferedInputStream详解
java io系列13之 BufferedOutputStream详解
java io系列14之 DataInputStream详解
java io系列15之 DataOutputStream详解
java io系列16之 PrintStream详解
java io系列17之 System.out.println详解
java io系列18之 CharArrayReader详解
java io系列19之 CharArrayWriter详解
java io系列20之 PipedReader和PipedWriter详解
java io系列21之 InputStreamReader和OutputStreamWriter详解
java io系列22之 FileReader和FileWriter详解
java io系列23之 BufferedReader详解
java io系列24之 BufferedWriter详解
java io系列25之 PrintWriter详解
java io系列26之 RandomAccessFile详解

Java多线程系列01--“基础篇”01之 基本概念
Java多线程系列02--“基础篇”02之 常用的实现多线程的两种方式
Java多线程系列03--“基础篇”03之 Thread中start()和run()的区别
Java多线程系列04--“基础篇”04之 synchronized关键字
Java多线程系列05--“基础篇”05之 线程等待与唤醒
Java多线程系列06--“基础篇”06之 线程让步
Java多线程系列07--“基础篇”07之 线程休眠
Java多线程系列08--“基础篇”08之 join()
Java多线程系列09--“基础篇”09之 interrupt()和线程终止方式
Java多线程系列10--“基础篇”10之 线程优先级和守护线程
Java多线程系列11--“基础篇”11之 生产消费者问题 Java多线程系列12--“JUC原子类”01之 框架
Java多线程系列13--“JUC原子类”02之 AtomicLong原子类
Java多线程系列14--“JUC原子类”03之 AtomicLongArray原子类
Java多线程系列15--“JUC原子类”04之 AtomicReference原子类
Java多线程系列16--“JUC原子类”05之 AtomicLongFieldUpdater原子类 Java多线程系列17--“JUC锁”01之 框架
Java多线程系列18--“JUC锁”02之 互斥锁ReentrantLock
Java多线程系列19--“JUC锁”03之 公平锁(一)
Java多线程系列20--“JUC锁”04之 公平锁(二)
Java多线程系列21--“JUC锁”05之 非公平锁
Java多线程系列22--“JUC锁”06之 Condition条件
Java多线程系列23--“JUC锁”07之 LockSupport
Java多线程系列24--“JUC锁”08之 共享锁和ReentrantReadWriteLock
Java多线程系列25--“JUC锁”09之 CountDownLatch原理和示例
Java多线程系列26--“JUC锁”10之 CyclicBarrier原理和示例
Java多线程系列27--“JUC锁”11之 Semaphore信号量的原理和示例 Java多线程系列28--“JUC集合”01之 框架
Java多线程系列29--“JUC集合”02之 CopyOnWriteArrayList
Java多线程系列30--“JUC集合”03之 CopyOnWriteArraySet
Java多线程系列31--“JUC集合”04之 ConcurrentHashMap
Java多线程系列32--“JUC集合”05之 ConcurrentSkipListMap
Java多线程系列33--“JUC集合”06之 ConcurrentSkipListSet
Java多线程系列34--“JUC集合”07之 ArrayBlockingQueue
Java多线程系列35--“JUC集合”08之 LinkedBlockingQueue
Java多线程系列36--“JUC集合”09之 LinkedBlockingDeque
Java多线程系列37--“JUC集合”10之 ConcurrentHashMap Java多线程系列38--“JUC线程池”01之 线程池架构
Java多线程系列39--“JUC线程池”02之 线程池原理(一)
Java多线程系列40--“JUC线程池”03之 线程池原理(二)
Java多线程系列41--“JUC线程池”04之 线程池原理(三)
Java多线程系列42--“JUC线程池”05之 线程池原理(四) Java多线程系列--“JUC线程池”06之 Callable和Future

第3部分 数据结构和算法

数据结构和算法 目录

C C++ Java
线性结构 1. 数组、单链表和双链表 数组、单链表和双链表 数组、单链表和双链表
2. Linux内核中双向链表的经典实现
队列 队列 队列
树性结构 二叉查找树 二叉查找树 二叉查找树
AVL树 AVL树 AVL树
伸展树 伸展树 伸展树
哈夫曼树 哈夫曼树 哈夫曼树
1. 红黑树(一)之 原理和算法详细介绍 1. 红黑树(一)之 原理和算法详细介绍 1. 红黑树(一)之 原理和算法详细介绍
2. 红黑树(二)之 C语言的实现 2. 红黑树(四)之 C++的实现 2. 红黑树(五)之 Java的实现
3. 红黑树(三)之 Linux内核中红黑树的经典实现 3. 红黑树(六)之 参考资料 3. 红黑树(六)之 参考资料
4. 红黑树(六)之 参考资料
哈夫曼树 哈夫曼树 哈夫曼树
二叉堆 二叉堆 二叉堆
左倾堆 左倾堆 左倾堆
斜堆 斜堆 斜堆
二项堆 二项堆 二项堆
斐波那契堆 斐波那契堆 斐波那契堆
图的理论基础 图的理论基础 图的理论基础
1. 邻接矩阵无向图 1. 邻接矩阵无向图 1. 邻接矩阵无向图
2. 邻接表无向图 2. 邻接表无向图 2. 邻接表无向图
3. 邻接矩阵有向图 3. 邻接矩阵有向图 3. 邻接矩阵有向图
4. 邻接表有向图 4. 邻接表有向图 4. 邻接表有向图
深度优先搜索和广度优先搜索 深度优先搜索和广度优先搜索 深度优先搜索和广度优先搜索
拓扑排序 拓扑排序 拓扑排序
Kruskal算法 Kruskal算法 Kruskal算法
Prim算法 Prim算法 Prim算法
Dijkstra算法 Dijkstra算法 Dijkstra算法
排序算法 冒泡排序 冒泡排序 冒泡排序
快速排序 快速排序 快速排序
直接插入排序 直接插入排序 直接插入排序
希尔排序 希尔排序 希尔排序
选择排序 选择排序 选择排序
堆排序 堆排序 堆排序
归并排序 归并排序 归并排序
桶排序 桶排序 桶排序
基数排序 基数排序 基数排序

第4部分 设计模式

UML系列01之 UML和绘图工具Visio介绍
UML系列02之 UML类图(一)
UML系列03之 UML类图(二)
UML系列04之 UML时序图
UML系列05之 基本流程图

设计模式01之 简单工厂模式(创建模式)
设计模式02之 工厂方法模式(创建模式)
设计模式03之 抽象工厂模式(创建模式)
设计模式04之 单例模式(创建模式)
设计模式05之 多例模式(创建模式)
设计模式06之 建造模式(创建模式)
设计模式07之 原型模式(创建模式)
设计模式08之 适配器(Adapter)模式(结构模式)
设计模式09之 合成(Composite)模式(结构模式)
设计模式10之 装饰(Decorator)模式(结构模式)
设计模式11之 代理(Proxy)模式(结构模式)
设计模式12之 享元(Flyweight)模式(结构模式)
设计模式13之 门面(Facade)模式(结构模式)
设计模式14之 桥梁(Bridge)模式(结构模式)
设计模式15之 不变(Immutable)模式(行为模式)
设计模式16之 策略(Strategy)模式(行为模式)
设计模式17之 模板方法(Template Method)模式(行为模式)
设计模式18之 观察者(Observer)模式(行为模式)
设计模式19之 迭代器(Iterator)模式(行为模式)

]]>
Jenkins工具(二)之 Jenkins集成android工程 2015-08-07T09:02:00+00:00 skywang http://wangkuiwu.github.com/2015/08/07/jenkins-02

本文演示Jenkins+Android+Gradle+Git的协同工作方法。主要介绍Jenkins如何对android工程进行持续集成,该android工程是通过gradle工具进行构建,并通过git进行版本控制。

目录
1. 下载插件
2. 配置工程
3. 参考链接

1. 下载插件

这里需要下载的插件有git, github和gradle插件。下载方法如下。

第1步:点击"Manage Jenkins" -- "Manage Plugins",进入到插件管理界面。如下图所示。

img

说明:
(1) Update表示可更新的插件,Available表示可下载的插件,Installed表示已下载安装的插件,Advanced表示高级设置选项。
(2) 点击"Available"进入可下载的插件界面;然后,在"Filter"中输入"git"或"gradle",查找相应的插件;然后勾选找到的插件;最后,点击"Install without restart"安装选中的插件。

2. 配置工程

这里介绍如何配置android工程。在配置工程之前,你得有工程。
本文以github上android演示工程来进行讲解。

第1步:在Jenkins中新建工程。

选择"New Item",然后输入Item name之后,选择"Freestyle project"。然后,点击"OK"新建工程。如下图所示。

img

第2步:配置工程。

文本介绍工程的几个重要配置。

配置一:工程路径

点击"Advanced Project Options",勾选"Use custom workspace"进行自定义路径。
接着,在"Directory"中输入自定义的工程路径,例如: /home/skywang/Documents/jenkins/projects 在"Display Name"中输入自定义的工程显示名,例如: TestProject

img

配置二:版本管理工具

点击"Source Code Management",选择git进行版本控制。
接着,在"Repository URL"中输入git仓库的地址。例如,本例的android工程的仓库地址是:https://github.com/wangkuiwu/jenkins-android-demo.git

img

然后,点击"Credentials"右边的"Add",添加认证方式。打开如下认证方式对话框。

img

在认证方式对话框的"Kind"栏中选择"Username with password",即选择用户名/密码的方式进行认证。
接着,输入用户名和密码。 点击"Add",添加该认证方式。返回到配置界面。

img

点击"Credentials"栏的下拉框,选择刚刚添加的认证方式。

配置三:构建触发器

点击"Build Triggers",勾选"Poll SCM"。输入"H 10 * * 2",这意味着"每周二的上午10:00",Jenkins会自动获取服务器上最新的代码,并进行打包验证。

img

配置四:设置构建工具

点击"Build" 下的 "Add build setup",选择"Invoke Gradle script"。
在"Tasks"中输入"clean build"。即表示构建时,会执行命令"gradle clean build"。

img

配置五:添加构成完成后的任务

点击"Add post-build setup",设置构建完成后自动执行的任务。这里选择"E-mail Notification",即构建完成之后自动发送邮寄通知。

img

上面只是列出了几个比较重要、常用的配置;你可以根据自己的需求进行其他定制。

3. 构建工程

前面我们创建了TestProject工程,并且设置"每周二 10:00"会自动从github上下载该工程并进行构建。

这里,我们介绍手动构建的方法。

第1步:开始构建

返回到Jenkins的Dashboard(即首页),然后点击"TestProject"名称右边的下拉图标弹出对话框,选择对话框中的"Build Now"开始构建。

img

第2步:跟踪构建进度

在"Build Executor Status"栏可以查阅构建进度。

img

第3步:查看构建结果

构建完成之后,按F5刷新页面。此时,TestProject工程的状态图标会由之前的"灰色"变成"蓝色"。

img

点击"TestProject"进入到工程,可以看到TestProject的工程内容。如下图

img

第4步:查看输出内容

进入到"Workspcae",可以找到工程的输出apk和单元测试报告。

例如,本工程的输出apk路径是:app/build/outputs/apk/app-debug.apk。进入Workspcae中对应的路径就可以看到该apk文件。

img

例如,本工程的单元测试报告文件是:javaLib/build/reports/tests/index.html。

img

点击index.html打开单元测试报告。

img

4. 参考链接

  1. Jenkins官网
  2. 基于Jenkins+git+gradle的android持续集成
]]>
Jenkins工具(一)之 Jenkins环境搭建 2015-08-07T09:01:00+00:00 skywang http://wangkuiwu.github.com/2015/08/07/jenkins-01

本文介绍Jenkins工具的搭建方法

目录
1. Jenkins介绍
2. 直接安装Jenkins
3. 安装tomcat+Jenkins
4. Jenkins的基本配置
5. 参考链接

1. Jenkins介绍

Jenkins是一个软件持续集成工具。

本文主要介绍在ubuntu系统下搭建Jenkins的方式,通常有两种。
第1种:直接安装Jenkins。
第2种:tomcat+Jenkins的方式。

2. 直接安装Jenkins

第1步:添加jenkins仓库

$ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -

第2步:在/etc/apt/sources.list末尾,添加以下内容。

deb http://pkg.jenkins-ci.org/debian binary/

第3步:安装jenkins

$ sudo apt-get update
$ sudo apt-get install jenkins

第4步:打开jenkins

在浏览器中输入http://localhost:8080http://127.0.0.1:8080打开jenkins。

3. 安装tomcat+Jenkins

前提:在ubuntu系统中安装tomcat。安装完tomcat之后,按照以下步骤将jenkins集成到tomcat中。

第1步:下载jenkins.war

第2步:将jenkins.war集成到tomcat中。

假设tomcat的目录是/home/skywang/opt/apache-tomcat-8.0.24,在将jenkins.war拷贝到webapps目录。指令如下:

$ cp jenkins.war /home/skywang/opt/apache-tomcat-8.0.24/webapps/

第3步:打开jenkins

在浏览器中输入http://localhost:8080/jenkins/http://127.0.0.1:8080/Jenkins打开jenkins。如下图。

img

4. Jenkins的基本配置

下面介绍对Jenkins的JDK和Gradle等基本内容进行配置。

第1步:点击"Manage Jenkins" -- "Configure System",进入到系统设置。

img

第2步:进行JDK的环境变量设置,如下图。

img

第3步:进行git的环境变量设置,如下图。

img

第4步:进行Gradle的环境变量设置,如下图。

img

第5步:点击"Save"保存设置。

4. 参考链接

  1. Jenkins官网
  2. 基于Jenkins+git+gradle的android持续集成
]]>
Ubuntu中tomcat环境搭建 2015-08-06T09:00:00+00:00 skywang http://wangkuiwu.github.com/2015/08/06/tomcat-01

本文介绍在ubuntu系统中中搭建tomcat的方法。

前提:ubuntu系统中已经有JDK运行环境。

第1步:下载tomcat安装包

方法一:下载apache-tomcat-7.0.63.tar.gz

方法二:到官网,选择"tar.gz"包。

img

第2步:解压tar包

$ tar -xvf apache-tomcat-7.0.63.tar.gz

第3步:将解压后的tomcat目录移到指定的目录

$ mv apache-tomcat-7.0.63 /home/project/skywang/opt/tomcat/apache-tomcat-7.0.63

第4步:配置tomcat环境

编辑~/.bashrc,添加以下内容。

## JDK环境变量
export JAVA_HOME=/home/project/skywang/opt/jdk1.7.0_79
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
## TOMCAT环境变量
export TOMCAT_HOME=/home/project/skywang/opt/tomcat/apache-tomcat-7.0.63

说明:上面是配置"java的环境变量"和"TOMCAT环境变量"。若系统中没有JDK,请先对JDK进行配置。

第5步:添加tomcat命令的别名

编辑~/.bashrc,添加以下内容。

alias tomcat_start='/home/project/skywang/opt/tomcat/apache-tomcat-7.0.63/bin/startup.sh'
alias tomcat_stop='/home/project/skywang/opt/tomcat/apache-tomcat-7.0.63/bin/shutdown.sh'

说明:上面是添加tomcat启动和停止指令的别名。
添加别名之后,可以通过$ tomcat_start$ tomcat_stop来快速的启动/停止tomcat服务。

第6步:启动tomcat服务

$ tomcat_start

说明:使用tomcat_start的前提是,执行了"第4步"的别名设置。
否则,需要先cd到tomcat的bin目录,然后运行$ ./startup.sh

第7步:打开tomcat浏览器

在浏览器中输入http://localhost:8080http://127.0.0.1:8080打开tomcat服务器。

img

]]>
maven内部服务器(三) 共享android库 2015-07-24T09:03:00+00:00 skywang http://wangkuiwu.github.com/2015/07/24/nexus-03

本文介绍通过maven内部服务器共享android库,即共享aar包的方法。

目录
1. android本地仓库说明
2. 创建本地仓库
3. 共享android公共库
4. 引用android公共库

1. android本地仓库说明

本文将介绍如何将(通过gradle构建的)android公共库通过nexus共享到服务器上,然后其他客户端就可以轻松的引用到该android公共库。

涉及到的内容可以分为三个部分: 第一部分:创建本地仓库。即,在nexus创建仓库。
第二部分:共享android公共库。即,将android公共库共享到nexus本地仓库中。
第三部分:引用android公共库。即,使用"共享到nexus本地仓库中的android公共库"。

2. 创建本地仓库

下面介绍在nexus中创建本地仓库的方法。

第1步 新建Hosted Repository

在Repositories中点击"Add",选择"Hosted Repository"。 如下图所示

img

第2步 编辑"新建的Hosted Repository"

选择新建的"Hosted Repository",此时它的名称是"New Hosted Repository"。选择它,然后点击"Configuration"。在Configuration中,只需要进行以下几项设置;

(1) Repository ID: 这是可以随意定义,只要不和已有的仓库ID重复即可。为了增加可读性,建议根据共享的android库的名字来命名。
(2) Repository Name: 这个也是可以随意定义的。建议根据共享库的名字来命名。
(3) Povoder: 选择"Maven2"即可。
(4) Repository Policy: 选择"release"即可。
(5) Deployment Policy: 选择"Allow Redeploy(允许部署)"。

除了上面的几项之外,其他的不需要设置;然后,点击"Save"。

img

第3步 查看"新建的Hosted Repository"

点击"Save"之后,新建的"Hosted Repository"的名称就变成上面设置的"Repository ID的值"。点击该仓库,此时该仓库有"Repository Path"和"Default Local Storage Location"等值。

img

3. 共享android公共库

下面介绍如何"将android公共库共享到nexus本地仓库中"。

前面已经创建好了WheelView本地仓库,下面介绍如何将WheelView公共库到本地仓库。本地使用的WheelView公共库已共享到github上,点击查看android共享库的源码,这份源码也是本文的示例源码。


下面介绍"对于用户已有的android库"如何修改,从而使它能被共享到nexus本地仓库。这里仅仅介绍通过gradle自动构建的android库,对于通过ant或者maven构建的工程,这里不予介绍。

第1步 编辑android库的build.gradle

编译android公共库的build.gradle,添加以下内容:

apply plugin: 'maven' 

def isReleaseBuild() {
    return VERSION_NAME.contains("SNAPSHOT") == false
}
def getRepositoryUsername() {
    return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}
def getRepositoryPassword() {
    return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}
afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                pom.groupId = GROUP
                pom.artifactId = POM_ARTIFACT_ID
                pom.version = VERSION_NAME
                repository(url: RELEASE_REPOSITORY_URL) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }   
                snapshotRepository(url: SNAPSHOT_REPOSITORY_URL) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }   
            }   
        }   
    }   
    task androidJavadocs(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }   
    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        classifier = 'javadoc'
        from androidJavadocs.destinationDir
    }   
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.sourceFiles
    }   
    artifacts {
        archives androidSourcesJar
        archives androidJavadocsJar
    }
}

说明:直接将该内容添加到build.gradle的末尾即可,不需要对上面的内容进行额外的修改!

第2步 编辑gradle.properties

编辑andriod公共库中的gradle.properties,添加以下内容。如果没有gradle.properties,则新建该文件。

## GROUP的值是自定义的。它表示群组;若要将该库发布的maven中,则它是库在maven中的groupId值。
GROUP=cn.skw.widget
## VERSION_NAME的值是自定义。它表示版本号;若要将该库发布的maven中,则它是库在maven中的版本号。
VERSION_NAME=1.0               
## POM_ARTIFACT_ID的值是自定义。它表示artifactId;若要将该库发布的maven中,则它是库在maven中的artifactId。
POM_ARTIFACT_ID=SelfWheelView

## 指定值。SNAPSHOT_REPOSITORY_URL是"库在nexus中的Repository Path的值"
SNAPSHOT_REPOSITORY_URL=http://127.0.0.1:8081/nexus/content/repositories/WheelView
## 指定值。RELEASE_REPOSITORY_URL是"库在nexus中Configuration栏的Default Local Storage Location的值"
RELEASE_REPOSITORY_URL=file:/home/project/skywang/opt/nexus/sonatype-work/nexus/storage/WheelView

## 指定值。nexus的用户名
NEXUS_USERNAME=admin
## 指定值。nexus的密码
NEXUS_PASSWORD=admin123

说明:
(1) GROUP: 它的值是自定义的,建议取包名。
(2) VERSION_NAME: 它的值是自定义的,建议取库的版本号。
(3) POM_ARTIFACT_ID: 它的值是自定义的,建议取库的名称。
(4) SNAPSHOT_REPOSITORY_URL: 它必须是nexus中Repository Path的值。
(5) RELEASE_REPOSITORY_URL: 它必须是nexus中库的Configuration栏目中Default Local Storage Location的值。
(6) NEXUS_USERNAME: 它必须是nexus的用户名。
(7) NEXUS_PASSWORD: 它必须是nexus的密码。

第3步 共享android库

在android库下面运行gradle uploadArchives来共享库到nexus中。该指令正常运行的界面如下所示。

img

再回到nexus中,点击仓库的"Browse Storage",会发现里面有aar文件。

img

这表示android公共库已被共享到nexus中!

4. 引用android公共库

下面介绍在其他的android工程中引用"上面共享到nexus中android公共库"的方法。

使用nexus中的android库,只需要在build.gradle中添加以下内容即可。

repositories {
    maven {
        // 本地服务器中WheelView仓库的路径
        url "http://127.0.0.1:8081/nexus/content/repositories/WheelView"
    }   
}

dependencies {
    // cn.skw.widget是仓库的GROUP值,SelfWheelView是仓库的POM_ARTIFACT_ID值,1.0是仓库版本号,@aar是android库的后缀名(如果是jar包,则不需要@aar)
    compile 'cn.skw.widget:SelfWheelView:1.0@aar'
}

点击查看使用android共享库的示例的源码

]]>
maven内部服务器(二) 共享java库 2015-07-24T09:02:00+00:00 skywang http://wangkuiwu.github.com/2015/07/24/nexus-02

本文介绍通过maven内部服务器共享java库,即共享jar包的方法。

目录
1. java本地仓库说明
2. 创建本地仓库
3. 共享jar包
4. 引用jar包

1. java本地仓库说明

本文将介绍如何将(通过gradle构建的)java公共库通过nexus共享到服务器上,然后其他客户端就可以轻松的引用到该java公共库。

涉及到的内容可以分为三个部分: 第一部分:创建本地仓库。即,在nexus创建仓库。
第二部分:共享jar包。即,将jar包共享到nexus本地仓库中。
第三部分:引用jar包。即,使用"共享到nexus本地仓库中的jar包"。

2. 创建本地仓库

第1步 新建Hosted Repository

在Repositories中点击"Add",选择"Hosted Repository"。 如下图所示

img

第2步 编辑"新建的Hosted Repository"

选择新建的"Hosted Repository",此时它的名称是"New Hosted Repository"。选择它,然后点击"Configuration"。在Configuration中,只需要进行以下几项设置;

(1) Repository ID: 这是可以随意定义,只要不和已有的仓库ID重复即可。为了增加可读性,建议根据共享的jar包的名字来命名。
(2) Repository Name: 这个也是可以随意定义的。建议根据共享库的名字来命名。
(3) Povoder: 选择"Maven2"即可。
(4) Repository Policy: 选择"release"即可。
(5) Deployment Policy: 选择"Allow Redeploy(允许部署)"。

除了上面的几项之外,其他的不需要设置;然后,点击"Save"。

img

第3步 查看"新建的Hosted Repository"

点击"Save"之后,新建的"Hosted Repository"的名称就变成上面设置的"Repository ID的值"。点击该仓库,此时该仓库有"Repository Path"和"Default Local Storage Location"等值。

img

3. 共享jar包

下面介绍如何"将jar包共享到nexus本地仓库中"。

前面已经创建好了jar包本地仓库,下面介绍如何将jar包共享到本地仓库。
本文演示用的jar包已共享到github上,点击查看jar包的源码,这份源码也是本文的示例源码。


下面介绍"对于用户已有的jar包"如何修改,从而使它能被共享到nexus本地仓库。这里仅仅介绍通过gradle自动构建的jar包,对于通过ant或者maven构建的工程,这里不予介绍。

第1步 编辑jar包的build.gradle

编译jar包的build.gradle,添加以下内容:

apply plugin: 'maven'

def isReleaseBuild() {
    return VERSION_NAME.contains("SNAPSHOT") == false
}
def getRepositoryUsername() {
    return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}
def getRepositoryPassword() {
    return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}
afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                pom.groupId = GROUP
                pom.artifactId = POM_ARTIFACT_ID
                pom.version = VERSION_NAME
                repository(url: RELEASE_REPOSITORY_URL) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }
                snapshotRepository(url: SNAPSHOT_REPOSITORY_URL) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }
            }
        }
    }

    task sourceJar(type: Jar) {
        from sourceSets.main.allJava
    }
    artifacts {
         archives sourceJar
    }
}

说明:直接将该内容添加到build.gradle的末尾即可,不需要对上面的内容进行额外的修改!

第2步 编辑gradle.properties

编辑andriod公共库中的gradle.properties,添加以下内容。如果没有gradle.properties,则新建该文件。

## GROUP的值是自定义的。它表示群组;若要将该库发布的maven中,则它是库在maven中的groupId值。
GROUP=com.skw.java.util
## VERSION_NAME的值是自定义。它表示版本号;若要将该库发布的maven中,则它是库在maven中的版本号。
VERSION_NAME=0.0.1
## POM_ARTIFACT_ID的值是自定义。它表示artifactId;若要将该库发布的maven中,则它是库在maven中的artifactId。
POM_ARTIFACT_ID=MathLibrary

## 指定值。SNAPSHOT_REPOSITORY_URL是"库在nexus中的Repository Path的值"
SNAPSHOT_REPOSITORY_URL=http://127.0.0.1:8081/nexus/content/repositories/MathLib
## 指定值。RELEASE_REPOSITORY_URL是"库在nexus中Configuration栏的Default Local Storage Location的值"
RELEASE_REPOSITORY_URL=file:/home/project/skywang/opt/nexus/sonatype-work/nexus/storage/MathLib

## 指定值。nexus的用户名
NEXUS_USERNAME=admin
## 指定值。nexus的密码
NEXUS_PASSWORD=54wangkuiwu

说明:
(1) GROUP: 它的值是自定义的,建议取包名。
(2) VERSION_NAME: 它的值是自定义的,建议取库的版本号。
(3) POM_ARTIFACT_ID: 它的值是自定义的,建议取库的名称。
(4) SNAPSHOT_REPOSITORY_URL: 它必须是nexus中Repository Path的值。
(5) RELEASE_REPOSITORY_URL: 它必须是nexus中库的Configuration栏目中Default Local Storage Location的值。
(6) NEXUS_USERNAME: 它必须是nexus的用户名。
(7) NEXUS_PASSWORD: 它必须是nexus的密码。

第3步 共享jar包库

在jar包库下面运行gradle uploadArchives来共享库到nexus中。该指令正常运行的界面如下所示。

img

再回到nexus中,点击仓库的"Browse Storage",会发现里面有jar包。

img

这表示jar包被共享到nexus中!

4. 引用java包

下面介绍在其他的java工程中引用"上面共享到nexus中java公共库"的方法。

使用nexus中的java库,只需要在build.gradle中添加以下内容即可。

repositories {
    maven {
        // 本地服务器中WheelView仓库的路径
        url "http://127.0.0.1:8081/nexus/content/repositories/MathLib"
    }   
}

dependencies {
    // jar包的groudid等信息
    compile 'com.skw.java.util:MathLibrary:0.0.1'
}

点击查看使用jar包的示例的源码

]]>
maven内部服务器(一) 环境搭建 2015-07-24T09:00:00+00:00 skywang http://wangkuiwu.github.com/2015/07/24/nexus-01

本文介绍在ubuntu系统中,使用maven搭建局域网服务的方式。主要用到的工具有JDK、nexus。

目录
1. 背景介绍
2. nexus环境搭建
3. nexus管理页面
4. 参考链接

1. 背景介绍

maven是一个项目构建和管理的工具。通过搭建一个maven内部服务器,可以快速的复用一些公用的库。

下面,就开始介绍如何在ubuntu系统中搭建maven内部服务器nexus

2. nexus环境搭建

第1步 下载nexus安装包

点击下载nexus-2.11.4-01-bundle.tar.gz或者打开nexus官网,选择"NEXUS OSS"进行下载。如下图

img

这里下载的nexus安装包是:nexus-2.11.4-01-bundle.tar.gz

第2步 解压nexus安装包

解压nexus安装包到某个目录。nexus的解压目录没有要求,放在任何地方都可以。

$ tar -xvf nexus-2.11.4-01-bundle.tar.gz -C /home/skywang/opt

说明:解压nexus后,得到两个文件夹"nexus-2.11.4-01"和"sonatype-work"。
(1) nexus-2.11.4-01是nexus的主目录,所有运行程序和配置文件都在里面。
(2) sonatype-work是nexus的数据目录,nexus-oss中是运行过程的maven仓库数据。

第3步 配置nexus到环境变量中

在~/.bashrc中添加以下内容:

## nexus的路径
export NEXUS_HOME=/home/skywang/opt/nexus-2.11.4-01
## 将nexus的运行程序路径添加到默认环境变量中
export PATH=$PATH:$NEXUS_HOME/bin

第4步 运行nexus

配置了nexus之后,新开一个终端;使用nexus start启动nexus。

$ nexus start
Starting Nexus OSS...
Started Nexus OSS.

说明:如果nexus能正常启动,则配置nexus成功!
若要停止nexux,则运行$ nexus stop即可。

3. nexus管理页面

3.1 启动nexus管理页面

nexus启动之后,在浏览器输入nexus的地址http://IP地址:8081/nexus/可以打开nexus。

如果是打开本机的nexus,则在浏览器输入以下网址:

http://127.0.0.1:8081/nexus/

如果是打开服务器的nexus,则将"127.0.0.1"改为服务器的地址即可!

img

3.2 登录nexus

点击右上角的"login"界面,出现登录对话框。输入用户名/密码。

用户名:admin
密码:admin123

img

3.3 nexus界面简介

登录之后的nexus界面如下:

img

左边是控制栏区域,比较重要的一项是"Repositories",即仓库栏。

点击"Repositories"会打开右边窗口,显示全部的仓库。每一个仓库都有type、Health Check、Format、Policy、Repository Status和Repository Path等属性。说明一下比较重要的几个属性:

  1. type: 它表示仓库类型。主要有group、hosted、proxy、virtual四种类型。
      不同类型的仓库有不用的作用和工作模式,一般只需要关注group、hosted、proxy三种类型。由于nexus oss上面可以有多个maven仓库,但是maven这个工具要求使用groupId:artifactId:version这三个参数就能唯一确定一个项目,因此nexus oss使用group类型的仓库来决定nexus oss上各个maven仓库的优先级,以解决不同maven拥有相同项目的冲突。proxy类型的仓库其实只是个代理,用于代理其他服务器上的maven仓库。hosted类型是nexus oss自己所在服务器本地的maven仓库,也是我们本地主要使用的仓库类型。
  2. Policy: 它表示仓库的发布策略。一般都是Snapshot或Release。Snapshot表示是快照(临时)版本,而Release则表示发行版本。
  3. Repository Path: 它表示仓库的地址。在maven或gradle中引用该仓库就需要用到该地址。

每个仓库除了有属性之外,还有配置信息。配置信息有Browse Index、Browse Storage、Configuration、Routing等。其中,就最重要的Configuration来进行说明:
Deployment Policy: 有Allow Redeploy(允许部署)、Disable Redeploy(不允许部署)、Read Only(只读)三种模式。只有在Allow Redeploy模式下,我们才有权限可以将我们的项目发布到这个项目中。nexus oss默认已经建立了Releases和snapshots两个hosted仓库,我们检查一下配置就可以直接拿来用,当然你也可以自己建立hosted仓库。

4. 参考链接

  1. nexus官网
  2. 建立企业内部maven服务器并使用Android Studio发布公共项目
]]>
Android 触摸事件机制(五) 触摸事件示例5--ViewGroup没拦截但是却消费了触摸事件 2015-01-05T13:01:00+00:00 skywang http://wangkuiwu.github.com/2015/01/05/TouchEvent-Sample-05-ViewGroup

本文将通过示例演示触摸事件的传递流程。

注意:本文是基于Android 4.4.2版本进行介绍的!

目录
1. 示例概述
1.1. 示例简介
1.2. 示例结论
2. 示例源码
3. 运行结果

1. 示例概述

1.1 示例简介

本文的示例是在触摸事件示例(一)的基础上修改的。与触摸事件示例(一)相比,本文的示例对MyViewGroup中的onTouchEvent()进行了修改。修改后的onTouchEvent()代码如下:

@Override
public boolean onTouchEvent(MotionEvent event) {
    String actionName = Utils.getActionName(event);
    Log.d(TAG, "onTouchEvent(start) :"+actionName);
    // boolean ret = super.onTouchEvent(event);
    boolean ret = true;
    Log.d(TAG, "onTouchEvent( end ) :"+actionName+", ret="+ret);
    return ret;
}   

说明:修改后的MyViewGroup没有拦截触摸事件,但是消费了触摸事件。

1.2 示例结论

(01) MyViewGroup没有拦截却消费了ACTION_DOWN。由于MyViewGroup没有拦截ACTION_DOWN,因此,该事件会继续分发给MyViewGroup的子类MyView。由于MyViewGroup消费了ACTION_DOWN,因此该事件不会分发给MyActivity的onTouchEvent()。
(02) MyViewGroup没有拦截却消费了ACTION_DOWN。那么,MyViewGroup仍然可以接受到ACTION_MOVE和ACTION_UP这两种触摸触事件。但是对于MyView而言,由于MyView没有接受该事件;因此,MyView不会收到ACTION_MOVE和ACTION_UP。
试想想,如果MyView接受了ACTION_DOWN事件的话;它是否会收到ACTION_MOVE和ACTION_UP事件呢?答案是:会。感兴趣的读者可以自行验证。

Activity中ACTION_DOWN的流程图如下:

2. 示例源码

点击查看:触摸事件示例5的源码

3. 运行结果

3.1 ACTION_DOWN事件

点击MyView所在的区域,ACTION_DOWN相关的log如下:

D/##skywang-MyActivity( 2950): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2950): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2950): onInterceptTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2950): onInterceptTouchEvent( end ) :DOWN, ret=false D/##skywang-MyView( 2950): dispatchTouchEvent(start) :DOWN D/##skywang-MyView( 2950): onTouchEvent(start) :DOWN D/##skywang-MyView( 2950): onTouchEvent( end ) :DOWN, ret=false D/##skywang-MyView( 2950): dispatchTouchEvent( end ) :DOWN, ret=false D/##skywang-MyViewGroup( 2950): onTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2950): onTouchEvent( end ) :DOWN, ret=true D/##skywang-MyViewGroup( 2950): dispatchTouchEvent( end ) :DOWN, ret=true D/##skywang-MyActivity( 2950): dispatchTouchEvent( end ) :DOWN, ret=true

3.2 ACTION_MOVE事件

点击MyView所在的区域,ACTION_MOVE相关的log如下:

D/##skywang-MyActivity( 2950): dispatchTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2950): dispatchTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2950): onTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2950): onTouchEvent( end ) :MOVE, ret=true D/##skywang-MyViewGroup( 2950): dispatchTouchEvent( end ) :MOVE, ret=true D/##skywang-MyActivity( 2950): dispatchTouchEvent( end ) :MOVE, ret=true

3.3 ACTION_UP事件

点击MyView所在的区域,ACTION_UP相关的log如下:

D/##skywang-MyActivity( 2950): dispatchTouchEvent(start) :UP D/##skywang-MyViewGroup( 2950): dispatchTouchEvent(start) :UP D/##skywang-MyViewGroup( 2950): onTouchEvent(start) :UP D/##skywang-MyViewGroup( 2950): onTouchEvent( end ) :UP, ret=true D/##skywang-MyViewGroup( 2950): dispatchTouchEvent( end ) :UP, ret=true D/##skywang-MyActivity( 2950): dispatchTouchEvent( end ) :UP, ret=true

]]>
Android 触摸事件机制(五) 触摸事件示例4--ViewGroup拦截并消费触摸事件 2015-01-05T12:01:00+00:00 skywang http://wangkuiwu.github.com/2015/01/05/TouchEvent-Sample-04-ViewGroup

本文将通过示例演示触摸事件的传递流程。

注意:本文是基于Android 4.4.2版本进行介绍的!

目录
1. 示例概述
1.1. 示例简介
1.2. 示例结论
2. 示例源码
3. 运行结果

1. 示例概述

1.1 示例简介

触摸事件示例(三)中,MyViewGroup只是拦截了触摸事件,但是并没有消费触摸事件。
而在本文的示例中,MyViewGroup将在拦截触摸事件的基础上,同时消费触摸事件。

本文的示例仍然是在触摸事件示例(三)的基础上修改的。与触摸事件示例(三)相比,本文的示例对MyViewGroup中的onTouchEvent()进行了修改。修改后的onTouchEvent()代码如下:

@Override
public boolean onTouchEvent(MotionEvent event) {
    String actionName = Utils.getActionName(event);
    Log.d(TAG, "onTouchEvent(start) :"+actionName);
    // boolean ret = super.onTouchEvent(event);
    boolean ret = true;
    Log.d(TAG, "onTouchEvent( end ) :"+actionName+", ret="+ret);
    return ret;
}   

1.2 示例结论

(01) MyViewGroup拦截并消费了ACTION_DOWN。那么,该事件就不会分发给MyViewGroup的子类,也不会调用MyActivity的onTouchEvent()。
(02) MyViewGroup拦截并消费了ACTION_DOWN。那么,MyViewGroup就会接受到ACTION_MOVE和ACTION_UP这两种触摸触事件。而且对于ACTION_MOVE和ACTION_UP事件,不会再执行拦截操作,即不会调用MyViewGroup.onInterceptTouchEvent();而是直接调用MyViewGroup.onTouchEvent()对事件进行处理。
为什么在ACTION_MOVE和ACTION_UP中,没有执行MyViewGroup.onInterceptTouchEvent()呢?查看[ViewGroup中的dispatchTouchEvent()源码]即可得到答案,MyViewGroup在分发ACTION_MOVE时,没有执行"第3步"和"第5步",而是直接执行"第6步";进而调用View.dispatchTouchEvent()进行的处理。

Activity中ACTION_DOWN的流程图如下:

2. 示例源码

点击查看:触摸事件示例4的源码

3. 运行结果

3.1 ACTION_DOWN事件

点击MyView所在的区域,ACTION_DOWN相关的log如下:

D/##skywang-MyActivity( 2465): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2465): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2465): onInterceptTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2465): onInterceptTouchEvent( end ) :DOWN, ret=true D/##skywang-MyViewGroup( 2465): onTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2465): onTouchEvent( end ) :DOWN, ret=true D/##skywang-MyViewGroup( 2465): dispatchTouchEvent( end ) :DOWN, ret=true D/##skywang-MyActivity( 2465): dispatchTouchEvent( end ) :DOWN, ret=true

说明:很显然,ACTION_DOWN的流程如下:
(01) MyActivity收到ACTION_DOWN,进入MyActivity.dispatchTouchEvent()
(02) MyActivity.dispatchTouchEvent()对ACTION_DOWN触摸事件进行分发,将消息传递给MyViewGroup。即,进入MyViewGroup.dispatchTouchEvent()
(03) MyViewGroup.dispatchTouchEvent()会调用MyViewGroup.onInterceptTouchEvent()检查自己有没有对触摸事件进行拦截。即先进入MyViewGroup.onInterceptTouchEvent()。 (04) 紧接着,MyViewGroup会退出MyViewGroup.onInterceptTouchEvent()。此时,MyViewGroup.onInterceptTouchEvent()返回true。表示MyViewGroup拦截了该触摸事件。
(05) MyViewGroup在得知自己拦截了触摸事件之后,将触摸事件交给自己的onTouchEvent()进行处理,即进入MyViewGroup.onTouchEvent()
(06) 紧接着,MyViewGroup会退出MyViewGroup.onTouchEvent(),并返回true。表示MyViewGroup消费了该事件。
(07) 随后,MyViewGroup会退出MyViewGroup.dispatchTouchEvent(),并返回true。表示MyViewGroup接受了该触摸事件。
(08) MyActivity得知MyViewGroup接受了该触摸事件之后,就会退出MyActivity.dispatchTouchEvent(),并返回true。表示此次触摸事件被消费了。

3.2 ACTION_MOVE事件

点击MyView所在的区域,ACTION_MOVE相关的log如下:

D/##skywang-MyActivity( 2465): dispatchTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2465): dispatchTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2465): onTouchEvent(start) :MOVE D/##skywang-MyViewGroup( 2465): onTouchEvent( end ) :MOVE, ret=true D/##skywang-MyViewGroup( 2465): dispatchTouchEvent( end ) :MOVE, ret=true D/##skywang-MyActivity( 2465): dispatchTouchEvent( end ) :MOVE, ret=true

说明:由于MyViewGroup接受了ACTION_DOWN;因此,ACTION_MOVE事件会继续分发给MyViewGroup。不过此时,是直接调用onTouchEvent()进行消息处理,而不再需要执行onInterceptTouchEvent()来拦截消息。
为什么没有执行MyViewGroup.onInterceptTouchEvent()呢?查看[ViewGroup中的dispatchTouchEvent()源码]即可得到答案,MyViewGroup在分发ACTION_MOVE时,没有执行"第3步"和"第5步",而是直接执行"第6步";进而调用View.dispatchTouchEvent()进行的处理。

3.3 ACTION_UP事件

点击MyView所在的区域,ACTION_UP相关的log如下:

D/##skywang-MyActivity( 2595): dispatchTouchEvent(start) :UP D/##skywang-MyViewGroup( 2595): dispatchTouchEvent(start) :UP D/##skywang-MyViewGroup( 2595): onTouchEvent(start) :UP D/##skywang-MyViewGroup( 2595): onTouchEvent( end ) :UP, ret=true D/##skywang-MyViewGroup( 2595): dispatchTouchEvent( end ) :UP, ret=true D/##skywang-MyActivity( 2595): dispatchTouchEvent( end ) :UP, ret=true

说明:ACTION_UP的路径和ACTION_MOVE的路径一样!

]]>
Android 触摸事件机制(五) 触摸事件示例3--ViewGroup拦截但不消费触摸事件 2015-01-05T11:01:00+00:00 skywang http://wangkuiwu.github.com/2015/01/05/TouchEvent-Sample-03-ViewGroup

本文将通过示例演示触摸事件的传递流程。

注意:本文是基于Android 4.4.2版本进行介绍的!

目录
1. 示例概述
1.1. 示例简介
1.2. 示例结论
2. 示例源码
3. 运行结果

1. 示例概述

1.1 示例简介

触摸事件示例(二)中,MyView接受了触摸事件。
可是,在有的时候,我们希望MyViewGroup对触摸事件进行拦截;而不希望这个事件发送给MyView进行处理。此时,就需要重载GroupView的onInterceptTouchEvent()来拦截触摸事件。这就是本文要讲到的示例。

本文的示例仍然是在触摸事件示例(一)的基础上修改的。与触摸事件示例(二)不同,本文的示例仅仅只对MyViewGroup中的onInterceptTouchEvent()进行了修改。修改后的onInterceptTouchEvent()代码如下:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    String actionName = Utils.getActionName(event);
    Log.d(TAG, "onInterceptTouchEvent(start) :"+actionName);
    // boolean ret = super.onInterceptTouchEvent(event);
    boolean ret = true;
    Log.d(TAG, "onInterceptTouchEvent( end ) :"+actionName+", ret="+ret);
    return ret;
}   

这里的onTouchEvent()直接返回true,表示MyView消费了触摸事件。

1.2 示例结论

(01) MyViewGroup拦截了ACTION_DOWN,并没有消费该ACTION_DOWN。既然MyViewGroup拦截了ACTION_DOWN,那就意味着该事件就不会分发给MyViewGroup的子类。但是由于MyViewGroup没有消费该事件,即它并没有接受该事件;那么,ACTION_DOWN会继续查找其他对象来消费它自己,这也意味着该触摸事件仍然会发送MyActivity的onTouchEvent()。
如果MyActivity中有和MyViewGroup同级别的GroupView的话,在得知MyViewGroup拦截了ACTION_DOWN,却没有消费该ACTION_DOWN之后;MyActivity仍然能够向这个同级的GroupView分发消息。
(02) MyViewGroup并没有消费ACTION_DOWN,那么,MyViewGroup就不能接受到ACTION_MOVE和ACTION_UP这两种触摸触事件。至于MyViewGroup的子类MyView,就更加不可能接受到ACTION_MOVE和ACTION_UP了。

Activity中ACTION_DOWN的流程图如下:

2. 示例源码

点击查看:触摸事件示例3的源码

3. 运行结果

3.1 ACTION_DOWN事件

点击MyView所在的区域,ACTION_DOWN相关的log如下:

D/##skywang-MyActivity( 2371): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2371): dispatchTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2371): onInterceptTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2371): onInterceptTouchEvent( end ) :DOWN, ret=true D/##skywang-MyViewGroup( 2371): onTouchEvent(start) :DOWN D/##skywang-MyViewGroup( 2371): onTouchEvent( end ) :DOWN, ret=false D/##skywang-MyViewGroup( 2371): dispatchTouchEvent( end ) :DOWN, ret=false D/##skywang-MyActivity( 2371): onTouchEvent(start) :DOWN D/##skywang-MyActivity( 2371): onTouchEvent( end ) :DOWN, ret=false D/##skywang-MyActivity( 2371): dispatchTouchEvent( end ) :DOWN, ret=false

说明:很显然,ACTION_DOWN的流程如下:
(01) MyActivity收到ACTION_DOWN,进入MyActivity.dispatchTouchEvent()
(02) MyActivity.dispatchTouchEvent()对ACTION_DOWN触摸事件进行分发,将消息传递给MyViewGroup。即,进入MyViewGroup.dispatchTouchEvent()
(03) MyViewGroup.dispatchTouchEvent()会调用MyViewGroup.onInterceptTouchEvent()检查自己有没有对触摸事件进行拦截。即先进入MyViewGroup.onInterceptTouchEvent()。 (04) 紧接着,MyViewGroup会退出MyViewGroup.onInterceptTouchEvent()。此时,MyViewGroup.onInterceptTouchEvent()返回true。表示MyViewGroup拦截了该触摸事件。
(05) MyViewGroup在得知自己拦截了触摸事件之后,将触摸事件交给自己的onTouchEvent()进行处理,即进入MyViewGroup.onTouchEvent()
(06) 紧接着,MyViewGroup会退出MyViewGroup.onTouchEvent()。而MyViewGroup自身并没有消费该事件,因此MyViewGroup.onTouchEvent()返回false。
(07) 随后,退出MyViewGroup.dispatchTouchEvent(),并返回false。表示MyViewGroup没有接受该触摸事件。
(08) MyActivity得知MyViewGroup没有接受该触摸事件之后,就会调用进入MyActivity.onTouchEvent()
(09) 紧接着,MyActivity会退出MyActivity.onTouchEvent(),并返回false。表示MyActivity也没有消费触摸事件。
(10) 最后,MyActivity会退出MyActivity.dispatchTouchEvent(),并返回false。表示此次触摸事件没有被消费。

对比,触摸事件示例(一)中的ACTION_DOWN路径。在本示例中,MyViewGroup拦截了ACTION_DOWN,但是没有消费ACTION_DOWN事件。 (01) MyViewGroup拦截了ACTION_DOWN事件,意味着该事件不会继续往下分发。 (02) MyViewGroup没有消费该事件,意味着该事件就继续往上分发。

3.2 ACTION_MOVE事件

点击MyView所在的区域,ACTION_MOVE相关的log如下:

D/##skywang-MyActivity( 2371): dispatchTouchEvent(start) :MOVE D/##skywang-MyActivity( 2371): onTouchEvent(start) :MOVE D/##skywang-MyActivity( 2371): onTouchEvent( end ) :MOVE, ret=false D/##skywang-MyActivity( 2371): dispatchTouchEvent( end ) :MOVE, ret=false

说明:由于MyViewGroup拦截了ACTION_DOWN,却没有消费给ACTION_DOWN;导致ACTION_MOVE不会分发给MyViewGroup。既然没有分发给MyViewGroup,就更加谈不上分发给MyView了。

3.3 ACTION_UP事件

点击MyView所在的区域,ACTION_UP相关的log如下:

D/##skywang-MyActivity( 2371): dispatchTouchEvent(start) :UP D/##skywang-MyActivity( 2371): onTouchEvent(start) :UP D/##skywang-MyActivity( 2371): onTouchEvent( end ) :UP, ret=false D/##skywang-MyActivity( 2371): dispatchTouchEvent( end ) :UP, ret=false

说明:ACTION_UP的路径和ACTION_MOVE的路径一样!

]]>