简单谈谈计算机网络

RESTful API 设计介绍 - 曾铭

WHAT

  • API 概念
  • 其它方案 SOAP 等
  • HTTP 无状态
  • RESTful 概念 REpresentational State Transfer 表征性状态传输
  • 复用 HTTP 本身的协议定义
  • 带来的好处:通用,动词,code,缓存,安全

例子

1
2
3
4
5
6
BAD
/getProduct

/addProduct
/deleteProduct

/listProducts
/productShop?productId=1
  • 对单一实体的重复
  • 多个实体对操作的重复
  • 实体之间逻辑接口的重复定义
1
2
3
4
5
6
7
8
9
10
11
GOOD
GET /products : will return the list of all products
GET /products/4 : will retrieve product #4
POST /products : will add a product to the collection
PUT /products/4 : will update product #4
DELETE /products/4 : will delete product #4

GET /products/4/shop
GET /users/3/favorite_schools
POST /users/3/favorite_schools
PUT /users/3/favorite_schools/5
  • 好的 API 定义清晰,可预期。

总结

  • 重复的实现或设计,嗅嗅不好的味道
  • 重复制造轮子,而不是重复发明轮子 (如用户授权,加密,缓存等)
  • RESTful 不仅仅适用于 APP,重点是 C/S
  • 各端实现:参考覃超的知乎回答

IP网段划分 - 王胜

三大类IP段

  • A类地址

    • 第1字节为网络地址,其他3个字节为主机地址。另外,第1个字节的最高位固定为0。
    • 地址范围:1.0.0.0到126.255.255.255。
    • 默认子网掩码:255.0.0.0,一个子网最多可以容纳1677万多台电脑。
    • 保留地址:127.0.0.0到127.255.255.255是保留地址,用做循环测试用。
    • 私有地址:10.0.0.0到10.255.255.255。【0000 1010】
  • B类地址

    • 第1字节和第2字节为网络地址,其他2个字节为主机地址。另外1个字节的前2位固定为10。
    • 地址范围:128.0.0.0到191.255.255.255。
    • 默认子网掩码:255.255.0.0 一个子网最多可以容纳6万台电脑。
    • 保留地址:169.254.0.0到169.254.255.255是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器,这时你将会从169.254.0.1到169.254.255.254中临时获得一个IP地址。
    • 私有地址:在B类地址中,172.16.0.0到172.31.255.255是私有地址。
  • C类地址

    • 第1字节、第2字节和第3个字节为网络地址,第4个字节为主机地址。另外第1个字节的前三位固定为110。
    • 地址范围:192.0.0.0到223.255.255.255。
    • 默认子网掩码 255.255.255.0 一个子网最多可以容纳254台电脑。
    • 私有地址:192.168.0.0到192.168.255.255是私有地址。

两个特殊地址

  • 0.0.0.0 全网地址,三界之外的收容器
  • 255.255.255.255 广播地址

OSI七层模型详解 - 吴明

OSI七层模型详解

  • 物理层:
    • 相关协议:IEEE802.2,Ethernet v.2,Internetwork
  • 数据链路层
    • 相关协议:MPLS,XTP,DCAP
  • 网络层
  • 传输层
    • 相关协议:EGP,NHRP
  • 会话层:
  • 表示层:
  • 应用层:

网络分层协议模型 - 张超耀

网络分层协议模型

  • 根据 TCP/IP协议簇的协议来命名

    • 应用层  数据   泛指应用层使用的
    • 传输层  数据段     传输层
    • 网络层  数据包     网络层
    • 链路层  帧       网络接入层
    • 物理层  比特(位)    通过介质实际传输数据时使用的
  • OSI七成协议模型

    • 应用层:例如HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP
    • 表示层:例如XDR、ASN.1、SMB、AFP、NCP
    • 会话层:例如ASAP、TLS、SSH、ISO 8327 / CCITT X.225、RPC、NetBIOS、ASP、Winsock、BSD sockets
    • 传输层:例如TCP、UDP、RTP、SCTP、SPX、ATP、IL
    • 网络层:例如IP、ICMP、IGMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25
    • 数据链路层:例如以太网、令牌环、HDLC、帧中继、ISDN、ATM、IEEE 802.11、FDDI、PPP
    • 物理层:例如线路、无线电、光纤
  • 分层的好处:

    • 各层之间是独立的
    • 灵活性好
    • 结构上可分割开
    • 易于实现和维护
    • 能促进标准化工作

协议模型:

包装数据包的过程

  • TCP传给IP的数据单元称作TCP报文段或简称为TCP段(TCP segment),传给网络接口层的数据单元称作IP数据报(IPdatagram).通过以太网传输的比特流称作帧(Frame)

分用即解包的过程

不同层直接协议关系


TCP/IP三次握手与四次挥手 - 李仙鹏

TCP/IP三次握手与四次挥手

引用自图解 TCP/IP 协议&version=11020012&pass_ticket=Mh3kdFcxrCoIa0yIg1d7eLqJGuQkBQLzt2YIYx5poC%2BLzaWWMRZ5D1Vl6Pobd8ui)


计算机网络安全 - 杨志平

2015网络安全事件

  • 携程网内部员工误删除代码 网站整体宕机12小时
  • 支付宝机房电缆被挖断 部分区域服务中断
  • 网易骨干网遭攻击 百万用户无法打游戏
  • 海康威视被黑客植入代码 导致被远程监控

敏感数据(账号、密码等)

  • 账号密码(post明文显示)
  • 重要资源数据(防爬虫)
  • 多重账号威胁(网络账号通用)
  • 通讯协议破解(iMessage)

网络传输加密

  • 数据加密算法

    • 对称式加密技术 (加密-解密)
      • DES(Data Encryption Standard)

        数据加密标准,速度较快,适用于加密大量数据的场合。

      • 3DES(Triple DES)

        是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。

      • AES(Advanced Encryption Standard)

        高级加密标准,是下一代的加密算法标准,速度快,安全级别高;

- 非对称式加密技术(公钥-私钥)
    - RSA
    >是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
    - DSADigital Signature Algorithm    >数字签名算法,是一种标准的 DSS(数字签名标准);
    - ECCElliptic Curves Cryptography    >椭圆曲线密码编码学。

- 散列算法 (不可逆)
    - MD5Message Digest Algorithm 5    >是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。
    - SHASecure Hash Algorithm    >可以对任意长度的数据运算生成一个160位的数值;

3个著名加密算法(MD5、RSA、DES)的解析

简单加密演示

  • 简单位移式加密(经典:凯撒加密)
1
2
3
4
5
6
“恺撒密码”据传是古罗马恺撒大帝用来保护重要军情的加密系统。它是一种替代密码,通过将字母按顺序推后起3位起到加密作用,
如将字母A换作字母D,将字母B换作字母E。据说恺撒是率先使用加密函的古代将领之一,因此这种加密方法被称为恺撒密码。
假如有这样一条指令:
RETURN TO ROME
用恺撒密码加密后就成为:
UHWXUA WR URPH
  • 置换加密
1
2
3
4
5
6
7
8
9
10
11
12
令明文m=m1,m2,...mL。令置换矩阵所决定的置换为pi,则加密置换c=Ek(m)=(c1,c2,...cL)=mpi(1),mpi(2),...,mpi(L)
解密置换
d=Dk(c)=(cn^-1(1),cn^-1(2),...cn^-1(L))
例,置换密码。给定明文为the simplest possible transposition ciphers,
将明文分成长为L=5的段,
m1=thesi, m2=mples m3=tposs m4=iblet,
m5=ransp, m6=ositi m7=oncip m8=hersx
最后一段长不足5,加添一个字母x。将隔断的字母序号按下述置换矩阵进行换位:
Ek= 0 1 2 3 4
3 0 4 2 1
得到密文如下
STIEH EMSLP STSOP EITLB SRPNA TOIIS IOPCN SHXRE

Alamofire文档阅读 - 潘君

AFNetworking的继承者

摘录自Alamofire 官方文档

Feature

  • Chainable Request / Response methods
    链式 request / response
    Complete Documentation
1
2
3
4
5
6
7
8
// Response handlers can even be chained:
Alamofire.request(.GET, "http://httpbin.org/get")
.responseString { _, _, string, _ in
println(string)
}
.responseJSON { _, _, JSON, _ in
println(JSON)
}
  • URL / JSON / plist Parameter Encoding
    除了以上几种 还可以自定义
    Alamofire provides built-in response serialization for strings, JSON, and property lists, but others can be added in extensions on Alamofire.Request.

    • Upload File / Data / Stream / MultipartFormData
      多种文件上传方式
  • Download using Request or Resume data

  • Authentication with NSURLCredential

  • HTTP Response Validation

  • Progress Closure & NSProgress

  • cURL Debug Output
  • Comprehensive Unit Test Coverage

某些点

  • url编码
    GET
    1
    2
    3
    GET Request With URL-Encoded Parameters
    Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
    // http://httpbin.org/get?foo=bar

POST

1
2
3
4
5
6
7
8
9
10
11
12
let parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]

Alamofire.request(.POST, "http://httpbin.org/post", parameters: parameters)
// HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3

  • 转object
    Generic Response Object Serialization

  • 校验

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Manual Validation

    Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
    .validate(statusCode: 200..<300)
    .validate(contentType: ["application/json"])
    .response { _, _, _, error in
    println(error)
    }
    Automatic Validation

    Automatically validates status code within 200...299 range, and that the Content-Type header of the response matches the Accept header of the request, if one is provided.

    Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
    .validate()
    .response { _, _, _, error in
    println(error)
    }
  • 方便打印
    Printable

1
2
3
4
5
let request = Alamofire.request(.GET, "http://httpbin.org/ip")

println(request)

// GET http://httpbin.org/ip (200)

DebugPrintable

1
2
3
let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])

debugPrintln(request)
  • 支持暂停/恢复/取消
  1. suspend(): Suspends the underlying task and dispatch queue
  2. resume(): Resumes the underlying task and dispatch queue. If the owning manager does not have startRequestsImmediately set to true, the request must call resume() in order to start.
  3. cancel(): Cancels the underlying task, producing an error that is passed to any registered response handlers.
  • 自定义response serializer

微信公众号开发

微信 Hello, world! - 曾铭

  • 微信公众号实现查询通讯录功能
  • 代码在这:Github 欢迎 pull-request!
  • 扫码关注,我们可以一起持续改进

微信公众号介绍 - 雨竹

  • 见附件

微信开发介绍 - 竟成

  • 见附件

微信JS SDK与微信浏览器介绍 - 李波

  • 见附件

带你装逼带你飞 - 吴明

  • 几个概念

    1. 公众号:
      微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字、图片、语音、视频的全方位沟通、互动 。形成了一种主流的线上线下微信互动营销方式。
      1. 订阅号:对个人
      2. 服务号:对公司
      3. 企业号:
  • 装B之路

    1. 服务号,订阅号注册。
    2. 微信公众号菜单:扫微信公众号
    3. 微信简单原理
    4. 简单开发

      -  [测试公众号](http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login)
      -  [微信公众平台接口调试工具](http://mp.weixin.qq.com/debug)
       -  [接口文档](http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html)
       -  用到的接口:
        - [获取access token](http://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html)
            - 传appid(wx0162d0ace2953263)
      

      和secret(b608757fe7f76667d2fb287b77218196)

          - 返回
          
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
          		<pre><code>200	OK
      Connection: keep-alive
      Date: Fri, 17 Jul 2015 09:39:35 GMT
      Server: nginx/1.8.0
      Content-Type: application/json;encoding=utf-8
      Content-Length: 144
      {
      "access_token":"OzZY0UIVI3nhVvNW9uUz8f9EQOnVgcqDr3HXlqYJjQGGEZrmdx2lJd_W8rTP78Q9pYbycTJGyzyZ3csse3ACK2VzfZ-ilmmPWUq8Jh2X1wU",
      "expires_in": 7200
      }
      </code></pre>
      - [自定义菜单创建接口](http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html) - 传上面的access_token和创建菜单json格式
      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
      27
      28
      29
      30
      31
      32
       	  		{
      <!--一级菜单 -->
      "button": [
      {
      "type": "view",
      "name": "51offer",
      "url": "http://www.51offer.com/"
      },

      {
      <!--一级菜单 -->
      "name": "移动",
      "sub_button": [
      {
      <!--二级菜单 -->
      "type": "view",
      "name": "blog",
      "url": "http://51offer.github.io/"
      },

      {
      "type": "view",
      "name": "github",
      "url": "https://github.com/51offer/public-docs/wiki"
      }

      ]

      },

      {
      "type": "click",
      "name": "我",
      "key": "me"
      }

      ]

      }

      - 返回
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      200	OK
      Connection: keep-alive
      Date: Fri, 17 Jul 2015 09:40:01 GMT
      Server: nginx/1.8.0
      Content-Type: application/json; encoding=utf-8
      Content-Length: 27
      {
      "errcode": 0,
      "errmsg": "ok"
      }
      • 查看微信公众号的菜单
      • end

本地调试 - 潘君

微信支付流程 - 柳晓

  • 见附件

移动组周技术分享-研发路上的那些事儿

心酸研发路 - 杨志平

  • 大版本发布周期过长(原因:团队专业有限,探索前进,频繁修改),导致没有什么机会思考、设计,人也拖的身心疲惫
  • 引入架构思想,软件质量提高。后期频繁加入改动,冲淡架构
  • 老板干涉过多 导致:压力过大 质量无法保证
  • 老板高度重视UI

研发路上的那些事儿 - 张超耀

  • 没有专业的移动端团队人员
  • 产品研发没有系统流程,走一步算一步
  • 需求人人可以改
  • 忙的时候忙的要死,闲的时候闲的蛋疼

研发之路上的坑 - 潘君

盲目相信自己,不合理的压缩周期

在开发周期过程中,过分相信努力的作用,以为团队只要努努力,可以爆发一个超越平时的战斗力.

在预估周期的过程中,过分考虑老板的感受,不合理的压缩周期,不断的向需求妥协,导致后期死的非常难看.

一方面自己的预估承诺没有兑现.另一方面团队本身也精疲力尽.

好事多磨,鸡血不能多打

一个好的项目不是短期可以做出来的,是必须慢慢打磨,而过分相信一个突击开发周期能够做出一个好产品是过于乐观的.

好事多磨,好的东西需要一个相对合理的周期.这个周期可能比较长,所以在较长的一段时间内要做的是保证团队的舒适度,而不是一味的打鸡血鼓励.

鸡血是一种需要正向循环的方式.如果没有一个好的反馈,鸡血的功效性就会越来越弱,最后反而会有逆效果.

高层强插改需求 - 吴明

  • 背景
    • 原公司移动开发中,在一项目层层过滤确定产品后,开发人员并已经开发了一段时间后,公司老板或者其他高层介入修改需求,延长开发时间。
  • 缺点:
    1. 开发时间浪费,花费时间做无用功
    2. 高层施压不利于下层产品开发,及产品迭代
    3. 项目延期打击开发团队人员士气和积极性
    4. 项目接近上线更改需求,严重影响开发人员心情,及代码编写质量
  • 后期流程改进
    1. 从项目入口抓起:所有指定项目必须经该项目需求方,产品,开发等直接最高领导确定,并且不更改需求下,开发人员才开发项目。
    2. 项目分阶段给高层领导汇报,把控项目质量。
    3. 高层需要项目后期改需求,只能下个版本迭代,本项目不予以改需求。

参与创业的辛酸史 - 郁兵生

  • 初创团队,没日没夜加班搞项目
  • 初创团队,不了解情况,项目周期把握不清。赶时间攒代码。

大众【设计占整个研发的重头】- 顾鹏凌

  • 完善的管理体
  • 细控的研发流程
  • 设计阶段作为重头,精雕细琢,避免后期遇到问题需要大改动

杂乱的管理 - 吴强

  • 初创团队,相关人员不完备
  • 产品经理只做了原型的工作,没有把控住需求的变更
  • 一人多职,多项目参与
  • 空降产品经理,做事一意孤行,跟团队不和

51offer的原始状态 - 庄丰洲

  • 没有移动端团队人员和移动端研发规范流程
  • 是个人都可以提需求

工作感悟-李仙鹏

  • 团队结构:

    崇尚扁平化的互联网公司,员工之间没有非常明县的上下级关系。

  • 需求把控:

    需求不明确、中途变更、压榨开发都TMD是耍流氓

    1. 一个好的项目需求,应该在kick off前全面规划产品,产品和设计明确需求并且画押签字,中途不得变更。当临时提出需求变更时,技术应该敢于把画押字据拿出来并且提出拒绝——把变更需求留在下一版本迭代。

    2. 不应该为了迎合进度而倒推时间压榨开发,这样做出来的东西很可能会是漏洞百出的

Better 的一路走来 - 王胜

第一个版本历时4个月的天天加班

  • 评估开发时间时,仅有原型;设计稿一出,开发人员瞬间觉得工作量要直线上升。
  • 按照一个有经验的工程师估出时间,然后上面说再调一个人,时间周期按照除以2来算。掉入《人月计划》中所说的坑。
  • 新组建的团队,缺少默契,需要磨合。【包括客户端之间,客户端与API之间,客户端与UI之间】
  • 临近上线,上面对体验要求无止境,导致细节调整没完没了

一起努力,挺过4个月

  • 打过鸡血
  • 慢慢地团队之间有了默契
  • 制定上线体验阀值,不能无止境提出体验调整的需求

后续版本的研发

  • 严格按照Scrum流程迭代开发版本,目前2周一迭代
  • Sprint确定需求后,不能强制加入新的需求
  • 特例的需求要插入Sprint,那么就顺延Sprint的周期

工作经历的一些片段 - 曾铭

文化

  • (敏感信息)略

好的

  • 工程师主导的开发流程:产品做调研,提目标,开发参与设计 feature 包揽实现、测试、验证
  • 牛人不少:一流的人招一流的人,二流的人招三流的人
  • 优秀工具的使用 (工具绝非一蹴而就, svn -> git,)
  • 对代码的极致追求 (代码行数、朝歌->镐京、Hackathon:一夜实现客户端聊天)
  • 相对优秀的办公环境 (畅通的网络等)

不好的

  • 目标不明确 (对商家态度的摇摆)
  • 不接地气(商业化不成功)
  • 理想主义者的碰撞, 无妥协
  • 急躁(寻求改变的高期望)
  • 压力大

以上不针对具体公司

用 travis-ci 自动部署 hexo 静态博客

各种静态博客引擎中,hexo 已经算比较方便,hexo deploy --generate 一条命令搞定部署工作。

我们团队成员在写静态博客的时候,碰到一些情况想把这一步也省掉:

  • 本地没装 hexo,只想写篇文章就 push
  • push 都不想,只在 github 上修改文章内容
  • 我就是懒,一行 deploy 命令也懒得打

……也都挺有道理。我们看看怎么用 travis-ci 搞定 hexo 自动部署。

实现

hexo 的作者写了篇文章介绍了自动部署,请参考这里

  • 设置 deploy key
1
ssh-keygen -t rsa -C "your_email@example.com"
# 注意指定 file_key,此处为 travis_key, passphrase 为空
# 之后会生成 travis_key 和 travis_key.pub 两个文件, 把 travis_key.pub 设置到 https://github.com/settings/ssh 中

travis encrypt-file travis_key --add
# 这里会生成 travis_key.enc 文件,同时在 .travis.yml 中新增 openssl 一行
  • 设置 .travis.yml, 附上最终配置
1
language: node_js


node_js:
- '0.12'


before_install:
- npm install hexo -g

# config for `hexo deploy`
- openssl aes-256-cbc -K $encrypted_4dbc5423f685_key -iv $encrypted_4dbc5423f685_iv
  -in .travis/travis_key.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- eval $(ssh-agent)
- ssh-add ~/.ssh/id_rsa
- cp .travis/ssh_config ~/.ssh/config
- git config --global user.name "travis_bot"
- git config --global user.email "mithvv@gmail.com"


script:
- hexo generate
- hexo deploy


branches:
  only:
  - blog
  • https://travis-ci.org 网站启用对应项目
  • 之后每次有新的 push 或 pull-request,travis-ci 都会自动 build,根据 build log 调试
  • Build Status 加到项目介绍中,Enjoy!

一些 tips

  • repo-setting 中设置 default branch 为 blog,这样访问项目首页直接显示源文件
  • 注意开源项目不要提交 travis_key & travis_key.pub 文件 ;)
  • travis-ci 每次 build 前自动 clone(参见 build log),所以我认为 hexo 作者配置中的 git clone 是不必要的

微信公众号开发

对于微信公众号开发的疑问

  • 微信公众点与自己服务器配对流程
  • 本地如何调试
  • 微信整体流程中用到的一些特殊协议?
  • openId/unionId 哪里查看
  • access_token 为什么要有时间限制 为什么是2小时
  • 网页授权如何做的?能取到哪些信息?
  • 参加活动不关注 能拿到多少信息
  • 菜单type类型
  • 有哪些好的第三方开发工具包
  • 所有的活动行为全部调一个url 有没有好的分发解决方案

公众号查询通讯录的实现 - 曾铭

思路

  • 通讯录表 -> 后台数据库
  • 用户关注公众号
  • 用户发消息(姓名)给公众号
  • 微信后台转发此消息给网站后台 post XML
  • 后台根据此消息(姓名)查询数据库,得到此人具体数据,组合 XML 返回给微信后台
  • 微信后台把具体数据展示给用户

实现

  • 通讯录表 xls -> csv -> 导入到 LeanCloud 数据库
  • 基于 express (node.js web 框架),建立 51offer_wechat.avosapps.com/contact_bot 站点;
  • 微信公众号后台配置开发者后台 URL,处理后台网址 get 请求,完成微信对开发者后台的验证
  • 处理网址 post 请求,完成接受消息,查询数据库,返回用户信息工作。具体参考:这里

总结

  • node.js (express) 处理网络请求的确精简方便
  • 微信公众号的所有信息都转发到一个接口,后续处理类型多时要设计合理的分发机制
  • 微信接口为什么用 XML 而不是 json 啊,这点不熟悉占用不少时间
  • 做这个很有意思,推荐大家多玩玩~

商户端APP集成微信扫描支付 - 王胜

准备工作

支付流程

  1. 用户在APP端浏览商品
  2. 加入购物车
  3. 结算
  4. 调用提交订单接口
  5. 提交订单接口返回预支付链接(预支付链接可根据服务端微信支付sdk生成)
  6. APP根据链接生成二维码
  7. 用户拿起手机扫描支付
  8. 微信调用第三方开发者服务端暴露的notify接口
  9. 第三方服务端在收到notify接口调用时,更新订单库里订单状态,同时调用push通道告诉APP支付成功
  10. APP收到push命令后进行页面跳转

微信分享 - 吴明

  • 微信工作原理
    • Alt text
  • 接口:
    • 你需要触发什么事件
    • 微信事件触发会回调哪里接口
  • 微信服务:
    • 订阅号:
    • 服务号
    • 企业号
    • 微购物
    • 微信公众号自定义菜单开发
      • 接口文档
        - [获取access token](http://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html)
        - [自定义菜单创建接口](http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html)
        - 以下操作都是在[微信公众平台接口调试工具](http://mp.weixin.qq.com/debug)调试方法
        
      • 步骤1:调用“获取access token”接口,传入你申请的测试微信公众号的appid和secret获取access_token
      • 步骤2:调用“自定义菜单创建接口”,传入上面生成的access_token和“自定义菜单json数据”如下
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
27
28
29
{
"button": [
{
"type": "view",
"name": "51offer",
"url": "http://www.51offer.com/"
},

{
"name": "移动",
"sub_button": [
{
"type": "view",
"name": "blog",
"url": "http://51offer.github.io/"
},

{
"type": "view",
"name": "github",
"url": "https://github.com/51offer/public-docs/wiki"
}

]
},

{
"type": "click",
"name": "我",
"key": "me"
}

]
}

  • 推荐:公众号:招商信用卡

知其所以然

2015.07.07 - 知其所以然(10分钟解释一个和开发相关的原理)

WEB 登录『原理』 - 曾铭

  • HTTP 是无状态协议
  • Session 服务器端简单存储
  • cookie 客户端简单存储(注意:在请求头中)

密码如何存储

  • 明文存储
  • md5 碰撞库破解 md5(pwd)
  • md5+salt md5(pwd+salt) salt pwd
  • sha1……都能用,千万不要自己实现散列算法

一个登录的过程

  • 明文密码
  • session_id, access_token, token
  • 第三方登录:OAuth2, OpenID

iBeacon - 潘君

  • BLE

    • RSSI(Received Signal Strength Indicator)
    • 唯一标识码
    • 例: 防丢器
  • 应用场景

    • 配合微信摇一摇
    • 商城导购
    • 地下停车库导航
  • 室内定位

    • 标签定位
    • 三角定位
    • 指纹定位

andoid虚拟机 - 吴明

  • 系统框架对比android vs ios
  • ios系统框架
  • android系统框架
  • Dalvik虚拟机

    • Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其指令集基于寄存器架构,执行其特有的文件格式——dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于Linux内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
  • Android系统是以Linux系统为底层构建的,Android系统是开源(源代码公开)的,Android系统势必会适配到不同硬件配置的设备上,因此谷歌为了降低应用的开发难度在Linux底层之上构筑了一个名为“Dalvik”的虚拟机。

  • 一个应用,一个虚拟机实例,一个进程!!!
  • android虚拟机详细

  • 其他:

    • ART模式:Android4.4中新加入的ART模式,该模式的完整名称是Androidruntime.
    • ART:Android 4.4开始推出的新的运行环境,在APP安装的时候使用dex2oat工具直接把DEX文件转换为机器码文件,运行的时候以机器码方式运行,可以充分利用系统性能;此外,改进的内存回收机制使得ART运行模式下的内存回收速度只有Dalvik运行时模式下的50%,也能够提升系统运行速度。

Android的Message Pool是个什么鬼(源码角度分析) - 李仙鹏

Android中,我们在线程之间通信传递通常采用Android的消息机制,而这机制传递的正是Message。

通常,我们使用Message.obtain())和Handler.obtainMessage())从Message Pool中获取Message,避免直接构造Message。

Message.obtain()源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {

synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}

从代码片中,可以看到Message是直接由sPool赋值的。

Handler.obtain()源码

1
2
3
4
5
6
7
8
9
/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
public final Message obtainMessage()

{
return Message.obtain(this);
}

Handler.obtain()最终还是调用Message.obtain()来获取的。

Message Pool相关源码分析

Message Pool数据结构
1
2
3
4
5
6
7
8
9
10
// sometimes we store linked lists of these things
/*package*/ Message next;

private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;

private static final int MAX_POOL_SIZE = 50;

private static boolean gCheckRecycle = true;

从代码中可以很明确的看到,Message Pool的数据结构实际就是一个链表。sPool就是一个全局的消息池,sPoolSize记录链表长度,MAX_POOL_SIZE表示链表的最大长度为50。

Message Pool如何存放Message
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/** @hide */
public static void updateCheckRecycle(int targetSdkVersion) {
if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
gCheckRecycle = false;
}
}

/**
* Return a Message instance to the global pool.
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* </p>
*/

public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}

/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/

void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;

synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}

从代码分析上看,消息池存放的核心方法就是上面的recycleUnchecked()方法:

1、将待回收的Message对象字段置空(避免因Message过大,使静态的消息池内存泄漏)。

2、以内置锁对方式(线程安全),判断当前线程池的大小是否小于50。若小于50,直接将mesaage插入到消息池链表尾部;若大于等于50,则直接丢弃掉,交由GC管理。


消费者心理学:三个趣味经济学原理 — 张超耀

  • 价格越低为什么不但不好卖,反而价格越高越好卖
  • 为什么大手大脚的浪费反而可以拯救经济?
  • 为什么免费未必就是最好的

这些经济学原理背后又有哪些逻辑在支撑,让我去探讨一下这些好玩的经济学吧。

价格越高越好卖——虚荣效应

  • 富人们一般不喜欢大众模仿他们的消费行为,这种情况就叫做虚荣效应(snob effect)。虚荣效应具体是指购买商品的时候追求与众不同的个性的现象。

  • 虚荣效应主要有以下两种表现。

    • 高档商品刚上市的时候迅速购买。这是因为,在这一瞬间并不是每个人都能享受到消费高档商品的荣誉。

    • 不论之前如何热情赞美的商品,一旦其市场占有率达到一般大众都可以消费的水平就不再继续购买。这是因为人人都能购买使用的商品既不会让人感到荣誉,也不会有高档的感觉。

大手大脚的浪费能拯救经济——节约悖论

  • 我们都知道,如果消费超过收入,就没有余钱可以储蓄,也就无法积累资金,最终只能过贫穷的生活。所以,为了成为富人我们会努力工作,有时候也会变成小气鬼,为了能储蓄更多钱而努力。

  • 这个原理对于个人是适用的,但是对于国家整体经济是否也适用呢?如果所有国民都变成小气鬼,这个国家真的能够变得更加富强吗?答案是否定的,尤其是在经济不景气的时候。让我们看看其原因何在。

  • 一旦经济进入不景气,基于对未来的担忧,人们会选择更多的储蓄进而减少消费。可是如果所有人都减少消费的话,企业的销售额就会降低,库存就会增加。随之而来的是企业只能降低生产减少雇用,而企业员工的收入就会减少。那么,对未来的担忧就会强化,人们会更加坚定地减少消费增加储蓄,于是整体经济就会陷入愈发不景气的恶性循环中。

免费未必就好——免费经济学

  • “世上没有免费的午餐”是1976年获得诺贝尔经济学奖的着名经济学家米尔顿弗里德曼(Milton Friedman)常说的一句话。

  • 有的信息粗看之下似乎是免费的,实际上经过了解后发现并不是免费的意思;或者可以解释为免费后面隐藏着某种诱饵,还可以理解为不要期待不付出代价的免费东西。就像“免费的奶酪只存在于捕鼠器上”的俄罗斯谚语一样,对免费的东西保持警惕是亘古不变的道理。

  • 看看我们周围,就能发现很多免费营销,地铁站前的免费报纸就是其中一种。曾经威胁到日报和体育报纸的免费报纸因为有很多读者,所以可以从广告收入上获得高收益。人气差的免费报纸会因为得不到足够的广告收入而被淘汰,这样的话,幸存下来的免费报纸就可以逐步占据更加有利的位置。越是资金实力雄厚的公司,在这种免费竞争中能够生存下来的概率就越大。因此,消费者也可能会面临因为垄断招致的损失。

  • 免费经济市场的另一个弊端就是对资源的浪费。以免费报纸为例,因为免费派发给消费者,所以新闻纸会被大量浪费掉。大量生产大量消费的体制会导致能源的过度使用而招致地球变暖势头的加速。”


Icon制作 - 杨志平

qq20150707-6 2x
qq20150707-11 2x

51offer的Icon的流程

qq20150707-1 2x
qq20150707-2 2x
qq20150707-3 2x
qq20150707-4 2x
qq20150707-5 2x

另一个Icon的制作的流程

qq20150707-7 2x
qq20150707-8 2x
qq20150707-9 2x
qq20150707-10 2x

Android 动画制作 - 王胜

View Animation

  • AlphaAnimation 淡入淡出效果
  • TranslateAnimation 移动效果
  • ScaleAnimation 缩放效果
  • RotateAnimation 旋转效果

原理:提供动画的起始和结束状态信息,中间的状态根据上述类里差值器算法填充
[示例参考]

Property Animation

View Animation动画比较简单,一般都是单个因素的变化,如果牵扯到复杂的动画,就显得力不从心。因此,Android 3.0 引入了属性动画。注:可通过[NineOldAndroids]项目在3.0之前的系统中使用Property Animation

原理:暴露出差值算法的回调方法,有工程师自己发挥想象,造出奇妙的动画效果。
[示例参考]

Drawable Animation

逐帧动画

原理:提供动画每个帧上的图片资源,顺序播放
[示例参考]

ClipDrawable 剪切动画

原理:提供一个背景图片,前景图片是一个ClipDrawable对象。通过线程操作ClipDrawable的剪切进度。

实例:

  • ClipDrawable 定义xml文件
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/loading_progress"
android:gravity="bottom">

</clip>
  • 组件引用
1
2
3
4
5
6
7
8
9
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:paddingTop="5dp"
android:paddingLeft="5dp"
android:background="@drawable/loading_bg"
android:src="@drawable/clip_loading"/>

  • 线程动态改变剪切进度
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
27
28
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果消息是本程序发送的
if (msg.what == MSG_WHAT) {
mClipDrawable.setLevel(mProgress);
}
}
};
.......
Runnable mRunnable = new Runnable() {
@Override
public void run() {
isRunning = true;
while (isRunning) {
handler.sendEmptyMessage(MSG_WHAT);
if (mProgress > MAX_PROGRESS) {
mProgress = 0;
}
mProgress += 100;
try {
Thread.sleep(18);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};

扯扯线程并发和同步的那些事

扯扯线程并发和同步的那些事 2015.6.26

线程基础的那些事——李仙鹏

线程

线程俗称为轻量级进程。在现代OS中,通常以线程作为基本的调度单位。线程会共享进程范围内的资源,例如内存句柄和文件句柄,但每个线程又有各自的程序计数器、栈以及局部变量等。因此,再配合多核CPU,多个线程方可被并发执行。

线程的上下文切换

如果当前运行线程数与CPU核数相同,那么这些线程将不会被系统调度出去。

但是,如果可运行的线程数量大于CPU核数,那么系统会通过上下文切换,将某个正在运行的线程调度出来,从而使其他线程能够获得CPU的时间片,从而得到运行。

上下文切换需要一定的开销:

  1. 系统和应用程序都使用一组相同的CPU,线程调度需要访问系统资源。系统代码消耗越多的CPU时间,分配到应用程序的可用CPU时间就越少。
  2. 上下文切换会导致处理器的一些缓存缺失

线程的以上特性,促使了现代编程的并发和同步问题:

  • 安全性问题。安全性的含义是“永远不会发生糟糕的事情”
  • 活跃性问题。活跃性关注的目标为“某件正确的事情最终会发生”
  • 性能问题。性能关注的点事“正确的事情尽快发生”

超线程(Hyper-Threading)

为何我们会经常听到宣传说:四核八线程并行(如I5处理器)、八核十六线程并行(如I7)。原因是,这些CPU使用了超线程技术。超线程最早由因特尔研发,并在奔腾四处理器将技术主流化。

超线程技术是在CPU内部仅复制必要的资源、让CPU模拟成两个线程;也就是一个实体核心,两个逻辑线程,在一单位时间内处理两个线程的工作,模拟实体双核心、双线程运作。

虽然采用超线程技术能同时执行两个线程,但它并不象两个真正的CPU那样,每个CPU都具有独立的资源。当两个线程都同时需要某一个资源时,其中一个要暂时停止,并让出资源,直到这些资源闲置后才能继续。因此超线程的性能并不等于两颗CPU的性能。

GUI为什么都是单线程

许多人曾经尝试过编写多线程的GUI来处理事件,但最终都由于竞态条件和死锁导致的稳定性而重回到单线程的事件队列模型:使用UI线程从队列中抽取事件,并将事件分发给事件处理器(消费者)。

另一个重要原因是MVC会导致多线程的GUI因为不一致的锁定顺序而发生死锁。
MVC模式图

推荐两本书

值得一看:

JAVA多线程中的单例——贾学涛

常见单利模写法

public class Singleton {  

    private static Singleton mInstance;

    private Singleton(){
    }

    public static Singleton getInstance(){
        if (mInstance == null) {
            mInstance = new Singleton();
        }
        return mInstance;
    }
}
  • 缺点:非线程安全的,在多线程并发的情况下容易出现多个实例存在的情况

改为线程安全的单例模式

通过添加synchronized关键字

public class Singleton {  

    private static Singleton mInstance;

    private Singleton(){
    }

    public static synchronized Singleton getInstance(){
        if (mInstance == null) {
            mInstance = new Singleton();
        }
        return mInstance;
    }
}
  • 缺点:每次都要进行同步检查,实际上需要检查的时机是在首次创建实例的时候。

改为双重检查锁单例模式

public class Singleton {  

    private static Singleton mInstance;

    private Singleton(){
    }

    public static Singleton getInstance(){
        if (mInstance == null) {          //Single Checked
            synchronized(Singleton.class) {
                if (mInstance == null) {        //Double Checked
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}
  • instance = new Singleton()这句,并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情

    1.给 instance 分配内存
    2.调用 Singleton 的构造函数来初始化成员变量
    3.将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)

    但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的.可能会出现第一次检测是mInstance为非null时,有可能实例还未创建。所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。

为实例变量增加volatile关键字

public class Singleton {  

    private volatile static Singleton mInstance;    // 增加volatile关键字

    private Singleton(){
    }

    public static Singleton getInstance(){
        if (mInstance == null) {          //Single Checked
            synchronized(Singleton.class) {
                if (mInstance == null) {        //Double Checked
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}
  • 使用 volatile 的主要原因是其另一个特性:禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障,读操作不会被重排序到内存屏障之前

  • Java 5 以前的版本使用了 volatile 的双检锁还是有问题的。其原因是 Java 5 以前的 JMM (Java 内存模型)是存在缺陷的,即时将变量声明成 volatile 也不能完全避免重排序

饿汉加载单例模式

public class Singleton {  

    private static Singleton mInstance = new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
        return mInstance;
    }
}

变种的饿汉加载单例模式

public class Singleton {

    private static Singleton mInstance;

    static {
        mInstance = new Singleton();
    }

    private Singleton(){
    }

    public static Singleton getInstance(){
        return mInstance;
    }
}
  • 缺点:在类被加载的时候就会去创建实例,牺牲空间来保证时间,与之前的单例模式相反,懒汉加载是牺牲时间,来保证空间,在需要的时候再去创建实例。

通过静态内部类来创建单例

public class Singleton {

    private Singleton(){
    }

    public static Singleton getInstance(){
        return InnerClass.mInstance;
    }

    private staitc class InnerClass{
        public static Singleton mInstance = new Singleton();
    }
}
  • 与前者一样,通过classloader机制来保证线程安全,区别是,前者当Singleton类被加载时,就会创建实例,而后者是在需要调用getInstance的时候去加载内部类的时候,来创建实例。

通过枚举来创建单例

public enum Singleton {
    INSTANCE;
}

访问实例对象 Singleton.INSTANCE

*默认枚举实例的创建是线程安全的,但是在枚举中的其他任何方法由程序员自己负责。

为什么要有线程同步之喂金鱼问题——曾铭

喂金鱼问题

  • 金鱼一天不吃会饿死,一天吃两次会撑死;
  • 张三、李四,每天每人分别会去执行这件事一次;

方案 1

两人执行一致

1
2
3
if (noFeed) {
feed fish
}
张三 李四
if (noFeed) { .
. if (noFeed) {
. feed fish
feed fish .
fish died .
结论
  • feed fish 时间越长,鱼被撑死可能性越大
  • 没解决问题

方案 2

两人执行一致

1
2
3
4
5
6
7
8
9
if (noNote) {
leave note

if (noFeed) {
feed fish
}

remove note
}
张三 李四
if (noNote) { .
. if (noNote) {
. leave note
leave note .
if (noFeed) { .
. if (noFeed) {
. feed fish
feed fish .
fish died .
结论
  • noNote, noFeed 按特定顺序执行才会出问题
  • noNote 多了一层保护,如果 leave note 时间很短,出问题可能性很小
  • 没解决问题

方案 3

张三执行

1
2
3
4
5
6
7
8
9
leave note3

if (noNote4) {
if (noFeed) {
feed fish
}
}

remove note3

李四执行

1
2
3
4
5
6
7
8
9
leave note4

if (noNote3) {
if (noFeed) {
feed fish
}
}

remove note4
张三 李四
leave note3 .
. leave note4
. if (noNote3) {
if (noNote4) { .
remove note3 .
. remove note4
fish died .
结论
  • 不会被撑死了,可能会被饿死……
  • 没解决问题

方案 4

张三执行

1
2
3
4
5
6
7
8
9
10
11
12
leave note3

while (noNote4)
{
sleep (1)
}

if (noFeed) {
feed fish
}

remove note3

李四执行

1
2
3
4
5
6
7
8
9
leave note4

if (noNote3) {
if (noFeed) {
feed fish
}
}

remove note4
结论
  • 的确解决了问题
  • 能优化么?
    • 程序不不对称
    • 循环等待的浪费

方案 5

两人执行一致

1
2
3
4
5
6
7
lock()

if (noFeed) {
feed fish
}

unlock()
总结
  • 能解决问题
  • 程序对称
  • 持有锁需要等待,未解决浪费问题
    • 生产者与消费者问题

END

全部内容来自《计算机的心智·操作系统之哲学原理》——邹恒明 第七章

iOS并发相关的概念介绍——潘君

@(归纳中)[iOS]

基础概念

竞态条件

竞态条件(race condition),从多进程间通信的角度来讲,是指两个或多个进程对共享的数据进行读或写的操作时,最终的结果取决于这些进程的执行顺序。
竞态条件(race condition)是指设备或系统出现不恰当的执行时序,而得到不正确的结果。

注: atomic 可以解决竞态竞争 但是无法保证类是线程安全

iOS中的相关概念

atomic属性

property 修饰符

加了atomic后生成的setter,类似如下代码:

1
2
3
4
5
- (void)setProp:(NSString *)newValue {
[_prop lock];
_prop = newValue;
[_prop unlock];
}
@synchronized指令

引用自@synchronized(id anObject) {}定义和使用
1.作用:创建了一个互斥锁,它的作用和其他语言中的互斥锁作用一样

2.解释:这个是OBC中的一个锁定令牌,防止{}里的内容在同一时间内被其他线程访问,起到了线程保护的作用

3.使用范围:一般在单例模式或者操作类的static变量的时候使用,即共用的变量的时候

4.外延:这个令牌隐式的包含了异常处理,如果你不想使用的话,就使用锁吧

5.它的参数是id类型,如果用
@synchronized(1) {
}
编译器提示
@synchronzied requires an Objective-C object type.
也就是说需要一个objective C的对象类型。

1
2
3
@synchronized(id anObject){
// test code
}
NSLock

使用样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//主线程中
TestObj *obj = [[TestObj alloc] init];
NSLock *lock = [[NSLock alloc] init];

//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
[obj method1];
sleep(10);
[lock unlock];
});

//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);//以保证让线程2的代码后执行
[lock lock];
[obj method2];
[lock unlock];
});

iOS多线程 - 杨志平

简介

iOS有三种多线程编程的技术,分别是:

  • NSThread

  • Cocoa NSOperation

  • GCD (全称:Grand Central Dispatch)

这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的

三种方式的介绍:

NSThread - 文档

优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销

NSOperation - 文档

优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

GCD - 文档

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。

GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。

创建线程的开销 - 查看文档

Item Approximate cost Notes
Kernel data structures Approximately 1 KB This memory is used to store the thread data structures and attributes, much of which is allocated as wired memory and therefore cannot be paged to disk.
Stack space 512 KB (secondary threads) 8 MB (OS X main thread) 1 MB (iOS main thread) The minimum allowed stack size for secondary threads is 16 KB and the stack size must be a multiple of 4 KB. The space for this memory is set aside in your process space at thread creation time, but the actual pages associated with that memory are not created until they are needed.
Creation time Approximately 90 microseconds This value reflects the time between the initial call to create the thread and the time at which the thread’s entry point routine began executing. The figures were determined by analyzing the mean and median values generated during thread creation on an Intel-based iMac with a 2 GHz Core Duo processor and 1 GB of RAM running OS X v10.5.

替代线程的一些技术

Item Approximate cost
Operation objects Introduced in OS X v10.5, an operation object is a wrapper for a task that would normally be executed on a secondary thread. This wrapper hides the thread management aspects of performing the task, leaving you free to focus on the task itself. You typically use these objects in conjunction with an operation queue object, which actually manages the execution of the operation objects on one or more threads.For more information on how to use operation objects, see Concurrency Programming Guide.
Grand Central Dispatch (GCD) Introduced in Mac OS x v10.6, Grand Central Dispatch is another alternative to threads that lets you focus on the tasks you need to perform rather than on thread management. With GCD, you define the task you want to perform and add it to a work queue, which handles the scheduling of your task on an appropriate thread. Work queues take into account the number of available cores and the current load to execute your tasks more efficiently than you could do yourself using threads.For information on how to use GCD and work queues, see Concurrency Programming Guide
Idle-time notifications For tasks that are relatively short and very low priority, idle time notifications let you perform the task at a time when your application is not as busy. Cocoa provides support for idle-time notifications using the NSNotificationQueue object. To request an idle-time notification, post a notification to the default NSNotificationQueue object using the NSPostWhenIdle option. The queue delays the delivery of your notification object until the run loop becomes idle. For more information, see Notification Programming Topics.
Asynchronous functions The system interfaces include many asynchronous functions that provide automatic concurrency for you. These APIs may use system daemons and processes or create custom threads to perform their task and return the results to you. (The actual implementation is irrelevant because it is separated from your code.) As you design your application, look for functions that offer asynchronous behavior and consider using them instead of using the equivalent synchronous function on a custom thread
Timers You can use timers on your application’s main thread to perform periodic tasks that are too trivial to require a thread, but which still require servicing at regular intervals. For information on timers, see Timer Sources
Separate processes Although more heavyweight than threads, creating a separate process might be useful in cases where the task is only tangentially related to your application. You might use a process if a task requires a significant amount of memory or must be executed using root privileges. For example, you might use a 64-bit server process to compute a large data set while your 32-bit application displays the results to the user

线程安全 - 文档

原则
  • Immutable objects are generally thread-safe. Once you create them, you can safely pass these objects to and from threads. On the other hand, mutable objects are generally not thread-safe. To use mutable objects in a threaded application, the application must synchronize appropriately.
  • Many objects deemed “thread-unsafe” are only unsafe to use from multiple threads. Many of these objects can be used from any thread as long as it is only one thread at a time. Objects that are specifically restricted to the main thread of an application are called out as such
  • The main thread of the application is responsible for handling events. Although the Application Kit continues to work if other threads are involved in the event path, operations can occur out of sequence
  • If you want to use a thread to draw to a view, bracket all drawing code between the lockFocusIfCanDraw and unlockFocus methods of NSView
Thread-Safe Classes and Functions

The following classes and functions are generally considered to be thread-safe. You can use the same instance from multiple threads without first acquiring a lock.

NSArray
NSAssertionHandler
NSAttributedString
NSCalendarDate
NSCharacterSet
NSConditionLock
NSConnection
NSData
NSDate
NSDecimal functions
NSDecimalNumber
NSDecimalNumberHandler
NSDeserializer
NSDictionary
NSDistantObject
NSDistributedLock
NSDistributedNotificationCenter
NSException
NSFileManager (in OS X v10.5 and later)
NSHost
NSLock
NSLog/NSLogv
NSMethodSignature
NSNotification
NSNotificationCenter
NSNumber
NSObject
NSPortCoder
NSPortMessage
NSPortNameServer
NSProtocolChecker
NSProxy
NSRecursiveLock
NSSet
NSString
NSThread
NSTimer
NSTimeZone
NSUserDefaults
NSValue

Thread-Unsafe Classes

The following classes and functions are generally not thread-safe. In most cases, you can use these classes from any thread as long as you use them from only one thread at a time.

NSArchiver
NSAutoreleasePool
NSBundle
NSCalendar
NSCoder
NSCountedSet
NSDateFormatter
NSEnumerator
NSFileHandle
NSFormatter
NSHashTable functions
NSInvocation
NSJavaSetup functions
NSMapTable functions
NSMutableArray
NSMutableAttributedString
NSMutableCharacterSet
NSMutableData
NSMutableDictionary
NSMutableSet
NSMutableString
NSNotificationQueue
NSNumberFormatter
NSPipe
NSPort
NSProcessInfo
NSRunLoop
NSScanner
NSSerializer
NSTask
NSUnarchiver
NSUndoManager

Main Thread Only Classes

The following class must be used only from the main thread of an application.

NSAppleScript

多线程的死锁 - 张超耀

  • 俗话说,人多好办事!在程序里也是这样,如果是同一个应用程序需要并行处理多件任务,那就可以创建多条线程。但是人多了,往往会出现冲突,使得这个工作无法再进行下去了(正所谓三个和尚没水喝),这就是“死锁”。

死锁的产生

那么我们如何来消除“死锁”呢?首先,让我们来看看产生“死锁”的必要条件:

  • 互斥:就是说多个线程不能同时使用同一资源

  • 请求和保持:就是某线程必须同时拥有多个资源才能完成任务,否则它将占用已经拥有的资源直到拥有他所需的所有资源为止

  • 不剥夺:就是说所有线程的优先级都相同,不能在别的线程没有释放资源的情况下,夺走其已占有的资源

  • 循环等待,就是没有资源满足的线程无限期地等待

有的朋友可能已经明白了,只要打破这这几个必要条件,就能打破“死锁”!

  • 互斥:就是要让多个线程能共享资源

  • 请求和保持:只要当检测到自己所需的资源仍被别的线程占用,即释放自己已占有的资源(毫不利己,专门利人),或者在经过一段时间的等待后,还未得到所需资源,才释放,这都能打破请求和保持

  • 不剥夺:只要给线程制定一个优先级即可

  • 最后的循环等待的解决方法其实和请求和保持是一样的,都是等待一段时间后释放资源。

好了,希望通过这个例子能让不了解死锁的朋友对“死锁”能有一定的认识

集合的并行操作 - 王胜

用for循环操作一个集合,即读取集合元素,同时又删除集合中的元素,会发生什么事情呢?

上代码【号外,号外,此示例来源于我们项目中的真实代码哦~】

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Target class
class Target {
int id;// ID
String type;// 类型
int count;// 未读消息数

public Target(int id, String type, int count) {
this.id = id;
this.type = type;
this.count = count;
}

@Override
public String toString() {
return "Target [id=" + id + ", type=" + type + ", count=" + count + "]";
}

}

// 以下是模拟一组target集合,target包含group、room、user类型。
List<Target> sessions = new ArrayList<Target>();
sessions.add(new Target(1, "group", 1));
sessions.add(new Target(2, "group", 1));
sessions.add(new Target(3, "group", 1));
sessions.add(new Target(4, "room", 1));
sessions.add(new Target(5, "group", 1));
sessions.add(new Target(6, "group", 1));
sessions.add(new Target(7, "group", 1));
sessions.add(new Target(8, "user", 1));
sessions.add(new Target(9, "user", 1));
sessions.add(new Target(10, "group", 1));
System.out.println("before size:"+sessions.size()+", sessions:"+humanPrintList(sessions));
int totalUnread = 0;// 统计集合中类型为group的target未读消息数量
for (int i=0;i<sessions.size();i++) {
System.out.println("read index:" + i + ", session:"+sessions.get(i));
if (sessions.get(i).type.equals("group")) {// 如果是group类型,则累加未读消息数
System.out.println("==> add totalUnread");
totalUnread += sessions.get(i).count;
} else {// 否则,将target移除集合
System.out.println("==> remove");
sessions.remove(i);
}
}
System.out.println("after size:"+sessions.size()+", totalUnread:"+totalUnread+",sessions:"+humanPrintList(sessions));

至此,示例代码结束。大家可以猜测下最后的输出中sessions的长度,内容以及总共的未读消息数据。

项目中的代码,期望结果是剩余集合只包含group类型的target,而且totalUnread的值是类型为group的target的未读消息数之和。可是,运行的结果却是:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
before size:10, sessions:
========== List content: ===========
Target [id=1, type=group, count=1]
Target [id=2, type=group, count=1]
Target [id=3, type=group, count=1]
Target [id=4, type=room, count=1]
Target [id=5, type=group, count=1]
Target [id=6, type=group, count=1]
Target [id=7, type=group, count=1]
Target [id=8, type=user, count=1]
Target [id=9, type=user, count=1]
Target [id=10, type=group, count=1]
====================================
read index:0, session:Target [id=1, type=group, count=1]
==> add totalUnread
read index:1, session:Target [id=2, type=group, count=1]
==> add totalUnread
read index:2, session:Target [id=3, type=group, count=1]
==> add totalUnread
read index:3, session:Target [id=4, type=room, count=1]
==> remove
read index:4, session:Target [id=6, type=group, count=1]
==> add totalUnread
read index:5, session:Target [id=7, type=group, count=1]
==> add totalUnread
read index:6, session:Target [id=8, type=user, count=1]
==> remove
read index:7, session:Target [id=10, type=group, count=1]
==> add totalUnread
after size:8, totalUnread:6,sessions:
========== List content: ===========
Target [id=1, type=group, count=1]
Target [id=2, type=group, count=1]
Target [id=3, type=group, count=1]
Target [id=5, type=group, count=1]
Target [id=6, type=group, count=1]
Target [id=7, type=group, count=1]
Target [id=9, type=user, count=1]
Target [id=10, type=group, count=1]
====================================

为什么结果完全不是预期的呢?原因是程序走到else时,将元素移除,后面的元素自动往前移动,所以继续取下一个下标时,被移除的后一个元素悄悄溜走了,成了漏网之鱼。

解决方法 : 最简单的就是在remove后执行 i--;

代码开发效率提升方法

2015.06.19 - 技术分享,主题”代码开发效率提升方法”

snippet的制作与使用 - 杨志平

备份路径

~/Library/Developer/Xcode/UserData/CodeSnippets/

界面

image

使用
1.系统自带

很多我们的代码提示都是snippet系统已经有的代码块如:
block变量定义

typedef <#returnType#>(^<#name#>)(<#arguments#>);

2.常用变量
  • strong
  • weak
  • assign
  • block
3.常用方法
  • 比如:hiddenKeyBoard
  • 网络请求:getData
  • 上下拉刷新,等等
4.常用模块
  • 常用的代理协议方法集
制作

选中代码块拖入snippet library即可。为了方便调用可简单编辑

image2

PaintCode的简单使用

简单的图形绘制,可像xib一样拖拽图形,并添加到view的CALayer层上

  • drawRect方法

myEclipse分享 - 吴明

  • myEclipse主要WebService开发工具

  • MyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、Java EE以及移动应用的开发。MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持相当不错。

  • myEclipse使用ssh框架

  • myEclipse常用快捷键

    • Alt+Shift+s:
      打开myEclipse快捷键菜单
      • 自动生成get set方法
      • 自动生成无参和有参构造方法
    • Ctrl+D:删除当前行
    • Ctrl+Alt+↓:复制当前行到下一行(复制增加)
    • Ctrl+Alt+↑:复制当前行到上一行(复制增加)
    • Alt+↓:当前行和下面一行交互位置
    • Alt+↑:当前行和上面一行交互位置
    • Ctrl+Shift+O:快速生成import,当从网上拷贝一段程序后,不知道如何import进所调用的类
  • ssh框架

OSX 快捷键入门 - 曾铭

OSX 系统级的快捷键支持
  • 统一标准的全局快捷键:如 FX、『设置』、opt
  • 在统一之外,留意每个应用的快捷键:如 chrome:opt+cmd+i,cmd+l
讨论常用快捷键 (具体快捷键请自己查)
  • 设置
  • 剪切复制粘贴全选
  • 新建、新建 tab、切换 tab、关闭 tab、关闭应用
  • 光标的自由游走
    • 上下左右(推荐 hjkl)、字符移动、行首行尾、文首文尾、向后删除、单词删除、行向前向后删除
  • Xcode
    • 上下移行 (@志平 推荐)
    • reveal to project navigator、切换 .h.m 文件
    • 显示隐藏 navigatiors、Debug area、Utilities
    • new tab、切换 tab、分割窗口
定制
  • System Preferences -> Keyboard : 配置快捷键、菜单快捷键、modifier keys
  • Karabiner
  • Keyboard Maestro 介绍
  • 定制建议
    • 原生为主,定制为辅
    • fix 原生不爽、有冲突的个别快捷键
      • 合理使用 opt, 规避冲突
    • 根据自己习惯定制
    • 常反思,记不住的快捷键都是『对你不重要』的快捷键

VIM - 潘君

vim起源
  • 源自开源vi
  • 作者Bram Moolenaar
  • 80年代末,Amiga计算机中无vi,作者自行开发
  • Vi IMitation(模拟) -> Vi IMproved(改良)
vim应用场景
  • linux
  • 平时代码
vim模式

列举常用模式如下
需要了解所有模式
在vim中使用:help vim-modes

  • Insert模式

    • 进入
      • i -> 在光标前插入
      • I-> 在句首插入
      • a -> 在光标后插入
      • A -> 在句尾插入
    • 离开
      • Esc
      • Ctrl + c
      • Ctrl + [
  • Normal模式

    • 进入vim的默认模式
    • 命令的天下
      • 简单移动
        • h j k l -> 左 下 上 右
        • 0 (数字零) -> 移动光标到行头
        • $ -> 移动光标到行尾
        • gg -> 到第一行
        • G -> 到最后一行
        • w -> 到下一个单词的开头。
        • e -> 到下一个单词的结尾。
      • 简单操作
        • dd -> 剪切当前行
        • yy -> 赋值当前行
        • p -> 粘贴
        • u -> 撤销
    • 神奇的.

      • 上次命令的重复
    • 命令的组合

      • daw -> 删除当前单词
      • 2dd -> 删除2行
      • 3p → 粘贴文本3次
      • 100idesu [ESC] → 会写下 “desu “100次
      • 0y$ -> 从行头拷贝到本行最后一个字符
  • visual模式

    • 进入
      • v
      • V
      • Ctrl + v
    • 退出
      • Esc
      • Ctrl + c
  • select模式

    • 进入

      • gh
      • gH
      • g(Ctrl + h)
    • 切换

      • Ctrl + o ->临时切换到可视化模式执行一个命令
      • Ctrl + g ->切换到可视化模式
vim大冒险游戏

VIM常用命令 - 王胜

光标移动
  • fx:移动光标到当前行的下一个 x 处。很明显,x 可以是任意一个字母,而且你可以使用 ; 来重复你的上一个 f 命令。
  • tx:和上面的命令类似,但是是移动到 x 的左边一个位置。
  • Fx:和 fx 类似,不过是往回找。
  • w:光标往前移动一个词。
  • b:光标往后移动一个词。
  • 0:移动光标到当前行首。
  • ^:移动光标到当前行的第一个字母位置。
  • $:移动光标到行尾。
  • ):移动光标到下一个句子。
  • ( :移动光标到上一个句子
替换
  • :s/hello/world 替换当前行中第一个hello为world
  • :%s/hello/world 替换每一行中第一个hello为world
  • :s/hello/world/g 替换当前行中所有的hello为world
  • :%s/hello/world/g 替换每一行中所有的hello为world
  • :%s/hello/world/gc 找到当前文件中所有的hello,并逐一询问用户是否要替换
内容提取
  • :r !date 将当前时间插入到当前文件
  • :r /path/to/src.file 将src.file里的内容输出到当前文件
总结

VIM的命令甚多,组合也很多,记忆是不能长时间记住的。唯一的捷径就是多多使用,用的多了,使用这些命令时就像手拿筷子一样,变成了本能。

Xcode插件管理 - 张超耀

  • 古人云“工欲善其事,必先利其器”,打造一个强大的开发环境,是立即提升自身战斗力的绝佳途径!以下是常用的一些有力的XCode插件。

  • 插件管理器:Alcatraz - The package manager for Xcode。

  • ColorSenseXCode颜色显示插件

    • 代码里的那些冷冰冰的颜色数值,到底时什么颜色?如果你经常遇到这个问题,每每不得不运行下模拟器去看看,那么这个插件绝对不容错过。更彪悍的是你甚至可以点击显示的颜色面板,直接通过系统的ColorPicker来自动生成对应颜色代码,再也不用做各种颜色代码转换了!
  • VVDocumenter规范注释生成器

    • 很多时候,为了快速开发,很多的技术文档都是能省则省,这个时候注释就变得异常重要,再配合Doxygen这种注释自动生成文档的,就完美了。但是每次都要手动输入规范化的注释,着实也麻烦,但有了VVDocumenter,规范化的注释,主需要输入三个斜线“///”,就OK啦!
  • XAlign代码整理

    • XAlign是一款专门用于代码整理的Xcode插件,其作者为来自Geek Zoo Studio的开发者QFish。XAlign能够对开发者的代码非常快速地进行对齐优化,有“=”、宏定义、属性三种对齐模式。当然,如果默认的对齐风格不是自己喜欢的,开发者还可以自定义或提出issues。
  • FuzzyAutocompletePlugin代码自动补全插件

    • 通过添加模糊匹配来提高Xcode代码自动补全功能,开发者无需遵循从头匹配的原则,只要记得方法里某个关键字即可进行匹配,很好地提高了工作效率。
  • XcodeBoost

    • XcodeBoost是一款可以让开发者轻而易举地检查和修改Objective-C代码的插件。XcodeBoost能够自动进行一些繁琐的操作,比如方法的定义与声明、添加基于命令行的代码处理(剪切/复制/粘贴/重复/删除行)、持续高亮等。
盘点开发者最喜爱的十大开源Xcode插件
那些不能错过的Xcode插件

开源

开源利弊浅谈 - 张超耀

开源?

  • 开源,(Open Source)全称为开放源代码。开源就是要用户利用源代码在其基础上修改和学习的。

优势何在?

  • 优势1:花费很少(如果有的话),许可费用
    • 当然,这往往省去那些讨厌的维护费用。
  • 优势2:易于管理
    • 只要你想,你可以在尽可能多的地方安装开源软件。无需为许可证合规性计数、跟踪或监视。
  • 优势3 :连续,实时改进
    • 因为每个人都可以访问源码,任何人都可以主动修改BUG,使其变得更好,而不必等待下一个版本。
  • 优势4:公司独立
    • 如果创建该软件的公司挂掉,代码仍然可以通过其用户社区继续存在和发展。
  • 优势5 :实践的探索
    • 我们可以很容易地“亲身探索”源码,以便更好地了解产品并作出改善。

劣势显著

  • 缺点1 :它不是完全免费
    • 开源软件可以涉及意料之外的实施、管理和支持成本。
  • 缺点2:学习曲线(技术支持)
    • 你可能在开源的产品上需要聘请专家,让自己加快速度。
  • 缺点3:迷茫的用户
    • 由于并行发展的努力在进行中,用户可能不知道哪个版本做什么或是否与你专有平台上的其他软件兼容。
  • 缺点4:孤立软件
    • 由于关键的程序员的斗争和退出,或他们失去兴趣转移到新的项目,使一些开源项目陷于停顿和死亡。
  • 缺点5:独立地(凭自己的力量)
    • 与商业产品不同,没有人在开源社区义务来帮助你,或回答你的任何问题。

开源,仁者见仁智者见智

与开源有关的小故事 - 曾铭

  • 比尔·盖茨
    • 软件私有,保护版权
    • 1976 年 《致计算机爱好者的公开信》
  • 理查德.斯托曼
    • Free Soft
    • GNU,GPL,Emacs,GCC
    • 推荐两本书:《大教堂与集市》《Just for Fun》
    • HHKB ;)
  • 思考
    • 开源软件和私有软件哪个质量更高?
    • 怎样参与开源?:
      • Github
      • 开源就是一种开放交流的态度
      • 不怕暴露自己的傻 X,(每个人都认为自己是对的,)万一对了呢 ;)
  • 最后再推荐一部纪录片:互联网之子

我如何接触开源 - 潘君

  • github trending

    • 代码 trending
      • 寻找有潜力的开源项目
    • 开发者 trending
      • 好的开发者应该不止一个好软件 顺藤摸瓜比较方便
  • 苹果官方开源

  • 开源软件闲暇阅读工具

    • CodeNav - 移动端优秀的代码查看软件
      • 优点
        • 支持多种方式导入源码
        • 交互不错 各种操作都算是方便
      • 缺点
        • 大屏支持还有bug
        • 不支持swift语法高亮

参与开源软件的心得 - 王胜

  • 参与方式:
    • 泡开源官方网站论坛,并参与issue讨论
    • 修改源码,生成patch文件,发给社区维护者
    • 有了Git && Github后,可以fork分支,修改代码,发送pull request
  • 参与过程情绪波动:
    查看源码 -> 领悟学习 -> 发现问题 -> 动手解决 -> 跟社区提交者沟通纳入源码树 or 通过github发送pull request
    -> 上游采用 -> 成就感十足。从而形成良性持续性参与感,并参与其中。
  • 收获心得:
    • 一次提交只做一件事
    • 提交说明规范、简单、见名知意。后续参与者看提交树就能看到软件的演化历史
    • 代码开源,足够多的眼睛,使bug无处可藏
    • 开源导致世界范围内可见,代码的创意来自于全球智慧的汇聚

OkHttp开源框架介绍 - 李仙鹏

SPDY

Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。

新协议的功能:

  • 数据流的多路复用
  • 请求优先级
  • HTTP报头压缩。
  • 服务器推送(即Server Push技术)

谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。

现在已经被Google弃用,推出新的基于SPDY实现的HTTP2.0。

HTTP2.0

HTTP也是基于TCP的应用层协议,大家熟知的为:

  • HTTP 0.9,只有基本的文本 GET 功能。
  • HTTP 1.0,完善的请求/响应模型,并将协议补充完整。
  • HTTP 1.1,在 1.0 基础上进行更新,增加了如 长久连接 keep-alive 与 chunked 等功能。

HTTP 2.0在2013年8月推出,基于Google的SPDY开发。

OkHTTP

OKHTTPis an HTTP client that’s efficient by default:

  • HTTP/2 and SPDY support allows all requests to the same host to share a socket.
  • Connection pooling reduces request latency (if SPDY isn’t available).
  • Transparent GZIP shrinks download sizes.
  • Response caching avoids the network completely for repeat requests.

OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.
You’ll also need Okio, which OkHttp uses for fast I/O and resizable buffers.

如何推广自己的开源项目(github获取更多的star) - 杨志平

前言

你可能花费几天甚至几个月时间开源一个你写的代码,但是没有人去使用它,靠运气的话可能可以推广. 现在我讲讲如何让人们关注我们的作品。该要点是打破下面的图片的循环

图片一

六步(4-6是秘诀)

  1. Projects are Everything
  • Read and Research
  • Building the Repo
  • README 文件
  • 图解
  • 更新反馈

1.Projects are Everything

开源代码就是给其他程序员解决问题或者节约时间的

2.Read and Research

很多问题都已经解决成千上万次了
你可以想一个你感兴趣的开源项目,上网搜索确认它的实现是不是已经有很多人实现了并有很多人已经使用它了,那就忘了这个想法。但是如果没有,或者解决方案不理想(可以通过issues查看他们的不足)你有时间的话就建一个和他们相识的开源项目,修复一些issues使用自己的文档(感觉有点无耻,但听说很有效)

3.Building the Repo

有一点就是,通常我们后面的repo的star增加速度比以前的repo要快挺多的,可能是以前的repo使得更多人认识你相信你。

4.README 文件(推荐布局方案)

图片2

5.图解(特效,一目了然)

Flipboard playing multiple GIFs

6.更新反馈

完成以上步骤,并不断更新开源库及时解决issues里面的bug就很有希望进入
star趋势
图片2
贡献名人
图片2

开源协议 - 吴明

  • 无规矩不成方圆,开源协议

    • BSD开源协议:满足三个条件
      • 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议
      • 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议
      • 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广
        • Apache Licence 2.0:(关心软件的专利问题,但同样希望宽松,选择这个协议)
        • 需要给代码的用户一份Apache Licence
        • 如果你修改了代码,需要再被修改的文件中说明。
        • 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明
        • 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改
    • GPL:(Linux)(希望代码使用者同样能把他们的贡献分享出来,那就选择GPL)

      • GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样
      • 代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代码做为闭源的商业软件发布和销售
      • 由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。
    • MIT:(简单、宽松,”为所欲为”,选择这个协议)

      • 类似BSD协议
    • Mozilla

    • LGPL

      • LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。
    • 说了这么多最后一个开源协议的选择

    • 其他

博客分享主题

2015.06.05 - 博客分享主题

android学习网站 - 王胜

  • Android官网
    • 官方SDK
    • 官方API文档
    • 官方training教程
    • 官方Sample【1.x之后的Android Studio有直接导入Sample的功能】
  • 任玉刚博客
    专注Android底层实现机制解析

android博客与学习网站 - 李仙鹏

博客框架与网站&&博客推荐 - 杨志平

常见博客框架
常见iOS开发博客网站

Android博客分享 - 吴明

  • 代码家

    • 最新好玩的android效果
    • 1到2周更新一次
    • 提供源码
  • 郭霖博客

    • 资深Android开发工程师、架构师
    • 畅销技术书籍《第一行代码——Android》
    • 博客主要针对android的最新技术分享透彻逻辑性强
  • android性能优化

    • 学习Android应用开发的绝佳资料
    • Google Android团队在2012年的时候开设了Android Training板块
  • Android开发资源汇总

博客工具与博客推荐 - 潘君

聊聊静态博客平台 - 曾铭

  • WordPress
  • Blogger
  • Tumblr
  • Ghost (node.js) WordPress 替代
博客的需求:

>

  • 写文章:(markdown,draft,category,tag)
  • 交流:评论、社区
  • 好看:theme(排版、中文排版、代码)
  • 好玩:自定义
  • 域名
静态博客

>

  • 博客何必动态生成,静态页面即可
  • 评论用第三方:多说,Disqus

  • Jekyll (Github Pager)ruby

  • Octopress 基于 Jekyll
  • Hexo (node.js)
非静态

>

  • 我只是想『漂亮』的写文章

  • Scriptogr.am

    • dropbox 同步
    • 自定义主题
  • FarBox
    • dropbox 同步
    • 自定义主题
    • Mac 客户端
  • pancake.io
  • Medium
    • 有社区,大部分是设计师
    • 漂亮
    • 有 App
    • 不能导出 md
  • Logdown
  • 作业部落
  • 简书
大道无形

>

技术博客分享 - 张超耀

  • 唐巧的技术博客(记录下自己学习的点滴)

    • 唐巧:猿题库iOS开发工程师,给InfoQ的「iOS 开发周报」供稿,并且转载到个人博客上。
  • ITeye

    • ITeye起源:ITeye即创办于2003年9月的javaEye,缘起是创始人范凯自己在学习和研究java的开源框架却发现没有一个讨论的地方,于是自己就办一个。
    • 一个优秀的Java学习交流分享平台。