阅读代码:AsyncTask

  • 阅读代码系列的文章都是我阅读代码过程中记录下来的只言片语,读者可能需要对照着代码来看才能看懂。
    如果对您要帮助我会非常的高兴!!
  • 看代码先了解这个段代码是如何用的非常重要,原因很简单,你只有知道熟知了它的用处,才能在看到它的实现时对此产生共鸣(难怪那样使用!!这样像是为了那样使用的!!原来是这样!!),如果要是以提问的形式写出来就更好了。

API-21

AsyncTask的使用

  1. 我们使用AsyncTask一般都是继承它,然后重新实现几个生命周期,然后实例化它并执行execute()
  2. onPreExecute() –> doInBackground()(新线程)–> onPostExecute()
  3. 当在doInBackground()里执行publishProgress()时在新线程里会调用onProgressUpdate

基本属性

  1. CPU_COUNT = Runtime.getRuntime().availableProcessors();
  2. CORE_POOL_SIZE, MAXIMUM_POOL_SIZE根据cpu数量算出 KEEP_ALIVE = 1
  3. ThreadFactory 使用了AtomicInteger计数线程个数,保证每个线程都有个唯一的名字
  4. BlockingQueue 待执行的任务队列
  5. ThreadPoolExecutor 并行的执行任务,用到了所有上面的东西来构造这个执行器
  6. SerialExecutor 串行执行器,对特定进程是唯一。 使用ArrayDeque,在执行时先包装runnable保证执行完这个任务后再执行下一个,然后使用offer添加到队列结尾,最后如果没有正在运行的任务则运行任务。scheduleNext是从任务队列里取一个任务然后放到THREAD_POOL_EXECUTOR里执行。
  7. 两个消息:MESSAGE_POST_RESULT 和 MESSAGE_POST_PROGRESS
  8. InternalHandler 内部处理器,接受上面两个消息,做相应的处理。使用了AsyncTaskResult,封装了asynctask实例和数据
  9. sDefaultExecutor = SERIAL_EXECUTOR; volatile???它有什么用真心不太了解!!
  10. 以上全是静态的。类所拥有的
  11. 真正的工作者WorkerRunnable<Params, Result> mWorker;实现了Callable,包含参数数组返回结果。
  12. FutureTask mFuture;??
  13. Status mStatus 状态
  14. enum Status: PENDING, RUNNING, FINISHED
  15. 两个原子变量:AtomicBoolean mCancelled, mTaskInvoked

构造函数

  1. 实现一个WorkerRunnable
    a. mTaskInvoked.set(true); 标识task被调用,这是个原子操作
    b. 设置优先级为后台
    c. postResult(doInBackground(mParams)); postResult会从sHandle取得message并传给它数据,然后发送给handler
  2. 实现一个FutureTask,在执行完成后postResultIfNotInvoked(get())?????

执行逻辑execute()

  1. execute → executeOnExecutor(使用默认的执行器) →
    1. 如果状态不是pending而是正在执行或完成,则报错,一个task只能执行一次  
    2. 设置为正在执行然后调用onPreExecute();  参数传给worker,执行器开始执行future。  
  2. 调用了默认的执行器的execute,就是那个串行执行器(虽然每个task只能执行一次,但是这个执行器是属于累的,也就是说所有的task都会被放到一个执行器一个线程上执行)
  3. 如前所述,串行器会将任务放到一个队列上,并且从头取任务执行。它就是序列化任务,真正执行的是THREAD_POOL_EXECUTOR 是他开启了新线程,并行工作
  4. 这时候THREAD_POOL_EXECUTOR执行的是什么呢?
    1. new Runnable() {r.run(); scheduleNext();}
    2. r 就是传进来的 Future,构造函数里初始化的那个,构造它时传进了worker

publishProgress()报告进度

  1. 向handler发送Progress信息,并传递数据AsyncTaskResult
  2. handler是在主线程的,所以就可以直接调用主线程的onProgressUpdate

想看更多关注我的blog:http://jinguoliang.github.io

2020年评论:
都忘记了自己曾经写过这个,要复习呀,要重复呀,那时候,没有这种能力,现在有了点

repo全解之自己搭建repo仓库

repo是什么

是什么: Repo是基于git的仓库管理工具,是一个python脚本
干什么: Repo整个很多的git仓库,可以做统一的上传,并且可以自动化部分Andoid开发流程

repo引导器

首先要说一下repo分为两部分, 一部分时一个名叫repo的python文件,另一部分是一个名叫repo.git这么一个git仓库.
而这个repo文件好像是一个引导器,一下命令下载它并设置它为可执行:

1
2
$curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo  
$chmod a+x ~/bin/repo

此时,你可以运行一下它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$~/bin/repo  #你也可以把它添加到PATH里
error: repo is not installed. Use "repo init" to install it here.
```

提示没有安装repo
如果再执行以下命令:

``` bash
$~/bin/repo help

usage: repo COMMAND [ARGS]

repo is not yet installed. Use "repo init" to install it here.

The most commonly used repo commands are:

init Install repo in the current working directory
help Display detailed help on a command

For access to the full online help, install repo ("repo init").

提示你repo没安装,可以使用repo init安装.并且只支持两个子命令.
这就说明,这个repo文件是一个引导器,或者是安装器.
它要如何安装呢?

repo.git gpg签名

我们就按照它的提示来操作,运行:

1
2
3
$repo init #假设将repo添加到了PATH下
Get https://gerrit.googlesource.com/git-repo/clone.bundle
fatal: manifest url (-u) is required.

在等了一会儿后显示如上,可以看到它是从google的gerrit来下载repo.git仓库,最后提示repo init的用法是必须指定一个manifest的url,我们下一小节介绍.
在执行完这个命令后,会在当前目录创建一个目录.repo,在它里面有个目录repo,是从repo.git仓库检出的代码. cd到.repo/repo,git status,会发现时clone来的
为什么会去那个地址检出代码呢?
答案肯定在那个repo脚本里,在里面会有两个变量

1
2
REPO_URL = 'https://gerrit.googlesource.com/git-repo'
REPO_REV = 'stable'

分别是repo.git仓库的url和检出的branch. 如果我们要想让repo来clone我们自己的repo.git,则修改上边的变量就可以了. 那如何如何自己创建repo.git呢? 这是另一个问题.
此时再执行repo help:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$repo help
usage: repo COMMAND [ARGS]
The most commonly used repo commands are:
abandon Permanently abandon a development branch
branch View current topic branches
branches View current topic branches
checkout Checkout a branch for development
cherry-pick Cherry-pick a change.
diff Show changes between commit and working tree
diffmanifests Manifest diff utility
download Download and checkout a change
grep Print lines matching a pattern
info Get info on the manifest branch, current branch or unmerged branches
init Initialize repo in the current directory
list List projects and their associated directories
overview Display overview of unmerged project branches
prune Prune (delete) already merged topics
rebase Rebase local branches on upstream branch
smartsync Update working tree to the latest known good revision
stage Stage file(s) for commit
start Start a new branch for development
status Show the working tree status
sync Update working tree to the latest revision
upload Upload changes for code review
See 'repo help <command>' for more information on a specific command.
See 'repo help --all' for a complete list of recognized commands.

哇,命令这么多了!!
此时我们只是有了repo工具,但是要想管理多个git,还需要一个清单,来说明要管理那些git,从哪里拉去等等. 这个任务要依赖manifest.git了,正如之前提到的,在repo init的时候,要通过-u url来指定manifest.git的位置.

manifests.git

使用如下命令:

1
$repo init -u https://android.googlesource.com/platform/manifests

就会初始化repo成功.
但是我们要管理自己的仓库,所以要建立一个自己的manifests.git.
这个manifests的内容最简单时是一个default.xml.
default.xml内容如下:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>

<manifest>
<remote name="local" fetch="git://localhost/" />
<default remote="local" revision="master"/>
<project path="hello" name="helo"/>
</manifest>

可以看到,根元素manifest,里边定义了remote,default,project.
remote可以多个,每个定义了一个远程拉取仓库, fetch是仓库的url, 可以使用”..”表示使用repo init -u url里的url
default则设置每个项目的默认仓库和默认分支
project定义了一个项目,它指明一个远程仓库,和clone到本地来后的目录名称. name为项目的远程仓库名,以上代码拉取的项目是git://localhost/helo

要管理的仓库

要管理的仓库是普通的git.
当以上一切准备完毕.
我们就可以

1
2
3
4
5
6
7
8
9
10
$repo sync
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From git://localhost/helo
* [new branch] master -> local/master

hello/: leaving master; does not track upstream
$ls
hello repo

远程仓库被拉取到了本地.

总结

其实吧, 我平时用了好多git库来存储笔记和项目, 我住的地方木有网络,然后我要从我的笔记和公司电脑同步数据,就只能通过u盘,于是就研究怎么clone本地的git仓库,当git仓库多了,我每次都要一个一个同步麻烦,所以就想到repo,因为之前做手机系统一直的时候用到过,然后就是捣鼓,当我最终弄出来的时候发现,没有review,我的提交根本递交不到我的git仓库里来,于是就无语了.不过呢,学到了东西.实际也是可以用它来同步的,只是有点杀鸡用牛刀了,不如写个简单的脚本.

一些问题

  1. repo只能用在Android吗?

参考

http://source.android.com/source/developing.html 使用repo
http://source.android.com/source/using-repo.html 使用repo
http://source.android.com/source/downloading.html#installing-repo 安装repo
http://project-management.diandian.com/post/2012-03-02/14242257 构建自己的repo.git
Git权威指南-第4篇-第25章-REPO
https://code.google.com/p/git-repo/source/browse/docs/manifest-format.txt?r=cd81dd6403fc8dbe6ec5920c517d9083902c3c1f 非常详细的介绍了manifest的格式

<翻译> 触摸模式(Touch Mode)

为Android设计和开发用户接口与普通的桌面环境有很大不同.因为Android运行在手机设备上,应用设计者和开发者必须处理大量的约束,而这些约束并不总是很明显.为了帮助你开发和设计更好的应用,我们正在发布一些关于用户接口的文章.在这个系列里,我们会向你介绍一些设计指导和工具,开发技巧并解释Android UI工具套件的基本原则.我们的目的很简单:帮助你去设计和开发好的用户体验.一开始,我想先介绍触摸模式,它是UI工具套件最重要的原则.
触摸模式view hierarchy的一种状态,它只受用户与手机交互的影响.单独来看,触摸模式是很容易理解的,它指示了用户最后一次交互是否是触屏操作.比如,当你使用G1手机时,用滚迹球选择一个widget会退出触摸模式,而当用手机点击屏幕上的按钮时又会进入触摸模式.当用户不在触摸模式时,可能会在滚迹球模式(tackball mode),导航模式(navigation mode)或者键盘导航(keyboard navigation).还有,与触摸模式直接相关的唯一的api是View.isInTouchMode().
听起来很容易对吗?奇怪的是,触摸模式是大幅简单而进入触摸模式的后果远远超过你的想象。让我们看看一些原因
##触屏模式,选项(Selection)和焦点(Focus)
为手机设计UI工具套件是困难的,因为它们要提供各种交互机制.有的设备只提供12个按键,有的会有触屏,有的需要触摸笔,有的既有触屏又有键盘.这样来看,第一款商业手机G1对Android开发者社区来说是一项福利,因为它提供了多种形式的输入:触屏,滚迹球和键盘.因为用户可以使用三种不同的机制来与应用交互,我们不得不努力解决所有可能出现的问题.
以ApiDemo为例,它显示一个文本项列表.用户可以通过滚迹球来导航这个列表,也可以通过手指来滚动这个列表.这时,选项是一个问题.如果我选择了列表顶部的一项,然后向上滑动列表,选项应该如何变化呢?它依然要在那一项上并滑出屏幕吗?这时,如果我又要用滚迹球来移动选项会发生什么?更糟糕的,如果我按下滚迹球来给予当前的选项来触发动作,而此时选项并没有显示在屏幕上,这时候又会发生什么?在仔细考虑后,我们决定移除选项(在触屏模式).
在触屏模式, 没有焦点和选项.一旦用户进入触屏模式,被选项不在被选中.相似的,当用户进入触屏模式,获取焦点的控件不再拥有焦点.下面的图片演示了当用户用滚迹球选择了一项后,再点击触屏,应用的反应.

has-selection
no-selection

为了让用户觉得更自然,当用户离开触屏模式时,框架知道怎样恢复选项/焦点.例如上边的例子,如果用户又使用滚迹球,先前的选项又会被选中.这就可以解释一个让开发者困扰的事情:他们创建的自定义view只有在滚动一次滚迹球后,才能接受按键事件.原因就是他们的应用处于触屏模式,需要使用滚迹球退出触屏模式,恢复焦点.
触屏模式,选项和焦点的关系意味着你不能确定选项/焦点是否一定存在.一个初学者常犯的错误是依赖ListView.getSelectedItemPosition().在触屏模式,这个方法将会返回INVALID_POSITION.你应该使用click listeners 或者 choice mode.

在触屏模式可获取焦点

现在,你知道在触屏模式焦点是不存在的,我必须声明这并不完全正确.Focus在触屏模式可以存在但是以一种非常特别的方式,我们叫它可获取焦点的.这种特殊的模式是为接受文本输入(如EditText)或者具有过滤功能(如ListView)的控件创造的.这就是为什么在向文本框输入文本之前不必首先用滚迹球或手指选中它.当用户点击屏幕,如果应用没有在触屏模式将会进入触屏模式.在进入触屏模式的过程中会发生什么取决于用户点击了什么和焦点在哪.如果用户点击了一个在触屏模式可获取焦点的控件,这个控件将会获取焦点.否则,现在获取焦点的控件如果在触屏模式不能获取焦点就会失去焦点.例如,在下边的图片中,当用户点击屏幕时,输入框会获取焦点.

text-field

在触屏模式是否可以获取焦点是view的一个属性可以通过代码或者xml设置,设置时应该谨慎,因为它破坏了与Android正常行为的一致性.游戏和全屏的地图是一个设置这个属性的很好的例子.
下边是一个需要在触屏模式获取焦点的控件的例子.当用户点击AutoCompleteTextView的Suggestion时,焦点依然在输入框.

search01

Android初学者经常会通过设置触屏模式下的获取焦点能力来”修复”不显示选项/焦点.我们希望你考虑清楚.如果使用不正确,你的应用会与系统行为不同,让用户非常不习惯.Android框架包括了所有你需要的工具来处理用户交互,你完全可以不在触屏模式设置控件的可获取焦点性.比如,简单的使用choice mode,而不是让ListView保持它的选项.如果Android框架不适合你的需求,你可以向我们提意见或者提交你的patch.
##触屏模式的备忘录
应该这样:

  • 与核心应用保持一致
  • 如果你想保持选中状态,使用它们适当的特性(radio button, check box, ListView的选项模式)
  • 如果是写游戏,使用(focusable in touch mode)

不应该:

  • 不要在触屏模式保持选中状态或者保持焦点.

<转载> Android 学习资源

转载自 http://www.zhanghongyang.com/2015/03/30/2015-03-30-android-learn-resources/
但是也加入了我子集的更改.吼吼!!(我拷贝了内容,然后编辑成markdown,逐个添加url :( )

国外教程网站

Android Developers Blog 不解释
vogella很不错的网站,免费的,包含android的教程也比较全面,并且教程中经常引用大牛blog,会有很多意外发现。代码资源有提供,但是不是很好找。 非常推荐
tutorialspoint非常适合入门,提供基本所有的基础教程,并且N多的例子。除了支持在线学习外,还提供基本教程和进阶教程的pdf下载。(ps:虽然Pdf可以点击下载,但是人家还是希望您能付款的。) 非常推荐
tutsplus每篇文章质量都非常高~~ 非常推荐
codepath
基本包含了日常开发中所有用到的东西,正如: We don’t waste time with the “theoretical approach” you might get from a book. We cover exactly the things we use every day as we are developing apps for contracts.他们的宗旨是:mission to change the way engineers learn new technologies。同时提供了问答的支持,也欢迎大家的加入。
coderzheaven
覆盖各种教程,关于Android基本时案例驱动的方式。 非常推荐
thenewcircle
貌似是个培训机构,多数是收费的,不过仍然有一些free resources值得你去挖掘。
coreservlets
虽然主打不是android,但是android的教程也是相当不错的,更好的是,教程都提供pdf、ppt、源码的下载。期待它的更新~ 非常推荐
Droid-Blog
Droid-Blog.net offers about 27,000 impressions to a highly targeted audience of Android developers looking for ways to monetize their applications. There is only one ad space on the top right on the whole blog which guarantees maximum attention for your ad. - See more at: http://droid-blog.net/become-a-sponsor/#sthash.roDmfOb9.dpuf
coursera.org
Coursera致力于普及全世界最好的教育,与顶级 大学和机构合作,向所有人提供免费课程。当然了,关于Android课程也不少。
commonsware.com
CommonsWare’s mission is to help people and organizations work better together through cooperation, whether that be in the fields of software development, community governance, or anywhere else. CommonsWare provides books, software, and services in fulfillment of that mission.
http://android.amberfog.com/
Just another Android developers blog 非常推荐
anddev
Android Development Community | Android Tutorials 非常推荐

2、国外个人博客

http://jakewharton.com/blog
作者:Jakewharton
看名字就知道,完全不需要介绍。
http://www.curious-creature.com/
作者:Romain Guy
我还是觉得不用介绍。
http://cyrilmottier.com/
作者:Cyril Mottier
我还是觉得不用介绍。
http://blog.stylingandroid.com/
作者:Mark Allison
a software developer with over 30 years’ experience, and over 4 years’ Android development experience. I run Styling Android Limited, an Android software development consultancy.
http://blog.danlew.net/
作者:Daniel Lew
文章数量相当客观,大多数都是一些tips,非常值得学习。
http://www.androidhive.info/
作者:Ravi Tamada
android高质量文章很多,不过也会有很多其他方面的文章,数量堪比教程网了。
http://loseyourmarbles.co/about-me/
作者:Chris Nash
My interests in software development and modern video gaming will form a large part of this blog 。
http://www.androiduipatterns.com/
作者:juhani@fatrobot.io
working for Fat Robot as Partner / CTO.
http://www.grokkingandroid.com/
作者:Wolfram Rittmeyer
I have been developing with Java for a long time and have started developing Android applications in 2010.
http://geekyouup.blogspot.com/
作者:Rich Hyndman
就职于 Google .

3、值得逛的网站

slideshare
SlideShare世界上最大的幻灯片分享社区。当然了关于Android的ppt也是非常的多,在作者允许的情况下都可以下载,当然了,如果不允许也是支持在线看的。在这里你基本可以找到各种presentation的ppt。例如:google io 什么的。
androidweekly.net
Android Weekly is a free newsletter that helps you to stay cutting-edge with your Android Development.非常值得订阅。
developer.android.com
oh , no reason!
大致整理了这么多,多数需要翻墙才能看,以上评价神马的大家当作建议,都是我的个人观点。如果大家有什么好的资源提供,欢迎留言!

2020年加注:
从来没看过

这山望着那山高

首先解释一下题目,“这山望着那山高”,就是说,你爬到一个山的山顶发现这个山不如旁边那座山高,于是就后悔,就像去爬那座山,是一个比喻。一般指工作不安心,总换工作。

现在我的工作是Android应用开发,负责一款亲子游玩软件的开发。

今天在看人家博客的时候发现自己对自己项目的一些东西并不怎么了解,于是想到了这个词语。为什么会想到呢?

我的第一份工作是做Android框架移植方面的工作。现在想想当时是整天潜在代码的海洋里,因为代码量太大了,于是,当时感觉这是无法完成的。所以就想到要去做软件开发,游在一个小软件的池塘里,应该可以将其完全掌控了吧?

现在应用已上线,工作也不是太忙了,我本来也应该把整个应用都掌控于胸了,但事实是没有。

现在究其原因,就是题目中的那句话“这山望着那山高”。不仅仅是工作,粒度更小一点,工作中的事情也是如此。这句话的意思其实就是没恒心,没毅力。此时发现应该纠正一开始对这个词的解释,不是爬到山顶,而是在爬的过程中,累了,于是才有这想法,“那座山更高,费一次劲,为什么不爬个高的?”。

Android框架完全可以分成更小的模块,而更小的模块还可以分成更小的模块。这样分下去,直到一天可以看完一个小模块,一上午可以看完一个小模块,一小时可以看完一个小模块。在看小模块的同时而不忘全局。

分而治之各个击破

这个词高中数学老师整天挂在嘴边。我当时也是对其甚是相信。
不过,它需要需要另一项技能与其相佐,恒心

2020年3月1日评论:
分而治之各个击破,没毛病,更好的是抓西瓜,抓根本,抓背后的概念,比如这个亲子软件,其实就是个信息客户端,包括后台和客户端。主要涉及的技术数据存储,服务器接口请求,AndroidSdk的使用,这样从上往下逐渐细分,实现既可以关注全剧,又能各个击破。

Android如何绘制Views(翻译)

当一个Activity获得焦点时,会被请求去绘制它的布局.Android 框架回去处理绘制的过程,但是Activity必须提供布局的层次结构(Hierarchy)的根节点。

绘制是从层次结构的根节点开始。根节点被请求去测量(measure)和绘制布局树。绘制过程是遍历这棵树然后绘制与无效区相交的每一个View。每一个ViewGroup负责请求每个孩子被绘制(使用 draw()方法),每个View负责绘制自己。因为这棵树是按顺序遍历的,这意味着父亲将会先于或者后于他们的孩子绘制,兄弟之间按照他们在这棵树出现的先后顺序绘制。(译者:这里设计到数据结构里的树的遍历)

绘制布局的过程分成两遍:一个测量的过程和一个布局的过程。测量的过程是通过measure(int, int)实现,自顶向下遍历View.在递归的过程中,每一个View把自己的尺寸规格向下传递。测量完后,每个View都存储了自己的测量结果。布局的过程通过方法layout(int, int, int, int)实现,也是自顶向下的过程。在这个过程中,每一个父view负责根据测量过程中的大小来放置子view。

当一个View对象的measure()*方法返回后,它的 getMeasuredWidth()getMeasuredHeight()的值必定被设置好了,根据上文的绘制过程,它的后裔也应如此(递归)。一个View对象的测量的宽度和高度受父View的限制。这保证了在测量完成后,所有的父View都能接受子View的测量结果。一个父View可能会调用多次子View的measure()方法。比如,父View会先用unspecified dimensions对每一个子View测量一次来找出每个子View想要的尺寸。然后如果所有子View的非限制的尺寸和太大或者太小时,父View会再次调用measure()*。(也就是说,如果子View自己不能获得自己需要的尺寸,父View就会在布局过程中对其进行干涉施加限制)。

测量的过程使用了两个类来传递尺寸:ViewGroup.LayoutParamsMeasureSpec
子View使用ViewGroup.LayoutParams来告诉父View如何测量和放置自己。ViewGroup.LayoutParams是个基类,只描述了View的宽高,每一个尺寸的值可以使用如下一个:

  • 一个精确的值
  • MATCH_PARENT 标识子View想要同父View一样大
  • WRAP_CONTENT 标识子View要求尺寸干好包含内容就可以(包括padding)

ViewGroup的不同的子类会定义自己的LayoutParams继承自ViewGroup.LayoutParams。比如,RelativeLayout有自己的LayoutParams,能够让子View横向或竖向居中。

MeasureSpec 对象用来从父View向子View传递要求。可以是如下三种模式:

  • UNSPECIFIED 父View通过它来确定子View想要的尺寸。比如,一个LinearLayout以高度为UNSPECIFIED,宽度为240来调用measure(),目的是要得到子View的高度,并且设置它的宽度为240px。
  • EXACTLY 精确设置一个尺寸,子View必须保证自己和后裔都要使用这个精确的值
  • AT MOST 设置一个最大值,子View必须保证自己和后裔不能超过这个尺寸

未完待续,敬请期待!!
Fri Jun 19 00:08:56 CST 2015 翻译完了,但略显生硬,应该润色一下。

Jenkins配置总结

背景

Bash

bash是类unix系统上的一个shell,即系统的壳,它包裹了系统,给用户提供了一个接口去与系统交互。为了做一些自动化工作,有了bash脚本,通过脚本,可以做一系列的与系统的交互

Jenkins

为了让自动化更加方便,出现了Jenkins。它是一种持续集成工具。通过配置,仅需一键,或者少许配置,或者在特定的时间自动运行构建工程,当然不限于构建工程。

Jenkins配置过程

1. 安装

  1. 官方下载jenkins.war
  2. 两种方式安装
  • 直接运行命令:
    java -jar jenkins.war
  • 使用servlet容器,如tomcat

注意

  • 要装新版本,旧版本太恶心了,我用apt-get安装的,安装倒是方便,但是装插件差点没哭了。
  • 我们当然要使用简单的命令了,java -jar jenkins.war 。
  • log信息会输出到终端,但可以通过参数制定输出的文件
  • 会在用户目录下建一个.jenkins作为它的home目录
  • 开机启动是个问题,考虑到这个问题,不如随web 服务器启动来的方便

2. 配置

详细过程不想说了,网上有太多,只说说我觉的比较重要的吧。

  1. Jenkins支持插件,有些功能是需要插件支持的,如git配置
  2. 我用的比较多的插件是多选框,默认的配置控件没有,需要安装Extended Choice Parameter plugin
  3. 旧版本下载插件超恶心
  4. 我们最好给jenkins创建个用户,使用这个用户运行jenkins,这样安全
  5. 配置git时,可能会报host key verify failed。先切到jenkins用户,生成密钥,添加到git服务器,然后执行git clone 测试通过了再配置。
  6. 缺少java装java,缺少ant装ant

Bash脚本

人家jenkins提供了调用构建工具的步骤,但我一般都不用,都在脚本里做了。一般就是配置一下参数配置,再写个脚本根据参数执行构建就是了。

以下是一些功能点:

  • 模式替换
1
sed  "/.*UMENG_CHANNEL.*/ s/\(.*value=\"\)[^\"]\+\(\".*\)/\1$newChannel\2/ " $ManifestFile > $ManifestFile.bak

这个语句的意思是在包含UMENG_CHANNEL的一行,将value=””里引号里的内容替换替换称$newChannel
下面来详细说明一下:

  1. sed语句, 前一部分选出匹配的行,后一部分是对这一行的操作。这里,后一部分是一个替换命令,格式为s/old/new/
  2. 正则表达式, 上面语句使用了组,即用()标识一个组,使用\NUM来引用之前标识出的组
  3. 具体的sed用法还是自己搜吧,这里只是分解一下比较复杂的内容
  • 分割一个字符串并遍历 这个语句有点复杂,不知道有没有简单的。
1
2
3
4
5
while IFS=',' read -a ADDR; do  # IFS为分隔符, 把$ChannelIds值作为标准输入,用read读取,
for i in "${ADDR[@]}"; do
#这里的$i就是$Channels通过,分割后的每一个channel
done
done <<< "$Channels"

1.<<<
这叫Here Strings,就是说她后面是一个字符串,不管是变量还是什么,都被作为标准输入
还有个<<,叫Here Documents,这特性很棒,他的格式这样:

1
2
3
<<[-]word
here-document
word

word是一个标识符,来表示here-document的开始和结束。 如果word被引号包着,则后面的here-doc不进行扩展,即变量不会替换成值
here-document会被作为标准输入,换行会被保留

2.IFS=’,’ read -a arr
read 从标准输入读数据存到arr这个变量里,-a标识读取的是数组,IFS这个环境变量标识读取的分隔符
bash的数组简直就是个大坑!!!
虽然之前看过一本Bash的书,但是还是不怎么领会精髓,感觉特别多的坑


官方定义:

Jenkins做两个工作:

  1. 持续构建和测试软件项目
  2. 监督外部执行的工作,如cron jobs或者procmail jobs。

最佳实践

当我真正开始爱自己

卓别林

当我真正开始爱自己
我才认识到,所有的痛苦和情感的折磨,
都只是提醒我:活着,不要违背自己的本心。
今天我明白了,这叫做
【真实】。

当我真正开始爱自己
我才懂得,把自己的愿望强加给人,
是多么的无理,就算我知道,时机并不成熟,
那人也没有做好准备,
就算那个人就是自己,
今天我明白了,这叫做
【尊重】。

当我开始爱自己,
我不再可求不同的人生,
我知道任何发生在我身边的事,
都是对我成长的邀请,
如今,我称之为,
【成熟】。

当我开始真正爱自己,
我才明白,我其实一直都在正确的时间,
正确的地方, 发生的一切都恰如其分。
由此我得以平静,
今天我明白了,这叫
【自信】。

当我开始爱自己,
我不在牺牲自己的自由时间,
不再去勾画什么宏伟的明天。
今天只做有趣和快乐的事,
做自己热爱,让心欢喜的事,
用我的方式,以我的韵律。
今天我明白了,这叫做
【单纯】。

当我开始真正爱自己,
我开始远离一切不健康的东西。
不论是饮食和人物, 还是事物和环境,
我远离一切让我远离本真的东西。
从前我把这叫做“追求健康的自私自利”,
但今天我明白了,这叫做
【自爱】。

当我开始真正爱自己,
我不再总想着永远正确,不犯错误。
我今天明白了,这叫做
【谦逊】。

当我开始真正爱自己,
我不再继续沉溺于过去,
也不再为明天而忧虑,
现在我只活在一切正在发生的当下,
今天,我活在此时此地,
如此日复一日。这叫做
【完美】。

当我开始认真爱自己,
我明白,我的思虑让我变得贫乏和病态,
但当我唤起了心灵的力量,
理智就变成了一个重要的伙伴,
这种组合我称之为,
【心的智慧】

我们无须再害怕自己和他人的分歧,矛盾和问题,
因为即使星星有时也会碰在一起,
形成新的世界,
今天我明白, 这就是【生命】!

软件工匠

软件工艺宣言

提高标准

作为有理想的软件工匠,我们一直身体力行,提升专业软件开发的标准,并帮助他人学习此工艺。

通过这些工作,我们建立了如下价值观:
不仅要让软件工作,

更要 精益求精

不仅要响应变化,

更要 稳步增加价值

不仅要有个体与交互,

更要 形成专业人员的社区

不仅要与客户合作,

更要 建立卓有成效的伙伴关系

也就是说,左项固然值得追求,右项同样不可或缺。

gitignore

.gitignore 指定忽略的文件

模式匹配

  1. 空行忽略,只是增加可读性
  2. #开头 注释
  3. 空字符会被忽略
  4. !取反后面的模式。匹配模式的被跟踪。考虑到性能,git不会列出被忽略的目录的文件,所以包含多个文件的模式不起作用。
  5. 如果模式以/结尾,将只匹配目录。 如foo/将匹配目录foo和foo下的所有
  6. 如果模式没有/,git会检测相对于.gitignore的路径(如果没有.gitignore,相对于项目根目录)
  7. 其他的,按照shell glob模式匹配
  8. 以/开头的模式匹配路径的开头。如 /*.c 匹配 cat-file.c 而不匹配mozilla-sha1/sha1.c

**有几种特殊含义

  1. **/foo 匹配 任意的文件或目录foo 同 模式 foo
  2. /** 匹配里边所有东西
  3. a/**/b 匹配
  4. 其他都无效