The Traps of Frameworks

When I interview a Java developer, if I see Spring Boot or Spring on the candidate’s resume, I may start with a simple question: “What is the default scope for a Spring bean”? Most people would get it right. I would then follow with a tricky question: “Does Spring make sure a Singleton bean thread-safe?” or “Does developer need to do anything to make sure a Singleton bean thread-safe?”.

When I say “tricky”, not because it’s tricky technically, but because half interviewees have no idea. The other half who correctly answered don’t always demonstrate solid understanding of Singleton and thread-safety. It’s okay to guess at an interview I guess.

Spring Boot is one of those popular frameworks for Java developers. Like most other Java frameworks, it provides proven reusable libraries and increases productivity. Some developers can probably make a living by simply being good at it.

However, because it encapsulates the interpretation of various Java Specifications, hides the complexity of design and implementation, often the framework itself imposes a serious impediment for developers to understand the underlining fundamentals.

Many Spring Boot developers don’t know Spring Boot is just a framework on top of another popular framework Spring Framework, which was initially a framework for Java Servlet applications. Most freshly-minted Spring Boot developers never heard of Servlet, not to mention web.xml. They only know their Spring Boot applications, “just run”. They never know why and how it runs.

Because of that, they never think of what the underlining Servlet Container is, what the default configurations (like Max Concurrent Requests) are, and how to fine tune those configurations. Imagine asking them to write a Java Web Application without Spring Boot?

Frameworks tend to wrap a lot of default features and behaviors under the hood, just to name a few: default Encryption Algorithm, default Socket Timeout, default Retry Strategy.

In the past, Frameworks might have configuration property for each “feature”, but this has changed in the recent years. Nowadays, Framework authors tend to favor “Convention over configuration”. Old configuration files are replaced by annotations with “sensible defaults”. Moreover, many of the features and behaviors are “discovered” automatically based on your running environments, like system properties, environment variables and what is in the class-path.

Several years back, I led a framework team. We built a Framework as the foundation for a slew of web applications that support multi-million $ business. We worked very hard to support all major features by default, and still allow each application to extend and override each feature by configuration and automatic discovery. I learned first hand, it’s even harder for application developers to fully understand how each feature worked and how to extend or override them.

Naturally, due to the lack of visibility and transparency of frameworks, people makes a lot of assumptions about frameworks, such as Singleton bean thread-safety. Some of the assumptions will definitely haunt the team down the road if the technical leads on the team didn’t review the design and code carefully.

Overtime, frameworks will evolve or die. If you ever worked with Struts 1.x framework, and if you didn’t understand Java Servlet, you would have a difficult time to migrate your applications to Struts 2.x or Spring.

Frameworks are your tools, not your crutches. If you don’t think out of the box of Spring Boot, you can’t professionally outgrow Spring Boot. Simple. Period.

That is true to other frameworks too.

Frameworks can help you get started quickly, but understanding the underlining principles will help you in the long run.

浅谈Web缓存

来自:腾讯AlloyTeam Blog

by TAT.yana

链接:http://www.alloyteam.com/2016/03/discussion-on-web-caching/(点击尾部阅读原文前往)

在前端开发中,性能一直都是被大家所重视的一点,然而判断一个网站的性能最直观的就是看网页打开的速度。其中提高网页反应速度的一个方式就是使用缓存。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。那么下面我们就来看看服务器端缓存的原理。

缓存分类

web缓存分为很多种,比如数据库缓存、代理服务器缓存、还有我们熟悉的CDN缓存,以及浏览器缓存。对于太多文字的阅读其实我是拒绝的,于是就画了个图来解释下。

浏览器通过代理服务器向源服务器发起请求的原理如下图,

浏览器先向代理服务器发起Web请求,再将请求转发到源服务器。它属于共享缓存,所以很多地方都可以使用其缓存资源,因此对于节省流量有很大作用。

浏览器缓存是将文件保存在客户端,在同一个会话过程中会检查缓存的副本是否足够新,在后退网页时,访问过的资源可以从浏览器缓存中拿出使用。通过减少服务器处理请求的数量,用户将获得更快的体验

下面我就来着重讲下传说中的浏览器缓存。

浏览器缓存

页面的缓存状态是由header决定的,header的参数有四种:

一、Cache-Control:

1、max-age(单位为s)指定设置缓存最大的有效时间,定义的是时间长短。当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。

我们来找个资源看下。比如shang.qq.com上的css资源,max-age=2592000,也就是说缓存有效期为2592000秒(也就是30天)。于是在30天内都会使用这个版本的资源,即使服务器上的资源发生了变化,浏览器也不会得到通知。max-age会覆盖掉Expires,后面会有讨论。

2、s-maxage(单位为s)同max-age,只用于共享缓存(比如CDN缓存)。

比如,当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。也就是说max-age用于普通缓存,而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖掉max-age和Expires header。

3、public 指定响应会被缓存,并且在多用户间共享。也就是下图的意思。如果没有指定public还是private,则默认为public。

4、private 响应只作为私有的缓存(见下图),不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。

5、no-cache 指定不缓存响应,表明资源不进行缓存,比如,

但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。

6、no-store 绝对禁止缓存,一看就知道如果用了这个命令当然就是不会进行缓存啦~每次请求资源都要从服务器重新获取。

7、must-revalidate指定如果页面是过期的,则去服务器进行获取。这个指令并不常用,就不做过多的讨论了。

二、Expires

缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。但在上面我们提到过,cache-control的优先级更高。 Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

三、Last-modified 

服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则返回码为304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为200,资源为服务器最新资源。

如下图,最后修改时间为2014年12月19日星期五2点50分47秒

四、ETag

 

根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生。浏览器会将这串字符串传回服务器,验证资源是否已经修改,如果没有修改,过程如下:

使用ETag可以解决Last-modified存在的一些问题:

a、某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新

b、如果资源修改非常频繁,在秒以下的时间内进行修改,而Last-modified只能精确到秒

c、一些资源的最后修改时间改变了,但是内容没改变,使用ETag就认为资源还是没有修改的。

使用缓存流程

还是用图说话,下面是我所总结的从浏览器请求到展示资源的过程:

cache-control指令使用

说了那么多cache-control的指令,那么如何选择使用哪些指令呢?我还是不说话==

额外的

除了开头提到的那么多缓存方式以外,还有一种我们都熟悉的缓存方式,LocalStorage和sessionStorage(好像是两种23333)。

LocalStorage是一种本地存储的公共资源,域名下很多应用共享这份资源会有风险;LocalStorage是以页面域名划分的,如果有多个等价域名之间的LocalStorage不互通,则会造成缓存多份浪费。

LocalStorage在PC上的兼容性不太好,而且当网络速度快、协商缓存响应快时使用localStorage的速度比不上304。并且不能缓存css文件。而移动端由于网速慢,使用localStorage要快于304。

在html中加载一个png图,首次加载的时候时间如下图,

然而将图片使用了LocalStorage存储后,再次刷新后加载时间为0。

而相对LocalStorage来说,SessionStorage的数据只存储到特定的会话中,不属于持久化的存储,所以关闭浏览器会清除数据。和localstorage具有相同的方法。

在前端开发中缓存是必不可少的,那么使用怎样的缓存方式更高效、让我们项目的性能更优,还是需要我们仔细斟酌。

C++的反思

来自:Skywind Inside

作者:skywind

链接:http://www.skywind.me/blog/archives/1398

最近两年 C++又有很多人出来追捧,并且追捧者充满了各种优越感,似乎不写 C++你就一辈子是低端程序员了,面对这种现象,要不要出来适时的黑一下 C++呢?呵呵呵。

咱们要有点娱乐精神,关于 C++的笑话数都数不清:

笑话:C++是一门不吉祥的语言,据说波音公司之前用ADA为飞机硬件编程,一直用的好好的,后来招聘了一伙大学生,学生们说我靠还在用这么落后的语言,然后换成C++重构后飞机就坠毁了。

笑话:什么是C++程序员呢?就是本来10行写得完的程序,他非要用30行来完成,并自称“封装”,但每每到第二个项目的时候却将80%打破重写,并美其名曰 “重构”。

笑话:C容易擦枪走火打到自己的脚,用C++虽然不容易,但一旦走火,就会把你整条腿给炸飞了。

笑话:同时学习两年 Java的程序员在一起讨论的是面向对象和设计模式,而同时学习两年 C++的程序员,在一起讨论的是 template和各种语言规范到底怎么回事情。

笑话:教别人学 C++的人都挣大钱了,而很多真正用 C++的人,都死的很惨。

笑话:C++有太多地方可以让一个人表现自己“很聪明”,所以使用C++越久的人,约觉得自己“很聪明”结果步入陷阱都不知道,掉坑里了还觉得估计是自己没学好 C++。

笑话:好多写了十多年 C++程序的人,至今说不清楚 C++到底有多少规范,至今仍然时不时的落入某些坑中。

笑话:很多认为 C++方便跨平台的人,实际编写跨平台代码时,都会发现自己难找到两个支持相同标准的 C++编译器。

—————

Q:那 C++为什么还能看到那么多粉丝呢?

A:其实是因为 Windows,因为 Windows的兴起带动了 C++,C++本来就是一门只适合开发 GUI的语言。

Q:为何 C++只适合开发 GUI呢?

A:你看 Unix下没有 GUI,为啥清一色的 C呀?所有的系统级问题都能在 C里找到成熟的解决方案,应用级问题都能用其他高级语言很好地解决,哪里有 C++什么事情呀?

Q:你强词夺理,Unix下也有 C++的项目呀。

A:有,没错,你任然可以用任何语言编写任何糟糕的代码。

Q:别瞎扯了,你都在说些什么?连C++和 Windows 都扯到一起去了。

A:回想下当年的情景,一个大牛在教一群初学者如何编程。一边开发一边指着屏幕上说,你看,这是一个 Button,我们可以用一个对象来描述它,那是一个 panel我们也可以用一个对象来描述它,并且你们有没有发现,其实 Button和 Panel是有血缘关系的,你们看。。。这样就出来了。。。。下面的学生以前都是学着学校落后的教材,有些甚至还在用 turboc的 bgi库来画一些点和圆。哪里见过这么这么华丽的 Windows 界面呀。大牛说的话,象金科玉律一样的铭刻在自己幼小的心理。一边学着 Windows,一边发现,果然,他们都需要一个基类,果然,他们是兄弟关系,共同包含一些基本属性,可以放到基类去。他们越用越爽,潜意识里觉得因为 C++这么顺利的帮他们解决那么多界面问题,那看来 C++可以帮他们解决一切问题了。于是开发完界面以后,他们继续开发,当他们碰到各种设计问题时,反而认为肯定自己没有用好 C++。于是强迫自己用下去,然后就完蛋了。

(点击 more展开)

—————

关于 C++的笑话我有一箩筐,各位 C++粉用不着对号入座。言归正传,为什么要黑 C++呢?谈不上黑不黑,我从94年开始使用 C++(先前是 C 和 Pascal),一路看着 C++成长壮大,用 C++写过的代码,加起来应该超过 10MB了吧,C++的各种宝典我也都读过,一直到 2004年开始切回 C,主要原因是发现很多没法用 C++思路继续解决下去的问题,或者说用 C++思路解决下去会很糟糕的问题。

那时候(2004-2005)正是 C++满天飞的时候,言必称 C++,用必用模版,我跳出来说你们醒醒吧,别过火了,这个世界并不是都是抽象数据结构和算法就可以描述清楚的。于是很多人激动的跳出来说:“你没领会到 C++精髓,你根本都不会用 C++”。我问他们:“语言是用来解决问题的,如果一个语言学了三四年都会经常掉沟里,算好语言么?如果编写十多年 C++的程序员都很难掌握得了,这算好语言么”。他们又说:“语言是死的,人是活的”。

我记得当时一位国内 C++大牛,为了纠正我的 “错误观点”,给我看过他写的一套十分强大的库,我打开一看,倒吸了一口冷气,全部是 .h文件。我只能回他三个字:“你牛逼”。当然这是一个极端的例子,那家伙后来终于也开始把 .h里面的东西逐步挪到 .cpp里面了,这是好事。

当时和云风在一家公司,2004年新人培训时,他给新人布置了一个实现内存分配器的作业,批改作业的时候,他经常边看边问人家,“不够C++呀,你能不能百分之百OOP?”,“1%的 C都不要留”。我当时在公司内部邮件列表里面发过关于 C++的问题,大部分人都表示:“你看没有C++我们怎么写3D引擎呢?”。我跟他们讲:“John Carmack直到 Quake3都还在用着 ANSI C,后来因为不得不支持 D3D,改用 C++了。为啥 C不能写 3D引擎了?”。他们告诉我:“你看,Point,就是个对象,Matrix也是个对象,那么多 Vector的代数计算,用 C++的算术重载是多么美妙的事情,三维世界就是对象的世界。”。

确实当时客户端 GUI的话,只有 C++,图形引擎也只有 C++,这两个正是C++最强的地方,所以我也没和他们争辩,强迫他们承认 C也可以很漂亮的写图形,而且C写的可以写的很优雅。我又不是闲着没事情,何必去质疑人家的核心价值观呢,呵呵。当年我正在接手一个 C++项目,代码超过 800KB,每次崩溃都需要花费很长时间去定位,项目中大量的前后依赖,改一个地方,前后要看好几处,一处遗漏,整个系统就傻逼了。我开始重构后,画了两个星期,将性能敏感的核心部分剥离出来用 C实现(代码量仅 200KB),然后导出 Python接口,用Python来完成剩下的部分,整个脚本层代码量只有 150KB。整个世界清爽了,整个 C++项目原来的工期为 2个程序员四个月,我一个人重构的时间加起来就 1.5个月,而且代码量比远来少了两倍还多,各种奇特的 BUG也一扫而尽。我看看左边的 800KB一团乱麻的 C++代码,再看看右边整洁的 300多 KB 纯 C + Python,琢磨着,这个项目干嘛不一开始就这么做?

跨语言接口

现代项目开发,不但需要更高的性能,而且需要更强大的语言描述能力。而 C++正处在一个尴尬的地方,比底层,它不如 C能够精确的控制内存和硬件,各种隐式构造让你防不胜防;比描述能力,比快速业务开发和错误定位,它又赶不上 Python, Ruby, Lua等动态语言,处于东线和西线同时遭受挤压和蚕食的地步。

很快,2006-2007年左右,其他项目组各种滥用 C++的问题开始显现出来:当时脚本化已经在工程实践中获得极大的成功,然而某些项目一方面又要追求 100%的 C++,另一方面又需要对脚本导出接口,他们发现问题了,不知道该怎么把大量的 C++基础库和接口导给 Lua。

C的接口有各种方便的方式导给脚本,然而整个项目由一群从来就不消于使用脚本的cpp大牛开发出来,当他们要吧cpp类导出接口给脚本时,他们设计了一套牛逼的系统,lua自动生成机器码,去调用c++的各种类,没错,就是c++版本的cffi或者ctypes。他为调用vc的类写了一套机器码生产,又为调用gcc的类写了一套代码生成。那位cpp大牛写完后四处炫耀他的成果,后来他离职了,项目上线一而再再而三的出现无可查证的问题,后来云风去支援那个项目组,这套盘根错节的c++项目,这套盘大的代码自生成系统深深的把他给恶心到了。后来众所周知云风开始反C++,倡导回归C了,不知道是否和这个项目有关系。

于是发现个有趣的现象,但凡善于使用脚本来提高工程效率的人,基本都是C加动态语言解决大部分问题(除了gui和图形),但凡认为c++统治宇宙的人很多都是从来没使用过脚本或者用了还不知道该怎样去用的人。

凭借这样的方法,我们的产品同竞争对手比拼时,同样一个功能,同样的人力配置,竞争对手用纯C++要开发三月,我们一个月就弄出来了,同样的时间,对手只能试错一次,我们可以试错三次。后来,据我们招聘过来的同事说,竞争对手也开始逐步降低 C++的比例,增加 java的比例了,这是好事,大家都在进步嘛。

ABI的尴尬

ABI级别的 C++接口从来没有标准化过,以类为接口会引入很多隐藏问题,比如内存问题,一个类在一个库里面实例化的,如果再另外一个库里面释放它们就有很多问题,因为两个动态库可能内存管理系统是不一样的。你用这里的 allocator分配一块内存,又用那里的 allocator去释放,不出问题才怪。很多解决方法是加一个 Release 方法(比如 DX),告诉外面的人,用完的时候不要去 delete,而是要调用 Release。

项目写大了各个模块隔离成动态库是很正常的,而各种第三方库和自己写的库为追求高性能引入特定的内存管理机制也是很正常的。很多人不注意该调用release的地方错写成delete就掉沟里去了。更有胜者跨 ABI定义了很多inline方法的类,结果各种隐式构造和析构其实在这个库里生成,那个库里被析构,乱成一团乱麻。C就清晰很多,构造你就调用fopen,析构你就fclose,没有任何歧义。其实C++的矛盾在于一方面承认作为系统级语言内存管理应该交给用户决定,一方面自己却又定义很多不受用户控制的内存操作行为。所以跨 ABI层的c++标准迟迟无法被定义出来,不是因为多态 abi复杂,而是因为语言逻辑出现了相互矛盾。为了弥补这个矛盾,C++引入了operator new,delete,这new/delete重载是一个补丁并没从逻辑上让语言变得完备,它的出现,进一步将使用者拖入bug的深渊。

其实今天我们回过头去看这个问题,能发现两个基本原则:跨abi的级别上引入不可控的内存机制从语言上是有问题的,只能要靠开发者约定各种灵巧的基类和约定开发规范来解决,这个问题在语言层是解决不了的;其次你既然定义了各种隐式构造和析构,就该像java活着动态语言一样彻底接管内存,不允许用户再自定义任何内存管理方法,而不是一方面作为系统极语言要给用户控制的自由,一方面自己又要抢着和用户一起控制。

因此对象层 ABI接口迟迟无法标准化。而纯 C的 ABI不但可以轻松的跨动态库还能轻松的和汇编及各类语言融合,不是因为C设计多好,而是C作为系统层语言没有去管它不该管的东西。当年讨论到这个话题时 C++大牛们又开始重复那几句金科玉律来反驳我:“语言只是招式,你把内功练好,就能做到无招胜有招,拿起草来都可以当剑使,C++虽然有很多坑,你把设计做好不那么用不就行了”。我说:本来应该在语言层解决好的事情,由于语言逻辑不完备,将大量问题抛给开发者去解决极大的增加了开发者的思维负担,就像破屋上表浆糊一样。你金庸看多了吧,武术再高,当你拿到一把枪发现子弹不一定往前射,偶尔还会往后射时,请问你是该专心打敌人呢?还是时刻要提防自己的子弹射向自己?

系统层的挫败

C++遭受挫败是进军嵌入式和操作系统这样靠近硬件层的东西。大家觉得宇宙级别的编程语言,自然能够胜任一切任务,很快发现几个问题:

●无法分配内存:原来用 C可以完全不依赖内存分配,代码写几千行一个 malloc没有都行。嵌入式下处理器加电后,跳到特定地址(比如起始地址0),第一条指令一般用汇编来写,固定在0地址,就是简单初始化一下栈,然后跳转到 C语言的 start函数去,试想此时内存分配机制都还没有建立,你定义了两个类,怎么构造呀?资源有限的微处理器上大部分时候就是使用一块静态内存进行操作。C++写起来写爽了,各种隐式构造一出现,就傻了。

●标准库依赖:在语言层面,C语言的所有特性都可以不用依赖任何库就运行,这为编写系统层和跨平台跨语言代码带来了很方便的特性。而C++就不行,我要构造呀,我要异常呀,你为啥不能给我强大的运行时呢?什么你还想用 stl?不看看那套库有多臃肿呀(内存占用,代码尺寸)。

●异常处理问题:底层开发需要严格的处理所有错误返回,这一行调用,下一行就判断错误。而异常是一种松散的错误处理方式,应用层这么写没问题,系统层这么写就很狼狈了。每行调用都try一下和 C的调用后if判断结果有什么区别?C++的构造函数是没有返回值的,如果构造内部出错,就必须逼迫你catch构造函数的异常,即便你catch住了,构造异常的时候当然会自动触发相关内部对象的析构,但是有很多并没有析构的资源(比如系统资源,比如C接口的资源,他们都没有一个析构),整个过程是很难控制的,此时这个实例是一个半初始化实例,你该怎么处理它呢?于是有人把初始化代码移除构造函数,构造时只初始化一下变量,新增加一个带返回的init函数,这样的代码写的比C冗余很多。何况硬件中断发生时,在你不知道的情况下,同事调到一些第三方的库,你最外层没有把新的exception给 catch住,这个exception该往哪里抛呀?内存不够的时候你想抛出一个 OutOfMemoryException,可是内存已经不够了,此时完全无能力构造这个异常又该怎么办呢?

●处理器兼容:C++的类依赖基地址+偏移地址的寻址方式,很多非 Intel系列的微处理器上只有简单的给定地址寻址,不支持这样一条语句实现BASE+OFFSET的寻址,很多C++代码编译出来需要更多的指令来运算地址,导致性能下降很多,得不偿失。

●隐式操作问题:C的特点是简单直接,每行语句你都能清楚的知道会被翻译成什么样子,系统会严格按照你的代码去执行。而用C++,比如 str1 = str2 + “Hello” + str3; 这样的语句,没几个人真的说得清楚究竟有多少次构造和拷贝,这样的写法编写底层代码是很不负责任的,底层需要更为精细和严格的控制,用C语言控制力更强。

当然,说道这里很多人又说,“C++本来就是 C的超集,特定的地方你完全可以按照C的写法来做呀。没人强迫你构造类或者使用异常呀”,没错,按 Linus的说法:“想要用 C++写出系统级的优秀的可移植和高效的代码,最终还是会限于使用 C本身提供的功能,而这些功能 C都已经完美提供了,所以系统层使用 C的意义就在于在语言层排除 C++的其他特性的干扰”。

很多人都记得 Linus在 2007年因为有人问 Git为什么不用 C++开发炮轰过一次C++。事实上2004年 C++如日中天的时候,有人问 Linux内核为何不用 C++开发,他就炮轰过一次了:

实际上,我们在1992年就尝试过在Linux使用 C++了。很恶心,相信我,用C++写内核是一个 “BLOODY STUPID IDEA”。事实上,C++编译器不值得信任,1992年时它们更糟糕,而一些基本的事实从没改变过:

– 整套 C++异常处理系统是 “fundamentally broken”。特别对于编写内核而言。

– 任何语言或编译器喜欢在你背后隐藏行为(如内存分配)对于开发内核并不是一个好选择。

– 任然可以用 C来编写面向对象代码(比如文件系统),而不需要用 C++写出一坨屎来。

总得来说,对任何希望用 C++来开发内核的人而言,他们都是在引入更多问题,无法象 C一样清晰的看到自己到底在写什么。

C++粉丝们在C++最火热的时候试图将 C++引入系统层开发,但是从来没有成功过。所以不管是嵌入式,还是操作系统,在靠近硬件底层的开发中,都是清一色的 C代码,完全没有 C++的立足之地。

应用层的反思

STL出来后,给人一种 C++可以方便开发应用层逻辑的错觉。由于很多语言层不严密的事情,让STL来以补丁的方式完成,于是很多以为可以象写 java一样写 C++的初学者落入了一个个的坑中。比如 list.size(),在 Windows下vc的 stl是保存了 list的长度的,size()直接 O(1)返回该变量,而在gcc的 stl中,没有保存 list长度,size()将搜索所有节点,O(n)的速度返回。

由于语言层不支持字符串,导致 std::string实现十分不统一,你拷贝构造一个字符串,有的实现是引用,才用 copy-on-write的方法引用。有的地方又是 new,有的实现又是用的内存池,有的实现线程安全,有的实现线程不安全,你完全没法说出同一个语句后面到底做了些什么(见孟岩的《Linux之父话糙理不糙》)。

再比如说我想使用 hash_map,为了跨平台(当你真正编写跨平台代码时,你很难决定目标编译器和他们的版本,想用也用不了 unordered_map),我很难指出一种唯一声明 hash_map的方法,为了保证在不同的编译器下正常的使用 hash_map,你不得不写成这样:

#ifdef __GNUC__

#ifdef __DEPRECATED

#undef __DEPRECATED

#endif

#include <ext/hash_map>

namespace stdext { using namespace __gnu_cxx; }

namespace __gnu_cxx {

template<> struct hash< std::string > {

size_t operator()( const std::string& x ) const {

return hash< const char* >()( x.c_str() );

}

};

}

#else

#ifndef _MSC_VER

#include <hash_map>

#elif (_MSC_VER < 1300)

#include <map>

#define IHAVE_NOT_HASH_MAP

#else

#include <hash_map>

#endif

#endif

#ifdef __GNUC__

using namespace __gnu_cxx;

typedef hash_map<uint32_t, XXXX*> HashXXXX;

#else

using namespace stdext;

typedef hash_map<uint32_t, XXXX*> HashXXXX;

#endif

如果有更好的跨平台写法,麻烦告诉我一下,实在是看不下去了。一个基础容器都让人用的那么辛苦,使得很多 C++程序员成天都在思考各种规范,没时间真正思考下程序设计。

由于语言层要兼容 C,又不肯象 C一样只做好系统层的工作,导致当 C++涉足应用层时,没法接管内存管理,没法支持语言层字符串,没法实现语言层基础容器。所以需要借助一些 stl之类的东西来提供便利,但 stl本身又是充满各种坑的。且不说内存占用大,程序体积大等问题,当编译速度就够呛了。所以为什么 C++下面大家乐意重复造轮子,实现各种基本容器和字符串,导致几乎每个不同的 C++项目,都有自己特定的字符串实现。就是因为大家踩了坑了,才开始觉得需要自己来控制这些细节。stl的出发点是好的,但是只能简单小程序里面随便用一下,真是大项目用,stl就容易把人带沟里了,所以很多大点的 C++项目都是自己实现一套类似 STL的东西,这难道不是违背了 stl设计的初衷了么?

语言层的缺失,让大家为了满足业务开发的快速迭代的需求,创造了很多很基础的设计灵巧的基类,来提供类似垃圾回收,引用计数,copy-on-write,delegate,等数不胜数的功能。每个项目都有一系列 BaseObject 之类的基础类,这样就引入一个误区,两年后你再来看你的代码,发现某个 BaseObject不满足需求了,或者你和另外一个项目 merge代码时,需要合并一些根本属性。图形和GUI这些万年不变的模型还好,应用类开发千变万化,一旦这些设计灵巧的基类不再适应项目发展时,往往面临着全面调整的代价。

打开一个个 C++大牛们 blog,很多地方在教你 std::string的原理,需要注意的事项。map的限制,vector的原理,教你如何实现一个 string。这就叫 “心智负担”,分散你的注意力,这是其他语言里从来见不到的现象。战士不研究怎么上前线杀敌,天天在琢磨抢和炮的原理,成天在思考怎么用枪不会走火,用炮不会炸到自己,这战还怎么打?

所以此后几年,越来越多的人开始反思前两年C++过热所带来的问题,比如高性能网络库 ZeroMQ作者 Martin Sustrik 的:《为什么我希望用C而不是C++来实现ZeroMQ》,比如云风的《云风的 BLOG: C 的回归》,比如引起热议的《Why C++ Is Not “Back”》。

全面被代替

2008年以后,行业竞争越来越激烈,正当大家一边苦恼如何提高开发效率,一边掉到C++的各种坑里的时候,越来越多的应用开发方案涌现出来,他们都能很好的代替 C++。各行各业的开发者逐步相见恨晚的发现了各种更加优秀的方案:需要底层控制追求性能的设计,大家退回到 C;而需要快速迭代的东西大家找到各种动态语言;介于性能和开发速度之间的,有java,知乎上好像很多黑java的,语言是有不足,但是比起C++好很多,没那么多坑,真正考虑面向对象,真正让人把心思放在设计上。所以再黑也不能挡住 java在 tiobe上和 C语言不是第一就是第二的事实,再黑也挡不住 java在云计算,分布式领域的卓越贡献。

所以2005年以后,C++处在一个全面被代替的过程中:

●底层系统:进一步回归 C语言,更强的控制力,更精确的操作。

●网页开发:2006年左右,C++和 fastcgi就被一起赶出 web世界了。

●高性能服务:varnish, nginx, redis 等新的高性能网络服务器都是纯C开发的。

●分布式应用:2007年左右, C++被java和其他动态语言彻底赶跑。

●游戏服务端:2008年后进一步进化为 C 和 脚本,完全看不到胖C++服务端了。

●并行计算:2010年后,go, scala, erlang;而能方便同go接口的,是 C不是C++。

●游戏引擎:没错 C++和脚本,但是这年头越来越多的开源引擎下,引擎类需求越来越少。

●游戏逻辑:脚本

●多媒体:SDL纯C,ffmpeg是纯 C,webrtc的核心部分(DSP, codec)是纯C的。

●移动开发:早年C++还可以开发下塞班,现在基本被 java + objc + swift 赶跑了。

●桌面开发:Qt+Script, C#等都能做出漂亮的跨平台界面。且界面脚本化趋势,不需要C++了。

●网页前端:JavaScript, Html5, Flash

●操作系统:FreeBSD, Open Solaris, Linux, RTOS, Darwin(OS X 底层),都是纯 C

●虚拟技术:qemu / kvm (云计算的基石)纯 C,Xen 纯 C

●数据库:MySQL (核心纯C,外围工具 C++),SQLite 纯 C, PostgreSQL / BDB / unqlite 纯C

●编译器:C/C++并存,不过编译器用脚本写都没关系,我还在某平台用 java写的 C/C++编译器

●大数据:kafka, hadoop, storm, spark 都使用 Java / Jvm 系列技术

●云存储:openstack swift python, hdfs java, 还有好多方案用 go

可以看出,即便 C++的老本行,GUI和图形(确实也还存在一些短期内 C++无法替代的领域,就像交易系统里还有 COBOL一样),这年头也面临的越来越多的挑战,比如新发布的 Rust (如何看待 Rust 的应用前景? – 知乎用户的回答)。可以发现,开发技术多元化,用最适合的技术开发最适合的应用是未来的趋势。而为这些不同的技术编写高性能的可控的公共组件,并轻松的和其他语言接口,正是 C语言的强项。所以不管应用层语言千变万化,对系统级开发语言C的需求还是那么的稳定,而这个过程中,哪里还有 C++的影子呢?

话题总结

所以说未来的趋势是:C x 各种语言混搭 的趋势,从TIOBE上 C++的指数十年间下跌了三倍可以看出,未来还会涌现出更多技术来代替各个角落残存的C++方案,C++的使用情况还会进一步下降。所以题主问学习纯C是否有前途,我觉得如果题主能够左手熟练的掌握 C语言,培养系统化的思维习惯和精确控制内存和硬件的技巧;右手继续学习各种新兴的开发技术,能够应对各个细分领域的快速开发,碰到新问题时能左右开弓,那么未来工作上肯定是能上一个大台阶的。至于C++ 嘛,有时间看看就行,逼不得已要维护别人代码的情况下写两行即可。

故事分享

古代用弓箭进行远距离攻击时,对射手要求较高,瞄准难度大,需要一直使劲保持准心。战斗中一个弓箭手开弓二十次就需要比较长的休息时间。弩的威力远胜于弓,秦弩的制造就如现代的自动步枪一般精密无二,它既可以延长射击,又可以精确瞄准。弩箭的发射速度更是弓箭的数倍,威力惊人。因为弩的操作非常简单,不需要射击技巧,平民很容易掌握它的使用方法。秦国靠着弩兵,在战争中取得了不少优势,被人称为 “虎狼之师”。

日本投降时,天皇下罪己诏。很多士兵不愿意相信这时真的,找种种理由拒绝相信。有的士兵甚至以为天皇的广播是敌人诱降的把戏,于是躲到丛林里继续三五成群的收集情报,袭击可以攻击的目标,等待上司来给他们下达新命令。直到好几年后看到周围的人都穿着日常的便装了,而来巡山的 “敌人” 也从士兵变为了巡逻队,他们都还觉得这是敌人的伪装。而同时,德国战败时,最后的党卫军一直战斗到 1957年才肯投降。

—————————————–

很多人觉得Java慢,C++快Java 10倍以上已经是上世纪的事情了,现代的 Java 只比 C/C++慢 70%,C++连1倍都快不了 Java。也不要觉得动态语言慢,javascript只比C/C++慢 2.7倍。luajit只比 C++慢 5.8倍。在 jit技术发展的今天,C++在性能上离动态语言/java的差距越来越小,可易用性和生产效率上的差距,却和动态语言/java 比起来越来越大。

—————————
最后,补充一张图:

How to Learn JavaScript Properly

Source: http://javascriptissexy.com/how-to-learn-JavaScript-properly/

Learn JavaScript Properly (For Beginners and Experienced Programmers)

This study guide, which I also refer to as a course outline and a road map, gives you a structured and instructive outline for learning JavaScript properly. In fact, you will find two study guides below, one for absolute beginners and the other for experienced programmers and web developers.

Our Career Paths and Courses Website Is Now Live

Learn.Modern Developer Launched

Our first cohort is in session: 97% of our first cohort on target to graduate. Enroll in the second cohort. Career Path 1: JavaScript Developer and Career Path 3: Modern Frontend Developer usually fill up quickly.

https://learn.moderndeveloper.com

You do want to learn JavaScript. I presume you are here for that reason, and you have made a wise decision. For if you want to develop modern websites and web applications (including an internet startup), or if you want a high-paying developer job ($75K to $250K+), JavaScript is undoubtedly the best web-development language to learn today, unless you want to develop native iOS or Android apps exclusively. And while there exist ample online resources to teach you JavaScript, finding the most efficient and beneficial method to learn the “language of the web” can be a frustrating endeavor. This study guide streamlines and simplifies the process; it has proven successful in helping thousands, and thousands more read and follow it each day.

Study Groups
People have started study groups for this study guide. You can find such groups on Reddit here and here, and other places, including Code Crew Meetup.

What You will Learn

You will learn the JavaScript language (up to advanced-intermediate, if you follow the “Beginners” study guide; or up to advanced, if you follow the “Experienced Programmers” study guide). You will also learn HTML, CSS, jQuery, and Git. And you will build a simple HTML/CSS website, an interactive HTML/CSS/JavaScript website, and a moderately sophisticated JavaScript quiz application.

  • Receive Updates

How Will Your Life Change After You Learn JavaScript Properly?

Maybe you will look more lovely and have a kinder, more pleasant personality after you learn JavaScript properly. Who knows? I don’t know.

But I do know that you will emerge more confident, more assured in your ability, and amply trained with a highly valued skill—a skill more valuable than most college degrees. For as a JavaScript developer, you will have the capacity not only to create whatever startup or web app you imagine, but also to work, making a handsome salary, as a front-end or full-stack developer, developing modern and futuristic applications. In fact, if you have never developed any kind of application before, you will experience ecstasy, so exultant and euphoric that you will want to enthusiastically practice more and build something—anything, like a hungry chef discovering a furnished kitchen with every tool, every utensil, and a stocked refrigerator.

It is worth noting that unlike just a couple of years ago—when you needed to know a true server-side language (such as PHP, Rails, Java, Python, or Perl) to develop scalable, dynamic, and database-driven web applications—today you can do as much and more with JavaScript alone.

This is the flourishing and glorious age of the JavaScript developer.

Be Empowered

This course outline transcends an entire semester of college coursework. If you complete the study guide, you will have learned enough programming to develop modern web applications, and with a bit of experience and a couple of completed projects, you will have become a sought-after programmer. Indeed, JavaScript developers are in high demand today. But you must prove your worth by developing a few impressive (interesting and non-trivial, though not necessarily complex) web applications.

How NOT To Learn JavaScript

  • Do not try to learn JavaScript the first time from bits of unrelated or related JavaScript tutorials online; this is the worst way to learn a programming language. It could work for some after countless such tutorials, but it is an inefficient process that lacks the proper hierarchical structure needed for learning a subject matter thoroughly. And this could lead to your being stuck quite frequently, when you start to build websites and web applications with the language. In short, you will not have the know-how—the comprehensive knowledge—you need to use that language as a tool—as your tool.
  • In addition, some will recommend you learn JavaScript from “JavaScript: The Good Parts,” by the venerable Douglas Crockford. While many regard Mr. Crockford as a JavaScript godfather, his book, The Good Parts, is not the best JavaScript book for beginners. It does not explain JavaScript’s core concepts in a detailed, clear, and easily digestible form. I do recommend you follow Crockford’s advanced videos, however, as part of the Learn Advanced JavaScript road map.
  • And do not try to learn the language by using only Codecademy; while you will learn how to program bits of small JavaScript tasks, you will not have learned enough to build complex web applications. Nonetheless, below I do recommend Codecademy as a supplemental learning resource.

Resources for the Two Study Guides

I have outlined two different study guides below, one for beginners and one for experienced web developers.

  1. Beginners should follow the Learn JavaScript Properly Study Guide for Beginners and get this book:
    Beginning JavaScript.Experienced programmers and web developers should follow the Learn JavaScript Properly Study Guide for Experienced Programmers and get this book:
    — The paperback Version: Professional JavaScript for Web Developers (3rd Edition)
    — The Kindle Version: Professional JavaScript for Web Developers (3rd Edition)
  2. Sign up for an account on Stack Overflow (a FREE service). It is a forum for asking and answering programming questions. This website will be considerably more useful than Codecademy for answering your programming questions, even very basic, seemingly stupid (remember, there is never a stupid question) questions.
  3. Sign up for an account on Codecademy. We will complete 4 Codecademy tracks. Codecademy is an online platform to learn programming: you can write code on their website, right in your browser. (It is also a FREE service.)
  4. JavaScriptIsSexy.com (this blog :) ): We will read 4 articles
  5. CodeSchool.com: We will complete 1 free course

Resources:
Beginning JavaScript (4th Edition)
— JavaScriptIsSexy.com (4 articles)
— Codecademy.com (4 tracks)
— CodeSchool.com (1 short course)
Notice for Visual Learners: If you are a visual learner, that is, if you prefer to see lots of images, schematics, and the like when learning a topic, you may find JavaScript and jQuery: Interactive Front-End Web Development more appealing than the Beginning JavaScript book. If you do get the JavaScript and jQuery book, note that the chapters are similar enough that you can use it (instead of Beginning JavaScript) to follow this study guide, though you will have to modify the sections a bit.

Learn JavaScript Properly Study Guide for Beginners

Prerequisite: Completed at least some high school (no programming experience necessary)

The Level of JavaScript Covered in this Study Guide: Absolute Beginner to Intermediate

How to Get the Best Out of This Study Guide

Type out and test every example code you encounter in the book. You can type the code and tweak it (experiment with it) in Firefox’s or Chrome’s console. The browser console is an area of the browser where you can write and run JavaScript code. Or use JSFiddle. JSFiddle is a web application that allows you to write and test your code online, right in your browser. You can test all sorts of code, including a combination of HTML, CSS, and JavaScript (and jQuery).

Don’t use Safari. I recommend Chrome, but if you use Firefox, get the Firebug Add on for Firefox; use it for testing and debugging your code.

Watch this Firefox’s and Chrome’s Console Tutorial on YouTube.

And watch this Chrome Dev Tools Tutorial (also on YouTube) to learn how to use Chrome Dev Tools.

Also, work all the end-of-chapter exercises.

Let’s get to work.

Weeks 1 and 2

Week 1: Making a Website with HTML and CSS; Learn JavaScript Data Types, Functions, Control Flow, and Loops

  1. Codecademy.com: If you do not already know HTML and CSS, complete the Web Fundamentals Track on Codecademy.
  2. Codecademy.com: Then follow the Make a Website track to make your first little website, using what you learned above.
  3. Beginning JavaScript: Read Chapter 1 (Introduction to JavaScript and the Web) and Chapter 2 (Data Types and Variables).
  4. Beginning JavaScript: Read Chapter 3 (Decisions, Loops, and Functions).
  5. Codecademy.com: Work through the JavaScript Track on Codecademy. Specifically, work through these sections: “Introduction to JavaScript,” “Functions,” “‘For’ Loops in JavaScript,” “‘While’ Loops in JavaScript,” and “Control Flow.”
  6. Beginning JavaScript: Read Chapter 4 (Common Mistakes, Debugging, and Error Handling).

Week 2: Learn JavaScript Objects, the Browser Object Model (BOM), and Events; Learn jQuery

  1. Beginning JavaScript: Read Chapter 5 (JavaScript — An Object- Based Language).
  2. JavaScriptIsSexy.com: Read my article, JavaScript Objects in Detail
  3. Codecademy.com: Work through the last three sections of the Codecademy JavaScript track: “Data Structures,” “Objects 1,” and “Objects 2.”
  4. Beginning JavaScript: Read Chapter 6 (Programming the Browser).
  5. Beginning JavaScript: Read Chapter 15 (JavaScript Frameworks), and stop just after you complete this section: “Digging Deeper Into jQuery”.
  6. Codecademy.com: Work through the entire jQuery Track on Codecademy.

Weeks 3 and 4

Week 3: HTML Forms and Frames; JavaScript Strings; Build Your First Interactive Website

  1. Beginning JavaScript: Read Chapter 7 (HTML Forms: Interacting with the User).
  2. Beginning JavaScript: Read Chapter 8 (Windows and Frames).
  3. Beginning JavaScript: Read Chapter 9 (String Manipulation).
  4. Codecademy.com: Now, make your first cool website. Work through the entire Make an Interactive Website track on Codecademy.

Week 4: JavaScript Date, Timers, and Cookies

  1. Beginning JavaScript: Read Chapter 10 (Date, Time, and Timers).
  2. Beginning JavaScript: Read Chapter 11 (Storing Information: Cookies).

Weeks 5 and 6

Week 5: JavaScript “this,” Variable Scope, and Hoisting, the DOM, JavaScript XML, and AJAX

  1. JavaScriptIsSexy.com: Read my post JavaScript Variable Scope and Hoisting Explained
  2. JavaScriptIsSexy.com: Read my post Understand JavaScript’s “this” With Clarity, and Master It
  3. Beginning JavaScript: Read Chapter 12 (Dynamic HTML and the W3C Document Object Model).
  4. Beginning JavaScript: Read Chapter 14 (Ajax).

Week 6: Build a Real-World JavaScript Quiz Application

At this juncture, you have learned enough to build a solid JavaScript web application. Don’t proceed any further until you can successfully build this application I describe below. Don’t be afraid to ask questions on Stack Overflow, and do reread sections of the book to properly understand the concepts.

You are building a JavaScript quiz web application (you will use HTML and CSS as well) that will function as follows:

  • It is a simple quiz that has radio button choices, and it will show the quiz taker his or her score upon completion.
  • The quiz can show any number of questions and any number of choices.
  • Tally the user’s score and display the final score on the last page. The last page will only show the score, so remove the last question.
  • Use an array to store all the questions. Each question, along with its choices and correct answer, should be stored in an object. The array of questions should look similar to this (Notice that only one question is in this example array; you will add many questions):
    var allQuestions = [{question: “Who is Prime Minister of the United Kingdom?”, choices: [“David Cameron”, “Gordon Brown”, “Winston Churchill”, “Tony Blair”], correctAnswer:0}];
  • Dynamically (with document.getElementById or jQuery) remove the current question and add the next question, when the user clicks the “Next” button. The Next button will be the only button to navigate this version of the quiz.
  • You can ask for help in the comments below or preferably on Stack Overflow. You will likely to get a prompt and accurate answer on Stack Overflow.

Improve Your Quiz

You should be very comfortable with JavaScript, probably feeling like a Jedi. No, you are not. Not yet. You must keep using your newly acquired knowledge and skills as often as possible to keep learning and improving.

Improve Your Quiz Application From Earlier:

  • Add client-side data validation: make sure the user answers each question before proceeding to the next question.
  • Add a “Back” button to allow the user to go back and change her answer. The user can go back up to the first question. For the questions that the user has answered already, be sure to show the radio button selected, so that the user is not forced to answer the questions again, which she has completed.
  • Use jQuery to add animation (fade out the current question and fade in the next question).
  • Test the quiz on IE 9, and fix any bugs. This will give you a good workout 😉
  • Store the quiz questions in an external JSON file.
  • Add user authentication: allow users to log in, and save their login credentials to local storage (HTML5 browser storage).
  • Use cookies to remember the user, and show a “Welcome, ‘First Name’” message when the user returns to the quiz.

Week 7 (Extra Credit)

Getting Started with Git; Objective Oriented JavaScript; Improve Your Quiz Even More

  1. CodeSchool.com: Take the FREE Try Git course.
  2. JavaScriptIsSexy.com: Read my post, OOP In JavaScript: What You NEED to Know.
  3. Improve Your Quiz Application Even Further:
    — Use Twitter Bootstrap for the entire page layout, including the quiz elements to make it look more polished. As an added bonus, use the tabs user interface component from Twitter Bootstrap and show 4 different quizzes, one on each tab.
    Learn Handlebars.js and add Handlebars.js templating to the quiz. You should no longer have any HTML in your JavaScript code. Your quiz is getting more advanced, bit by bit.
    — Keep a record of all the users who take the quiz and show each user how his or her score ranks among the scores from other quiz takers.
  4. Later (after you have learned Backbone.js and Node.js or Meteor.js), you can use these technologies to refactor your quiz code and turn the same quiz into a sophisticated, single-page, modern web application built with the latest JavaScript frameworks. And you will store the users’ authentication credentials and scores in a MongoDB database.
  5. Next: Decide on a personal project to build, and start building your project promptly (while everything remains fresh in your memory). Use the book as a reference. And of course be an active member on Stack Overflow: ask questions and answer other programmers’ questions. I am confident you will be able to answer a number of questions.

Continue Improving

    1. Learn Backbone.js Completely, if you want to be a front-end developer or learn how to develop web applications with a JavaScript front-end framework.

Alternatively, if you want to develop complete applications, that is, the front-end and the backend, learn Meteor.js properly.

  1. At this point, you will definitely need my book, MongoDB for JavaScript Applications, to help you build your own jQuery, Backbone.js, Node.js, or Meteor.js applications, since none of the noted resources, or any other book for that matter, cover MongoDB in depth for JavaScript applications.
  2. Learn Intermediate and Advanced JavaScript
  3. Learn Node.js Completely and With Confidence

Words of Encouragement

I wish you success with your studies and in your JavaScript career. Never give up! When you are struggling and feeling incompetent (you may from time to time), always remember that most (probably all) programmers, new and experienced alike, feel this way sometimes, or have felt this way at some point during their programming career.

Remember to dig deep and don’t get frustrated; just carry on and stick with the task until you figure it out, for a worthwhile reward awaits you when you triumph in the end: programming is fun, liberating, and lucrative. The ecstasy one gets from building an application is a powerful feeling that you must experience to understand. Even more satisfying, however, is the empowerment you experience when you realize you have attained the skill and knowledge to build applications from scratch, to change the world with any idea you dream up.

The moment will come when you realize that all the difficulties you endured were worth while. Just as the millions before you have triumphed, so too, you will vanquish the toughest bugs, master the incomprehensible topics, and overcome the seemingly impossible tasks.

Feel free to share your links with us below when you build something, even if it is a tiny, itsy-bitsy project. :)

如何自学 Android 编程?

来源:伯乐在线专栏作者 – gityuan

链接:http://android.jobbole.com/82908/

引言:在知乎上回答了 自学编程一年,压力过大,该怎么办? – Gityuan 的回答,之后有不少知乎朋友私信或email给我,希望能讲讲学习Android的心得。

看到很多人提问非科班该如何学习编程,其实科班也基本靠自学。有句话叫“师傅领进门修行靠个人”,再厉害的老师能教你的东西都是很有限的,真正的修行还是要靠自己。我本科是学数学的,虽然研究生是计算机专业,但研究生往往是做研究工作,并不会接触编程这么基本的东西,关于编程相关我都是靠自学。对于Android这一块,是参加工作还开始接触,开始自己学习的。

学习级别,很多人都往往划分成入门、初级、中间..骨灰级等。这里就简单地划分为两级:基础篇和进阶篇。另外,本文涉及到的所有书籍都是 Gityuan 在学习过程中所读过的比较经典的一些书籍,才推荐给大家。

一、基础篇

看书的姿态:学习过程往往大家都需要看书,网上一搜,往往会有一大推的书推荐给大家去阅读,面对这么多书,该如何选择,如何阅读的呢,对于同一个层级的书籍选择一本精读,其余的粗读、略读即可,大同小异,对于精读的书籍需要反复的阅读。

1.1 Java篇

  • Java是Android的基础,建议初学者一定要先学习Java基本知识,进而再学习Android,循序渐进,切莫心急,只有扎实的基础才能建造牢固的上层建筑。
  • Thinking in Java: 中文版《Java编程思想 》,这是一本非常经典的Java书籍,很多人都说这个书不适合初学者,我记得自己当初看的第一本Java书便是这本书。看完第一遍对Java有了整体的理解,但很多细节没有完全理解,查了资源又看了第二遍,对Java有了更深地理解。再后来一段时间后,能力也有所提升,再拿起这本书又看了第三遍,发现对面向对象有了更深一步的理解,这本书就是适合反复的阅读。
  • Effective Java:Java进阶书,这本书采用“条目”的方式来展开的,总提出了78条Java具体的建议,对Java平台精妙之处的独到见解,还提供优秀的代码范例。作为Java进阶之书,对Java水平的提升大有裨益。
  • Java concurrency in Practice:中文版《Java并发编程实战》,本书采用循序渐进的讲解方式,从并发编程的基本理论讲起,再讲述了结构化并发应用,性能与测试,最后将显式锁、原子变量、非阻塞算法这些高级主题。对于Java并发这一块算得上是一本很棒的书。
  • Java Performance:中文版《Java性能优化权威指南》,Java之父James Gosling推荐的一本Java应用性能优化的经典之作,包含算法结构、内存、I/O、磁盘使用方式,内容通俗易懂,还介绍了大量的监控和测量工具。关于优化都是属于较深的领域,对Java有一定基础后,很有必要了解看看。

Java虚拟机,这是作为进阶Java高手必需有所了解:

本文的重点是讲如何学习Android,所以姑且把Java基础与进阶的书都放到Android学习的基础篇里。作为Android开发者来说,完全没有必要一开始都对Java理解得那么深,只有要看一两本Java基本书,掌握Java面向对象的思想的核心要义即万物皆为对象,掌握Java基本语法,基本就可以开启Android的学习之路。在后续对Android也有一定理解后,再慢慢不断提升Java和Android水平。

有朋友私信我觉着这个java书难度有点高,可能是本人在看Java书籍之前,还看过些许C和C++的入门书的缘故,所以看的第一本书《Java编程思想》。如果你真的是零基础,第一次接触编程,想以Java作为自己的入门语言,那么你可以先看看《Java语言程序设计》(基础篇) 或者《Java从入门到精通》,作为初学者险掌握Java基本语法,平时遇到不熟悉的方法,多查看API文档即可,慢慢地就熟悉了。

1.2 Android基础篇

有了一定的Java基础(不需要精通Java),就可以开始入门Android。建议初学Android者,一定要先搭建自己的开发环境,先准备jdk和Android Studio环境。再看书的过程,一边看知识点一边写示例程序,一来加深印象,二来提高动手能力。

  • 《疯狂Android讲义》:作者李刚,这是我看过的第一个Android书籍,目前有第三版了,我当时看的是第二版基于Android 4.2,书中有大量的实例,记得当时每看完一个实例就跟着敲了一遍,大概花了一周时间把这本书看完并把大部分的实例代码都亲手敲了一遍。
  • 《第一行代码》:作者郭霖,网上有不少人都推荐这本书作为Android入门书,但我当时没有看过。这是图灵系列图书,前段时间图灵的编辑看到我的博客gityuan.com,于是联系到我问是否有兴趣出书,便提到郭霖的《第一行代码》也是他们出版社推出的,然后就给我邮寄了一本。我大概扫了一扫这本书,内容的确比较基础,作者文笔不错,书中还穿插了不少打怪涨经验升级的片段,比较风趣,初学者可以看看。
  • Android的基本书籍,只需一两本即可,没有必要看太多基础书籍,不同能力就该有不同的追求,这里就不再介绍其他基础书籍。 另外,Android开发过程中总是需要各种开发环境、工具的下载,再这里推荐一个不错的网站 AndroidDevTools.cn,收集整理了 Android开发、设计等相关的各种工具大集合,非常全面,而且速度也不错哦,最重要的不用翻墙就可下载到最新的工具。

1.3 Android一手资料

何为Android一手资料?那就是Google官方给出的资料,这里往往是英文版的,营养价值极高。其实你只要英文还凑合+翻墙工具,强烈建议你直接看Android官网的资料,千万别被英语所吓倒,因为很多专业名称,大家一看就明白比如Activity/Service等这些代码名称本身就是英语,剩下地都就非常基础语法,不懂可以随时翻译,我一般都是用Chrome浏览器+Google翻译插件,哪里不会点哪里,妈妈再也不用担心我的英语了。

言归正传,如果你能看完并理解下列的内容,那么你完全可以没有必要再看前面介绍的书籍,并且对于Android已有相当熟悉了。

1.4 Android资源整理

到这里,那么你已经具备开发App的本领。平时需要自己动手多写写App,另外就是看看别人优秀的App是如何写的,下面列举一些开源库、工具以及App:

当然还有很多优秀的博客和网站值得推荐… //TODO

二、进阶篇

作为程序员,不去阅读源码,仅仅看API文档,只是浮于表象,这是远远不够的。.真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读Andoid系统源码,也包括阅读各种优秀的开源库。

2.1 阅读源码的重要性

借用Linux之父Linus Torvalds的一句名言:Read the fucking source code。不管是阅读Andoid系统源码还是优秀的开源框架,对能力那都会有一个巨大的提升;首先,能学习到优秀的代码风格和设计思想;能真正做到“知其然,还需知其所以然”;能指导自己更加灵活的使用API,能更加快速地找到系统bug的根源。
2.2 阅读源码的准备

  • Java基础:上层framework以及App层都是采用Java语法;
  • C/C++基础:Android的jni/native层代码采用C++,Linux 采用C;
  • Linux:Android内核基于Linux的,了解Linux相关知识对深入掌握Android还是很有必要。
  • Git:Android源码采用git和repo进行管理;
  • Make:Android源码采用Make系统编译,源码系统中会看到很多Android.mk之类的文件;
  • Source Insight:这绝对是看源码的神器;可以在Java、C++、C代码之间无缝衔接;
  • Eclipse:熟悉常用快捷键,工欲善其事必先利其器;虽然Source Insight很方便,但由于对Eclipse的熟悉感,对于framework Java层面的代码,我还是更习惯用Eclipse来看,对于Native代码以及linux代码则采用Source Insight来看;
  • Android Studio:这是Google官方支持的App开发环境,关于Android Studiod使用教程;
  • Google Drawings:这是画图工具,Gityuan博客中的文章都是采用Google Drawing完成,比如Binder开篇文中的图。
  • StarUML:这是类图,Gityuan博客文章的类图和流程图都是采用StarUML完成,比如理解Android进程创建流程文中时序图。

2.3 阅读源码的姿态

阅读源码绝不是从源码工程按顺序一个个的文件,从首行看到尾行。正确而高效地阅读源码的姿态应该是以某一个主线为起点,从上层往底层,不断地追溯,在各个模块、文件、方法之间来回跳转,反复地阅读,理清整个流程的逻辑。同时带着思考去看源码,尝试去揣测作者的用意,去理解代码的精妙之处,去思考代码可能存在的缺陷,去总结优秀的代码设计思想。下面说说我在阅读Android源码过程常涉及的库。

阅读Android源码:

面是我以Android开机过程为主线,展开一系列的文章 Android开篇中的一副流程图,在公司内部分享时我曾多次以下图为流程整个Android架构,如下图:

Android系统源码

android.googlesource.com:Google官方源码,国内无法直接访问,需要翻墙,对于一个程序员来说具备翻墙的能力是非常有必要的。Android源码中包含的库非常之多,下面列举我在看Android源码过程中涉及较多,也是比较常看的一些库:

2.4 优秀资源

牛顿曾说过:“如果我看得更远一点的话,是因为我站在巨人的肩膀上”,这句话很具有实用价值,看完前面的介绍,你千万不要一上来就一头扎进源码的世界,小心你会进入二次元世界,处于混沌状态,最后崩溃乃至放弃求知之路,一定要合理利用现有的优秀资源。

Android 系统源码分析

  • Innost的专栏
    • 邓凡平前辈所写博客,条例有序,覆盖了Android系统大部分内容;
    • 《深入理解Android》 (卷I,卷II,卷III)
  • 老罗的Android之旅
    • 罗升阳前辈所写博客,从各个层面介绍Android系统;
    • 《Android系统源代码情景分析 》
  • Gityuan源码分析
    • 对于邓凡平和罗升阳两位前辈的博客基于Android 2.x或4.x,目前Android已发展到Android 6.0。不管Android如何变化,其核心思维变化并没有很大,所以两位前辈的博客还是很有值得学习和参考的地方。话又说回来,Android经过了几个大版本的迭代,无论是从代码结构还是整体逻辑仍有不少变化。故博主计划写一关于Android 6.0源码系列的博文。
    • Gityuan作为Android界新秀,能力尚不及很多前辈,但有一颗乐于分享的心,有一份痴于Android的品质,有一种坚持的态度,已经并一直还在努力奋斗的道路上…

2.5 进阶书籍

  • 深入理解Linux内核
  • 深入Linux内核架构
  • Linux内核设计与实现
  • Linux设备驱动程序
  • 重构 改善既有代码的设计
  • 编程珠玑 (卷1, 卷2)
  • 设计模式
  • 设计模式之禅
  • 人月神话

前4本书都是关于Linux,如果你不是需要从事Linux相关开发,只想提升对Android整体的理解,那么只需看一到两本,对Linux的进程、内存、IO以及驱动有所了解,对CPU调度、进程间通信有所熟悉就基本可以。另外,优秀的书还有很多,这里只介绍/列举我看过的书,目前还在看一些优秀的书,后续再更新。

三、其他

最后,再说说关于学习编程的番外篇:

  • 好奇心比雄心走得更远:很多人对未来空有满腔的雄心壮志,往往不如对技术要有一份好奇心,一份探索欲,再加上一份执着的人。
  • 要有open的心态:曾经的我也只是把自己的所思所得都放入自己的云笔记,很少整理,这其实不利于技术发展,有空应该多整理自己零散的知识点,觉得不错的点可以拿出来写成博客,那是对能力的又一层提升。另外,在低头做技术的同时,还应该有空抬头看世界,不能闭门造车。
  • 天道酬勤:学历只能代表过去,能力代表现在,潜力代表未来! 你不把自己逼一把,你压根不知道自己有多优秀,只要努力去学习,去挖掘潜力,进而提升自我技术修为,未来不再是梦!共勉之!
  • 解决问题的方式:遇到问题,一定要先尝试自己解决,解决不了再请教他人。这是对自己的一个锻炼,也是对他人的一个尊重,可以有多种途径自行搜索:
    • 百度一下,很多时候还是能有所帮助的,不要过分强调google,完全抛弃百度,毕竟中文看起来比较快;
    • 先中文关键词google一下;再英文关键词google一下;
    • stackoverflow.com知乎等技术问答网站内直接搜索;
    • 查看官方文档;
    • 如果有源码,尝试直接看源码,看能否解决;
  • 有空可以多逛逛github,多看看Google官方文档,多关注社区,定会收获不少;
  • 当然,最最重要的是能静得下心,持之以恒地专研技术。

专栏作者简介( 点击 → 加入专栏作者 )


gityuan: Android全栈工程师:上至能写App,中间能改framework和Native代码,下至能调驱动,全栈能解决性能与稳定性。(新浪微博:@Gityuan)

 

 

Android 通用流行框架大全

来源:segmentfault

链接:https://segmentfault.com/a/1190000005073746

Android通用流行框架大全

 

1. 缓存


名称 描述
DiskLruCache Java实现基于LRU的磁盘缓存

 

2.图片加载


名称 描述
Android Universal Image Loader 一个强大的加载,缓存,展示图片的库
Picasso 一个强大的图片下载与缓存的库
Fresco 一个用于管理图像和他们使用的内存的库
Glide 一个图片加载和缓存的库

 

3. 图片处理


名称 描述
Picasso-transformations 一个为Picasso提供多种图片变换的库
Glide-transformations 一个为Glide提供多种图片变换的库
Android-gpuimage 基于OpenGL的Android过滤器

 

4. 网络请求


名称 描述
Android Async HTTP Android异步HTTP库
AndroidAsync 异步Socket,HTTP(客户端+服务器),WebSocket,和socket.io库。基于NIO而不是线程。
OkHttp 一个Http与Http/2的客户端
Retrofit 类型安全的Http客户端
Volley Google推出的Android异步网络请求框架和图片加载框架

 

5. 网络解析


名称 描述
Gson 一个Java序列化/反序列化库,可以将JSON和java对象互相转换
Jackson Jackson可以轻松地将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象
Fastjson Java上一个快速的JSON解析器/生成器
HtmlPaser 一种用来解析单个独立html或嵌套html的方式
Jsoup 一个以最好的DOM,CSS和jQuery解析html的库

 

6. 数据库


名称 描述
OrmLite JDBC和Android的轻量级ORM java包
Sugar 用超级简单的方法处理Android数据库
GreenDAO 一种轻快地将对象映射到SQLite数据库的ORM解决方案
ActiveAndroid 以活动记录方式为Android SQLite提供持久化
SQLBrite SQLiteOpenHelper 和ContentResolver的轻量级包装
Realm 移动数据库:一个SQLite和ORM的替换品

 

7. 依赖注入


名称 描述
ButterKnife 将Android视图和回调方法绑定到字段和方法上
Dagger2 一个Android和java快速依赖注射器。
AndroidAnotations 快速安卓开发。易于维护
RoboGuice Android平台的Google Guice

 

8. 图表


名称 描述
WilliamChart 创建图表的Android库
HelloCharts 兼容到API8的Android图表库
MPAndroidChart 一个强大的Android图表视图/图形库

 

9. 后台处理


名称 描述
Tape 一个轻快的,事务性的,基于文件的FIFO的库
Android Priority Job Queue 一个专门为Android轻松调度任务的工作队列

 

10. 事件总线


名称 描述
EventBus 安卓优化的事件总线,简化了活动、片段、线程、服务等的通信
Otto 一个基于Guava的增强的事件总线

 

11. 响应式编程


名称 描述
RxJava JVM上的响应式扩展
RxJavaJoins 为RxJava提供Joins操作
RxAndroid Android上的响应式扩展,在RxJava基础上添加了Android线程调度
RxBinding 提供用RxJava绑定Android UI的API
Agera Android上的响应式编程

 

12. Log框架


名称 描述
Logger 简单,漂亮,强大的Android日志工具
Hugo 在调试版本上注解的触发方法进行日志记录
Timber 一个小的,可扩展的日志工具

 

13. 测试框架


名称 描述
Mockito Java编写的Mocking单元测试框架
Robotium Android UI 测试
Robolectric Android单元测试框架

Android自带很多测试工具:JUnit,Monkeyrunner,UiAutomator,Espresso等

 

14. 调试框架


名称 描述
Stetho 调试Android应用的桥梁,使得可以利用Chrome开发者工具进行调试

 

15. 性能优化


名称 描述
LeakCanary 内存泄漏检测工具
ACRA Android应用程序崩溃报告

iOS开发经验总结(下)

来源:蝴蝶之梦天使

链接:http://www.jianshu.com/p/d333cf6ae4b0

四十、AFNetworking 传送 form-data

将JSON的数据,转化为NSData, 放入Request的body中。 发送到服务器就是form-data格式。

四十一、非空判断注意

BOOL hasBccCode = YES;

if ( nil == bccCodeStr

    || [bccCodeStr isKindOfClass:[NSNull class]]

    || [bccCodeStr isEqualToString:@“”])

{

    hasBccCode = NO;

}

如果进行非空判断和类型判断时,需要新进行类型判断,再进行非空判断,不然会crash。

四十二、iOS 8.4 UIAlertView 键盘显示问题

可以在调用UIAlertView 之前进行键盘是否已经隐藏的判断。

@property (nonatomic, assign) BOOL hasShowdKeyboard;

 

[[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(showKeyboard)

                                             name:UIKeyboardWillShowNotification

                                           object:nil];

 

[[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(dismissKeyboard)

                                             name:UIKeyboardDidHideNotification

                                           object:nil];

 

– (void)showKeyboard

{

    self.hasShowdKeyboard = YES;

}

 

– (void)dismissKeyboard

{

    self.hasShowdKeyboard = NO;

}

 

while ( self.hasShowdKeyboard )

{

    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

}

 

UIAlertView* alerview = [[UIAlertView alloc] initWithTitle:@“” message:@“取消修改?” delegate:self cancelButtonTitle:@“取消” otherButtonTitles@“确定”, nil];

[alerview show];

四十三、模拟器中文输入法设置

模拟器默认的配置种没有“小地球”,只能输入英文。加入中文方法如下:

选 择Settings—>General–>Keyboard–>International KeyBoards–>Add New Keyboard–>Chinese Simplified(PinYin) 即我们一般用的简体中文拼音输入法,配置好后,再输入文字时,点击弹出键盘上的“小地球”就可以输入中文了。

如果不行,可以长按“小地球”选择中文。

四十四、iPhone number pad

phone 的键盘类型:

  1. number pad 只能输入数字,不能切换到其他输入

  2. phone pad 类型: 拨打电话的时候使用,可以输入数字和 + * #

四十五、UIView 自带动画翻转界面

– (IBAction)changeImages:(id)sender

{

    CGContextRef context = UIGraphicsGetCurrentContext();

 

    [UIView beginAnimations:nil context:context];

    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

    [UIView setAnimationDuration:1.0];

 

    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:_parentView cache:YES];

    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:_parentView cache:YES];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:_parentView cache:YES];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:_parentView cache:YES];

 

    NSInteger purple = [[_parentView subviews] indexOfObject:self.image1];

    NSInteger maroon = [[_parentView subviews] indexOfObject:self.image2];

 

    [_parentView exchangeSubviewAtIndex:purple withSubviewAtIndex:maroon];

 

    [UIView setAnimationDelegate:self];

    [UIView commitAnimations];

}

四十六、KVO 监听其他类的变量

[[HXSLocationManager sharedManager] addObserver:self

                                         forKeyPath:@“currentBoxEntry.boxCodeStr”

                                            options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionOld context:nil];

在实现的类self中,进行[HXSLocationManager sharedManager]类中的变量@“currentBoxEntry.boxCodeStr” 监听。

四十七、ios9 crash animateWithDuration

在iOS9 中,如果进行animateWithDuration 时,view被release 那么会引起crash。

[UIView animateWithDuration:0.25f animations:^{

        self.frame = selfFrame;

    } completion:^(BOOL finished) {

        if (finished) {

            [super removeFromSuperview];

        }

    }];

会crash。

[UIView animateWithDuration:0.25f

                          delay:0

         usingSpringWithDamping:1.0

          initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveLinear

                     animations:^{

                         self.frame = selfFrame;

                     } completion:^(BOOL finished) {

                         [super removeFromSuperview];

                     }];

不会Crash。

四十八、对NSString进行URL编码转换

iPTV项目中在删除影片时,URL中需传送用户名与影片ID两个参数。当用户名中带中文字符时,删除失败。

之前测试时,手机号绑定的用户名是英文或数字。换了手机号测试时才发现这个问题。

对于URL中有中文字符的情况,需对URL进行编码转换。

urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

四十九、Xcode iOS加载图片只能用PNG

虽然在Xcode可以看到jpg的图片,但是在加载的时候会失败。

错误为 Could not load the “ReversalImage1” image referenced from a nib in the bun

必须使用PNG的图片。


如果需要使用JPG 需要添加后缀

[UIImage imageNamed:@“myImage.jpg”];

五十、保存全屏为image

CGSize imageSize = [[UIScreen mainScreen] bounds].size;

UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);

CGContextRef context = UIGraphicsGetCurrentContext();

 

for (UIWindow * window in [[UIApplication sharedApplication] windows]) {

    if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) {

        CGContextSaveGState(context);

        CGContextTranslateCTM(context, [window center].x, [window center].y);

        CGContextConcatCTM(context, [window transform]);

        CGContextTranslateCTM(context, –[window bounds].size.width*[[window layer] anchorPoint].x, –[window bounds].size.height*[[window layer] anchorPoint].y);

        [[window layer] renderInContext:context];

 

        CGContextRestoreGState(context);

    }

}

 

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

五十一、判断定位状态 locationServicesEnabled

这个[CLLocationManager locationServicesEnabled]检测的是整个iOS系统的位置服务开关,无法检测当前应用是否被关闭。通过

CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    if (kCLAuthorizationStatusDenied == status || kCLAuthorizationStatusRestricted == status) {

        [self locationManager:self.locationManager didUpdateLocations:nil];

    } else { // the user has closed this function

        [self.locationManager startUpdatingLocation];

    }

CLAuthorizationStatus来判断是否可以访问GPS

五十二、微信分享的时候注意大小

text 的大小必须 大于0 小于 10k

image 必须 小于 64k

url 必须 大于 0k

五十三、图片缓存的清空

一般使用SDWebImage 进行图片的显示和缓存,一般缓存的内容比较多了就需要进行清空缓存

清除SDWebImage的内存和硬盘时,可以同时清除session 和 cookie的缓存。

// 清理内存

[[SDImageCache sharedImageCache] clearMemory];

 

// 清理webview 缓存

NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (NSHTTPCookie *cookie in [storage cookies]) {

    [storage deleteCookie:cookie];

}

 

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

[config.URLCache removeAllCachedResponses];

[[NSURLCache sharedURLCache] removeAllCachedResponses];

 

// 清理硬盘

[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{

    [MBProgressHUD hideAllHUDsForView:self.view animated:YES];

 

    [self.tableView reloadData];

}];

五十四、TableView Header View 跟随Tableview 滚动

当tableview的类型为 plain的时候,header View 就会停留在最上面。

当类型为 group的时候,header view 就会跟随tableview 一起滚动了。

五十五、TabBar的title 设置

在xib 或 storyboard 中可以进行tabBar的设置

其中badge 是自带的在图标上添加一个角标。

1. self.navigationItem.title 设置navigation的title 需要用这个进行设置。

2. self.title 在tab bar的主VC 中,进行设置self.title 会导致navigation 的title 和 tab bar的title一起被修改。

五十六、UITabBar,移除顶部的阴影

添加这两行代码:

[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];

[[UITabBar appearance] setBackgroundImage:[[UIImage alloc] init]];

顶部的阴影是在UIWindow上的,所以不能简单的设置就去除。

五十七、当一行中,多个UIKit 都是动态的宽度设置

设置horizontal的值,表示出现内容很长的时候,优先压缩这个UIKit。

五十八、JSON的“” 转换为nil

使用AFNetworking 时, 使用

AFJSONResponseSerializer *response = [[AFJSONResponseSerializer alloc] init];

response.removesKeysWithNullValues = YES;

 

_sharedClient.responseSerializer = response;

这个参数 removesKeysWithNullValues 可以将null的值删除,那么就Value为nil了

END

写吐了,那么长应该是没人会看完的,看完了算你狠。

iOS开发经验总结(上)

来源:蝴蝶之梦天使

链接:http://www.jianshu.com/p/d333cf6ae4b0

在iOS开发中经常需要使用的或不常用的知识点的总结,几年的收藏和积累(踩过的坑)。

一、 iPhone Size

手机型号 屏幕尺寸
iPhone 4 4s 320 * 480
iPhone 5 5s 320 * 568
iPhone 6 6s 375 * 667
iphone 6 plus 6s plus 414 * 736

二、 给navigation Bar 设置 title 颜色

UIColor *whiteColor = [UIColor whiteColor];

NSDictionary *dic = [NSDictionary dictionaryWithObject:whiteColor forKey:NSForegroundColorAttributeName];

[self.navigationController.navigationBar setTitleTextAttributes:dic];

三、 如何把一个CGPoint存入数组里

CGPoint  itemSprite1position = CGPointMake(100, 200);

NSMutableArray * array  = [[NSMutableArray alloc] initWithObjects:NSStringFromCGPoint(itemSprite1position),nil];

    //    从数组中取值的过程是这样的:  

CGPoint point = CGPointFromString([array objectAtIndex:0]);

 

NSLog(@“point is %@.”, NSStringFromCGPoint(point));

谢谢@bigParis的建议,可以用NSValue进行基础数据的保存,用这个方法更加清晰明确。

CGPoint  itemSprite1position = CGPointMake(100, 200);

NSValue *originValue = [NSValue valueWithCGPoint:itemSprite1position];

NSMutableArray * array  = [[NSMutableArray alloc] initWithObjects:originValue, nil];

//    从数组中取值的过程是这样的:

NSValue *currentValue = [array objectAtIndex:0];

CGPoint point = [currentValue CGPointValue];

 

NSLog(@“point is %@.”, NSStringFromCGPoint(point));

现在Xcode7后OC支持泛型了,可以用NSMutableArray *array来保存。

四、 UIColor 获取 RGB 值

UIColor *color = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];

const CGFloat *components = CGColorGetComponents(color.CGColor);

NSLog(@“Red: %f”, components[0]);

NSLog(@“Green: %f”, components[1]);

NSLog(@“Blue: %f”, components[2]);

NSLog(@“Alpha: %f”, components[3]);

五、 修改textField的placeholder的字体颜色、大小

self.textField.placeholder = @“username is in here!”;

[self.textField setValue:[UIColor redColor] forKeyPath:@“_placeholderLabel.textColor”];

[self.textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@“_placeholderLabel.font”];

六、两点之间的距离

static __inline__ CGFloat CGPointDistanceBetweenTwoPoints(CGPoint point1, CGPoint point2) { CGFloat dx = point2.xpoint1.x; CGFloat dy = point2.ypoint1.y; return sqrt(dx*dx + dy*dy);}

七、IOS开发-关闭/收起键盘方法总结

1、点击Return按扭时收起键盘

(BOOL)textFieldShouldReturn:(UITextField *)textField

{

    return [textField resignFirstResponder];

}

2、点击背景View收起键盘(你的View必须是继承于UIControl)

[self.view endEditing:YES];

3、你可以在任何地方加上这句话,可以用来统一收起键盘

[[[UIApplication sharedApplication] keyWindow] endEditing:YES];

八、在使用 ImagesQA.xcassets 时需要注意

将图片直接拖入image到ImagesQA.xcassets中时,图片的名字会保留。

这个时候如果图片的名字过长,那么这个名字会存入到ImagesQA.xcassets中,名字过长会引起SourceTree判断异常。

九、UIPickerView 判断开始选择到选择结束

开始选择的,需要在继承UiPickerView,创建一个子类,在子类中重载

(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event

当[super hitTest:point withEvent:event]返回不是nil的时候,说明是点击中UIPickerView中了。

结束选择的, 实现UIPickerView的delegate方法

(void)pickerView:(UIPickerView*)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

当调用这个方法的时候,说明选择已经结束了。

十、iOS模拟器 键盘事件

当iOS模拟器 选择了Keybaord->Connect Hardware keyboard 后,不弹出键盘。


当代码中添加了

[[NSNotificationCenter defaultCenter] addObserver:self

                                             selector:@selector(keyboardWillHide)

                                                 name:UIKeyboardWillHideNotification

                                               object:nil];

进行键盘事件的获取。那么在此情景下将不会调用- (void)keyboardWillHide.

因为没有键盘的隐藏和显示。

十一、在ios7上使用size classes后上面下面黑色

使用了size classes后,在ios7的模拟器上出现了上面和下面部分的黑色

可以在General->App Icons and Launch Images->Launch Images Source中设置Images.xcassets来解决。

十二、设置不同size在size classes

Font中设置不同的size classes。

十三、线程中更新 UILabel的text

[self.label1 performSelectorOnMainThread:@selector(setText:)                                      withObject:textDisplay

                                   waitUntilDone:YES];

abel1 为UILabel,当在子线程中,需要进行text的更新的时候,可以使用这个方法来更新。

其他的UIView 也都是一样的。

十四、使用UIScrollViewKeyboardDismissMode实现了Message app的行为

像Messages app一样在滚动的时候可以让键盘消失是一种非常好的体验。然而,将这种行为整合到你的app很难。幸运的是,苹果给UIScrollView添加了一个很好用的属性keyboardDismissMode,这样可以方便很多。

现在仅仅只需要在Storyboard中改变一个简单的属性,或者增加一行代码,你的app可以和办到和Messages app一样的事情了。

这个属性使用了新的UIScrollViewKeyboardDismissMode enum枚举类型。这个enum枚举类型可能的值如下:

typedef NS_ENUM(NSInteger, UIScrollViewKeyboardDismissMode) {

    UIScrollViewKeyboardDismissModeNone,

    UIScrollViewKeyboardDismissModeOnDrag,      // dismisses the keyboard when a drag begins

    UIScrollViewKeyboardDismissModeInteractive, // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss

} NS_ENUM_AVAILABLE_IOS(7_0);

以下是让键盘可以在滚动的时候消失需要设置的属性:

十五、报错 “_sqlite3_bind_blob”, referenced from:

将 sqlite3.dylib加载到framework

十六、ios7 statusbar 文字颜色

iOS7上,默认status bar字体颜色是黑色的,要修改为白色的需要在infoPlist里设置UIViewControllerBasedStatusBarAppearance为NO,然后在代码里添加:

[application setStatusBarStyle:UIStatusBarStyleLightContent];

十七、获得当前硬盘空间

NSFileManager *fm = [NSFileManager defaultManager];

    NSDictionary *fattributes = [fm attributesOfFileSystemForPath:NSHomeDirectory() error:nil];

 

    NSLog(@“容量%lldG”,[[fattributes objectForKey:NSFileSystemSize] longLongValue]/1000000000);

    NSLog(@“可用%lldG”,[[fattributes objectForKey:NSFileSystemFreeSize] longLongValue]/1000000000);

十八、给UIView 设置透明度,不影响其他sub views

UIView设置了alpha值,但其中的内容也跟着变透明。有没有解决办法?

设置background color的颜色中的透明度

比如:

[self.testView setBackgroundColor:[UIColor colorWithRed:0.0 green:1.0 blue:1.0 alpha:0.5]];

设置了color的alpha, 就可以实现背景色有透明度,当其他sub views不受影响给color 添加 alpha,或修改alpha的值。

// Returns a color in the same color space as the receiver with the specified alpha component.

(UIColor *)colorWithAlphaComponent:(CGFloat)alpha;

// eg.

[view.backgroundColor colorWithAlphaComponent:0.5];

十九、将color转为UIImage

//将color转为UIImage

(UIImage *)createImageWithColor:(UIColor *)color

{

    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);

    UIGraphicsBeginImageContext(rect.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);

    CGContextFillRect(context, rect);

    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

 

    return theImage;

}

二十、NSTimer 用法

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

 

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

在NSRunLoop 中添加定时器.

二十一、Bundle identifier 应用标示符

Bundle identifier 是应用的标示符,表明应用和其他APP的区别。

二十二、NSDate 获取几年前的时间

eg. 获取到40年前的日期

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *dateComponents = [[NSDateComponents alloc] init];

[dateComponents setYear:-40];

self.birthDate = [gregorian dateByAddingComponents:dateComponents toDate:[NSDate date] options:0];

二十三、iOS加载启动图的时候隐藏statusbar

只需需要在info.plist中加入Status bar is initially hidden 设置为YES就好

二十四、iOS 开发,工程中混合使用 ARC 和非ARC

Xcode 项目中我们可以使用 ARC 和非 ARC 的混合模式。

如果你的项目使用的非 ARC 模式,则为 ARC 模式的代码文件加入 -fobjc-arc 标签。

如果你的项目使用的是 ARC 模式,则为非 ARC 模式的代码文件加入 -fno-objc-arc 标签。

添加标签的方法:

  • 打开:你的target -> Build Phases -> Compile Sources.
  • 双击对应的 *.m 文件
  • 在弹出窗口中输入上面提到的标签 -fobjc-arc / -fno-objc-arc
  • 点击 done 保存

二十五、iOS7 中 boundingRectWithSize:options:attributes:context:计算文本尺寸的使用

之前使用了NSString类的sizeWithFont:constrainedToSize:lineBreakMode:方法,但是该方法已经被iOS7 Deprecated了,而iOS7新出了一个boudingRectWithSize:options:attributes:context方法来代替。

而具体怎么使用呢,尤其那个attribute

NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:13]};

CGSize size = [@“相关NSString” boundingRectWithSize:CGSizeMake(100, 0) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attribute context:nil].size;

二十六、NSDate使用 注意

NSDate 在保存数据,传输数据中,一般最好使用UTC时间。

在显示到界面给用户看的时候,需要转换为本地时间。

二十七、在UIViewController中property的一个UIViewController的Present问题

如果在一个UIViewController A中有一个property属性为UIViewController B,实例化后,将BVC.view 添加到主UIViewController A.view上,如果在viewB上进行 – (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion NS_AVAILABLE_IOS(5_0);的操作将会出现,“ Presenting view controllers on detached view controllers is discouraged ” 的问题。

以为BVC已经present到AVC中了,所以再一次进行会出现错误。

可以使用

[self.view.window.rootViewController presentViewController:imagePicker

                                                      animated:YES

                                                    completion:^{

                                                        NSLog(@“Finished”);

                                                    }];

来解决。

二十八、UITableViewCell indentationLevel 使用

UITableViewCell 属性 NSInteger indentationLevel 的使用, 对cell设置 indentationLevel的值,可以将cell 分级别。

还有 CGFloat indentationWidth; 属性,设置缩进的宽度。

总缩进的宽度: indentationLevel * indentationWidth

二十九、ActivityViewController 使用AirDrop分享

使用AirDrop 进行分享:

NSArray *array = @[@“test1”, @“test2”];

 

UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:array applicationActivities:nil];

 

[self presentViewController:activityVC animated:YES

                 completion:^{

                     NSLog(@“Air”);

                 }];

就可以弹出界面:

三十、获取CGRect的height

获取CGRect的height, 除了 self.createNewMessageTableView.frame.size.height 这样进行点语法获取。

还可以使用CGRectGetHeight(self.createNewMessageTableView.frame) 进行直接获取。

除了这个方法还有 func CGRectGetWidth(rect: CGRect) -> CGFloat

等等简单地方法

func CGRectGetMinX(rect: CGRect) -> CGFloat

func CGRectGetMidX(rect: CGRect) -> CGFloat

func CGRectGetMaxX(rect: CGRect) -> CGFloat

func CGRectGetMinY(rect: CGRect) -> CGFloat

三十一、打印 %

NSString *printPercentStr = [NSString stringWithFormat:@“%%”];

三十二、在工程中查看是否使用 IDFA

allentekiMac-mini:JiKaTongGit lihuaxie$ grep -r advertisingIdentifier .

grep: ./ios/Framework/AMapSearchKit.framework/Resources: No such file or directory

Binary file ./ios/Framework/MAMapKit.framework/MAMapKit matches

Binary file ./ios/Framework/MAMapKit.framework/Versions/2.4.1.e00ba6a/MAMapKit matches

Binary file ./ios/Framework/MAMapKit.framework/Versions/Current/MAMapKit matches

Binary file ./ios/JiKaTong.xcodeproj/project.xcworkspace/xcuserdata/lihuaxie.xcuserdatad/UserInterfaceState.xcuserstate matches

allentekiMac-mini:JiKaTongGit lihuaxie$

打开终端,到工程目录中, 输入:

grep -r advertisingIdentifier .

可以看到那些文件中用到了IDFA,如果用到了就会被显示出来。

三十三、APP 屏蔽 触发事件

// Disable user interaction when download finishes

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

三十四、设置Status bar颜色

status bar的颜色设置:

如果没有navigation bar, 直接设置 // make status bar background color

self.view.backgroundColor = COLOR_APP_MAIN;

如果有navigation bar, 在navigation bar 添加一个view来设置颜色。// status bar color

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, -20, ScreenWidth, 20)];
[view setBackgroundColor:COLOR_APP_MAIN];

[viewController.navigationController.navigationBar addSubview:view];

三十五、NSDictionary 转 NSString

// Start
NSDictionary *parametersDic = [NSDictionary dictionaryWithObjectsAndKeys:
self.providerStr, KEY_LOGIN_PROVIDER,
token, KEY_TOKEN,
response, KEY_RESPONSE,
nil];

NSData jsonData = parametersDic == nil ? nil : [NSJSONSerialization dataWithJSONObject:parametersDic options:0 error:nil];
NSString 
requestBody = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

将dictionary 转化为 NSData, data 转化为 string .

 

三十六、iOS7 中UIButton setImage 没有起作用

如果在iOS7 中进行设置image 没有生效。

 

那么说明UIButton的 enable 属性没有生效是NO的。 **需要设置enable 为YES。**

 

三十七、User-Agent 判断设备

UIWebView 会根据User-Agent 的值来判断需要显示哪个界面。

如果需要设置为全局,那么直接在应用启动的时候加载。

(void)appendUserAgent

{

NSString oldAgent = [self.WebView stringByEvaluatingJavaScriptFromString:@”navigator.userAgent”];

NSString newAgent = [oldAgent stringByAppendingString:@”iOS”];

NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:

newAgent, @”UserAgent”, nil];

1

newAgent, @”UserAgent”, nil];

[[NSUserDefaults standardUserDefaults] registerDefaults:dic];

}

@“iOS” 为添加的自定义。

三十八、UIPasteboard 屏蔽paste 选项

当UIpasteboard的string 设置为@“” 时,那么string会成为nil。 就不会出现paste的选项。

三十九、class_addMethod 使用

当 ARC 环境下

class_addMethod([self class], @selector(resolveThisMethodDynamically), (IMP) myMethodIMP, “v@:”);

使用的时候@selector 需要使用super的class,不然会报错。

当MRC环境下

class_addMethod([EmptyClass class], @selector(sayHello2), (IMP)sayHello, “v@:”);

可以任意定义。但是系统会出现警告,忽略警告就可以。

这可能是史上最全的CSS自适应布局总结

作者:茄果

链接:http://www.cnblogs.com/qieguo/p/5421252.html

标题严格遵守了新广告法,你再不爽,我也没犯法呀!屁话不多说,直入!

所谓布局,其实包含两个含义:尺寸与定位。也就是说,所有与尺寸和定位相关的属性,都可以用来布局。

大体上,布局中会用到的有:尺寸相关的盒子模型,普通流、浮动、绝对定位三种定位机制,CSS3中的transform、弹性盒子模块、试验中的grid模块。逛园子的时候经常可以看到浮动布局,inline-block布局,弹性盒布局这几个名词。现在对布局也算有一点了解,做个总结巩固一下。如果你也看了很多资料,但是实际动手时对布局还是无从下手的话,希望本文可以帮你理清思路。

唠叨一句:看到一个效果图的时候,千万不要急着手贱去敲代码!先思考清楚页面的构造,理清各元素之间的关系,特别需要注意的是在不同的设备下需要有怎样的展现,当你思路清晰找到最好的布局方案时,coding其实真的不需要多少时间。

尺寸相关

为什么要先说尺寸呢?因为尺寸在布局中的作用非常核心,布局方式定位这些只是改变了元素之间的关系,没有尺寸就什么也不是。比如我们通常会用margin来控制跟其他元素的距离,这就是布局。

很多人都会觉得,什么width、margin太简单了,早就掌握了。这种心态我一开始学习CSS的时候也有,觉得很好理解很简单,但是后面才发现自己原来很多东西都没真正掌握。看看张鑫旭大神给我们上的政治课:http://www.zhangxinxu.com/wordpress/2012/07/bottleneck-css-study/

先说说百分比,百分比是相对父对象的,这里特性非常好用,很多时候会用在自适应布局上面。浏览器尺寸的改变,就是根节点html的长宽改变,我们可以用%来将浏览器尺寸和元素尺寸联系起来,做到自适应。

另外一个比较有意思的是auto,auto是很多尺寸值的默认值,也就是由浏览器自动计算。首先是块级元素水平方向的auto,块级元素的margin、border、padding以及content宽度之和等于父元素width。使用auto属性在父元素宽度变化的时候,该元素的宽度也会随之变化。

但是当该元素被设为浮动时,该元素的width就变成了内容的宽度了,由内容撑开,也就是所谓的有了包裹性。overflow | position:absolute | float:left/right都可以产生包裹性,替换元素也同样具有包裹性。在具有包裹性的元素上想利用width : auto;来让元素宽度自适应浏览器宽是不行的。

高度方向:外边距重叠,外边距auto为0,这两点需要注意。书写方向什么的,接触比较少就不扯了。

那为什么margin:auto对不能计算垂直方向的值呢?很简单,垂直方向是被设计成可以无限扩展的,内容越多浏览器便产生滚动条来扩展,所以垂直方向都找不到一个计算基准,以此返回一个false,便成了0。

用处:通过width、height控制大小,各个方向的margin值控制与边界或者其他元素的距离来定位。

浮动

目前PC网站大多使用float布局,从成本上考虑大改的概率很小,所以不要说浮动无用,总是会有机会让你维护的!代表网站:淘宝、腾讯、百度,好吧BAT都到齐了。

浮动听得多了,博客园上关于用浮动布局的介绍也非常的多。浮动原本用于文本环绕,但却在布局被发扬光大,这就是命!我的理解:浮动布局的核心就是让元素脱离普通流,然后使用width/height,margin/padding将元素定位。脱离普通流的元素,就像脱离地心引力一样,与普通流不在一个高度上。这个跟图层的概念类似。高度不同所以可以叠在其他元素上面产生重叠或者使用负边距跑到父元素外,理解了这一点浮动布局就很好理解了。

下面用个圣杯布局的例子说明一下,理解了这个之后其他布局更加简单:

left,宽度固定,高度可固定也可由内容撑开

right,宽度固定,高度可固定也可由内容撑开

center,可以自适应浏览器宽度,高度可固定也可由内容撑开。

HTML & CSS:

原理非常简单,左右侧边栏定宽并浮动,中部内容区放最后不浮动、默认width:auto并设置相应外边距,让左右侧边栏浮动到上面。注意:子元素设置为浮动之后,父对象的高度就坍塌了,需要设置父对象后的元素清除浮动,这样父对象的高度才能被浮动子元素撑起来了。

当然,我们也要问一下,为啥父对象高度会坍塌呢?上面也说过了,浮动元素已经脱离了普通流,父对象所在的普通流比喻成地表,那浮动元素就已经上天了。但是父对象还在地表啊,从外太空看浮动元素在父对象里面,但是其实并不在,又怎么能撑开父对象呢?宽度如果我们不设置的话,其实也是为0的,因为父对象里面空空如也,所以宽高为0。

要撑开的办法就两个,1是让父对象也上天(。。。你咋不上天呢),2是把浮动元素的边框边界拉下来。

父对象也上天(即浮动)的话,那就不能实现宽度自适应了。因为float元素的width:auto是包裹内容的,参考前面说的!

办法2就是在后面的元素里加一个clear语句。说到这个问题就要扯到clear与BFC了,我就不献丑了。传送门:https://developer.mozilla.org/zh-CN/docs/Web/CSS/clear

这个三列布局还有个双飞(是双飞翼!想啥呢)的变种,就是在HTML中center部分也就是内容区提到最前面,也就是内容先行渲染。在网络不好的时候,左右双翼能不能出来不要紧,先让主体内容出来!这种想法,明显的优秀工程师思维,但,尼玛的双翼都是广告啊。广告不出来,哪能赚钱养你们这群工程师?所以提出双飞的玉伯才离开了淘宝???(纯属意淫,如真属实,当我扯淡,哈哈哈!)

先上码:

思路:

1)既然HTML里面要让center放前面,为了让left跑到center前面,那center也必须浮动了,否则因为都是块元素他们会分两行。

2)浮动之后还要让center宽度自适应,那明显width只能100%,然后在父元素中设width:auto,还有两侧margin,其实也就是父对象宽度自适应,center只是继承content的宽度。

3)对left使用负的margin让他们浮动到上方去。

代码里面我用到了一个calc(),这个CSS3带来的计算函数简直酷毙了!本例里如果不使用calc函数,那么就需要wrap左边距为0,left左边距-100%,然后center多加一层子块DIV设置margin-left:100px,可以达到同样的效果!calc函数与百分比配合就足以实现自适应的要求!目前所有的自适应布局都在利用浏览器来为我们计算尺寸,但是有了calc之后我们就可以自己制定规则!单是想想都高潮了吧?

总结:使用浮动来进行布局,一个比较大的问题是清除浮动。这个可以使用一个after伪类来清除。更大的问题是浮动性像水一样向上流动,难以把握。在元素较多而且元素高度尺寸不一的情况下,单纯使用浮动只能实现上端对齐,这对于适应多种设备的布局就显得力不从心了。目前的做法是牺牲一部分内容,将元素做成等高排列,从美观上看也当然也是极好的,比参差不齐的排列要美观。

普通流布局

普通流布局:display : inline-block!这是一个传说中取代float布局的存在。看了一些网站,PC端浮动为主,移动端的也用的不多啊,已经有些使用flex的了,说好的inline-block一统江湖呢?

使用inline-block之前先处理点小障碍:inline-block元素会有4px左右的空隙,这个是因为我们写代码时候的换行符所致。

解决办法很简单:在inline-block的父元素中设置样式font-size:0;letter-spacing: -4px; 然后设置inline-block的所有兄弟元素 font-size:值;letter-spacing: 值px;  恢复正常的显示。

另外还有一点需要注意的是inline-block默认是基线对齐的,而inline-block的基线又跟文本基线一致,所以在内容不同的时候并不能水平对齐。只需要用vertical-align显式声明一下top/bottom/middle对齐即可。这里补充一下基线的内容,没你想的那么简单哦。分有文字和无文字两种情况:

1)无文字:容器的margin-bottom下边缘。与容器内部的元素没一毛钱关系。

2)有文字:最后一行文字的下边缘,跟文字块(p,h等)的margin、padding没关系!注意是最后一行,无论文字在什么子对象容器内在什么位置都没关系,浏览器会找到最后一行文字对齐底部。

你们感受一下:

警示:inline-block的基线是最后一行文字的底部,flex里面的基线是第一行文字的底部(请看下文阮老师的文章)

满满的都是泪啊。。。既然都叫baseline,何必呢?

使用inline-block进行圣杯布局:

这里也没什么好说的,用到的也是width:auto和width:100%这两点,简单知识点的简单用法。

双飞的话,代码跟圣杯的基本相同,注意在html的顺序变为center>right>left,只改左栏移动的margin-left: calc(-100% – 100px)到预定位置即可。不能用calc的话可以在center里面再加一层,跟浮动一样的处理方式。更简单的方法是使用CSS3带给我们的box-sizing属性。请看代码:

总结:相比浮动inline-block更加容易理解,也更符合我们的认知,结合盒子模型的几个控制属性就可以进行布局了。对于元素高度不同的情况,目前浮动布局的做法都是将元素做成等高元素进行展现,这从美学上看也符合整齐的要求,不过牺牲了一部分内容。但inline-block有vertical-align属性,可以很好地解决元素高度不同而带来的布局问题。用过之后,你也会喜欢上inline-block的。。。至少我会!

绝对定位

前面的浮动和普通流中其实定位都是靠盒子模型控制的,与我们常说的定位还是有差别的。而绝对定位就是我们平常所说的定位,给定参考坐标系+坐标确定位置。关于绝对定位的资料太多,我就不说了。提一点就是absolute定位的基准是最近的非static定位父对象,而fixed是相对html根节点的定位。两种定位都会脱离普通流,跟之前说的浮动一样,上天了。

当然,他们跟浮动在空间中的位置还是有差别的,项目中有遇到这个问题的请参考张大婶的文章: http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/  还是要结合项目来看,否则看过也只是看过而已,并不会存到你的脑子里,毕竟还是相当抽象相当理论性的东西。借用张大神的一个总结图:

使用绝对定位(特指absolute)做自适应布局跟前面两种方式没太大差别,宽度自适应还是在auto和100%上做文章,而位置则由top/bottom/left/right等控制。还是以圣杯布局来举例:

<!DOCTYPE html>

<html>

    <head>

        <meta charset=“utf-8” />

        <title>宽度自适应布局</title>

        <style>

            .wrap {

                position: relative;

                background-color: #FBD570;

                margin-left: 100px;

                margin-right: 150px;

                height: 250px;

            }

            .left {

                position: absolute;

                top: 0;

                left: -100px;

                width: 100px;

                background: #00f;

                height: 180px;

            }

            .right {

                position: absolute;

                top: 0;

                right: 0;

                   width: 150px;

                background: #0f0;

                height: 200px;

                margin-right: -150px;

            }

            .center {

                position: absolute;

                top: 0;

                left: 0;

                background: #B373DA;

                height: 150px;

                min-width: 150px;

                width: 100%;

            }

        </style>

    </head>

    <body>

        <div class=“wrap”>

            <div class=“center”>

                center,可以自适应浏览器宽度,高度固定。

            </div>

            <div class=“left”>left,宽度高度固定</div>

            <div class=“right”>right,宽度高度固定</div>

        </div>

    </body>

</html>

父元素为relative,子元素为absolute,这样的话,又会出现跟浮动一样的问题:父对象高度坍塌,子元素不能撑起父对象。原因也跟浮动一样,解决办法的话目前我知道的只有给父对象指定一个确定height值,大家如果有更好的办法,请联系我!

总结:单纯使用绝对定位进行自适应布局的情况很少,一般绝对定位都用在尺寸固定的元素定位上。而且fixed定位的渲染效率很低,因为它会频繁触发浏览器的重排。另外提一点:CSS3的transform会对绝对定位产生影响哦~比如说让fixed定位不再固定在浏览器视窗的黑魔法:http://www.zhangxinxu.com/wordpress/2015/05/css3-transform-affect/

弹性盒子

CSS3中对布局影响最大的莫过于弹性盒子模块了,这是一套区别于以往盒子模型布局的全新方案。上面几种方法你可以看到,为了实现自适应我们用的都是width:auto和100%的嵌套以及各种边距的移动定位,这套规则并不符合我们的认知。为什么不能开拓出一块区域,横竖排列都可以,内部所有元素的尺寸可以按照一个规则和这个区域的大小联系起来?终于CSS3做出了改变,引入了flex弹性布局方案,弹性盒布局有如下优势:

1.独立的高度控制与对齐。

2.独立的元素顺序。

3.指定元素之间的关系。

4.灵活的尺寸与对齐方式。

在MDN上有非常简单易懂的基础教程:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes

上面也已经给出了圣杯布局的自适应布局方案,所以代码就不贴了不过这个例子实现的是3栏成比例缩放,左右栏如果需要固定值的话可以写成  flex: 0 0 150px; 的样式。

但是上面的教程没有给出各个属性的详细解释,建议看看阮一峰的博文,详细易懂而且配图超漂亮的有木有:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

总结:弹性盒子在移动端的应用会越来越普遍,这套模型值得去好好研究。语法规则都是非常贴近人性,非常灵活,浏览器兼容性也非常好,当然国内百花齐放的移动浏览器会有哪些大坑呢?我们拭目以待~

其他

其他包括position:relative和CSS3中的transform都可以实现定位,但是由于他们在原来的普通流中还占着一个坑,所以很少用来布局啥的。transform是个很酷炫的东西,可以用平面的素材做出很多3D的效果,而且不需要js就可以做,非常好玩。此文已经很长,就不多说了,以后会写一篇文章来专门说说她的故事。

Java中文乱码解决之道(2): 字符编码详解

来源: chenssy

链接:http://www.cnblogs.com/chenssy/p/4202688.html

在上篇博文(java中文乱码解决之道(一)—–认识字符集)中,LZ简单介绍了主流的字符编码,对各种编码都是点到为止,以下LZ将详细阐述字符集、字符编码等基础知识和ASCII、GB的详情。

一、基础知识

在了解各种字符集之前我们需要了解一些最基础的知识,如:编码、字符、字符集、字符编码基础知识。

编码

计算机中存储的信息都是用二进制表示的,我们在屏幕上所看到文字、图片等都是通过二进制转换的结果。编码是信息从一种形式或格式转换为另一种形式的过程,通俗点讲就是就是将我们看到的文字、图片等信息按照某种规则存储在计算机中,例如‘c’在计算机中怎么表达,‘陈’在计算机中怎么表达,这个过程就称之为编码。解码是编码的逆过程,它是将存储在计算机的二进制转换为我们可以看到的文字、图片等信息,它体现的是视觉上的刺激。

n位二进制数可以组合成2的n次方个不同的信息,给每个信息规定一个具体码组,这种过程也叫编码。

在编码和解码中,他们就如加密、解密一般,他们一定会遵循某个规则,即y  = f(x),那么x = f(y);否则在解密过程就会导致‘a’解析成‘b’或者乱码。

字符

字符是可使用多种不同字符方案或代码页来表示的抽象实体,它是一个单位的字形、类字形单位或符号的基本信息,也是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

字符是指计算机中使用的字母、数字、字和符号,包括:1、2、3、A、B、C、~!·#¥%……—*()——+等等。在 ASCII 编码中,一个英文字母字符存储需要1个字节。在 GB 2312 编码或 GBK 编码中,一个汉字字符存储需要2个字节。在UTF-8编码中,一个英文字母字符存储需要1个字节,一个汉字字符储存需要3到4个字节。在UTF-16编码 中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。在UTF-32编码中,世界上任何字符的存 储都需要4个字节。

2014112600001_thumb4

字符集

字符是各种文字和符号的总称,而字符集则是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同。而计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。

常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

字符编码

计算机中的信息包括数据信息和控制信息,然而不管是那种信息,他们都是以二进制编码的方式存入计算机中,但是他们是怎么展示在屏幕上的呢?同时在展 现过程中如何才能保证他们不出错?这个时候字符编码就起到了重要作用!字符编码是一套规则,一套建立在符合集合与数字系统之间的对应关系之上的规则,它是 信息处理的基本技术。

使用字符编码这套规则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。

2014112600002_thumb1

二、ASCII

2.1、标准ASCII码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语和其他西欧英语,它是现今最通用的单字节编码系统。

ASCII使用7位或者8位来表示128或者256种可能的字符。标准的ASCII码则是使用7位二进制数来表示所有的大小写字母、数字、标点符合和一些控制字符,其中:

0~31、127(共33个)是控制字符或者通信专用字符,如控制符:LF(换行)、CR(回车)、DEL(删除)等;通信专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等。ASCII值为8、9、10、13分别表示退格、制表、换号、回车字符。

32~126(共95个)字符,32为空格、48~57为阿拉伯数字、65~90为大写字母、97~122为小写字母,其余为一些标点符号和运算符号!

前面提过标准的ASCII码是使用七位来表示字符的,而最高位(b7)则是用作奇偶校验的。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。 (参考百度百科)

下面是ASCII字符对照表,更多详情请关注:》》 ASCII码表 《《

2014112400001_thumb3

2014112400002_thumb

2.2、扩展ASCII码

标准的ASCII是用七位来表示的,那么它的缺陷就非常明显了:只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,基本上只能应用于现代美 国英语,对于其他国家,128个字符肯定不够。于是,这些欧洲国家决定利用字节中闲置的最高位编入新的符号,这样一来,可以表达的字符数最多就为256 个,但是随着产生的问题也就来了:不同的国家有不同的字母,可能同一个编码在不同的国家所表示的字符不同。但是不管怎么样,在这些编码中0~127所表示的字符肯定是一样的,不一样的也只是128~255这一段。

8位的ASCII在欧洲国家表现的不尽人意,那么在其他国家就更加不用说了,我们拥有五千年历史文化的中华名族所包含的汉字多大10多万,不知道是 多少个256。所以一个字节8位表示的256个字符肯定是不够的,那么两个字节呢?可能够了吧!我们常见的汉字就是用两个字节表示的,如GB2312。

2014112600003_thumb

三、GB**

对于欧美国家来说,ASCII能够很好的满足用户的需求,但是当我们中华名族使用计算机时,ASCII明显就不满足需求了,有5000年历史文化的 我们,拥有的汉字达到将近10万,所以为了显示中文,我们必须设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。显示中文的常用字符编码 有:GB2312、GBK、GB18030。

GB2312

GB2312,中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,由中国国家标准总局发布,1981年5月1日实施。

GB2312编码的规则:一个小于127的字符的意义与原来相同,但两个大于127的 字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127 号以下的那些就叫”半角”字符了。

在GB2312中,GB2312共收录6763个汉字,其中一级汉字3755个,二级汉字3008个,还收录了拉丁字母、希腊字母、日文等682个 全角字符。由于GB2312的出现,它基本上解决了我们日常的需要,它所收录的汉子已经覆盖了中国大陆99.75%的使用平率。但是我国文化博大精深,对 于人名、古汉语等方面出现的罕用字,GB2312还是不能处理,于是后面的GBK和GB18030汉字字符集出现了。

GB2312字符集库非常庞大,详情:GB2312简体中文编码表

GBK

GBK,全称《汉字内码扩展规范》,由中华人民共和国全国信息技术标准化技术委员会1995年12月1日制订,也是汉字编码的标准之一。

GBK是GB2312的扩展,他向下与GB2312兼容,,向上支持 ISO 10646.1 国际标准,是前者向后者过渡过程中的一个承上启下的标准。同时它是使用双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),首字节在 81-FE 之间,尾字节在 40-FE 之间,共23940个码位,共收录了21003个汉字。

GB18030

GB18030,国家标准GB18030《信息技术 中文编码字符集》,是我国计算机系统必须遵循的基础性标准之一。它有两个版本:GB18030-2000、GB18030-2005。其中 GB18030-2000仅规定了常用非汉字符号和27533个汉字(包括部首、部件等)的编码,而GB18030-2005是全文强制性标准,市场上销 售的产品必须符合,它是GB18030-2000的基础上增加了42711个汉字和多种我国少数民族文字的编码。

GB18030标准采用单字节、双字节和四字节三种方式对字符编码。(码位总体结构见下图)

单字节部分采用GB/T 11383的编码结构与规则,使用0×00至0×7F码位(对应于ASCII码的相应码位)。双字节部分,首字节码位从0×81至0×FE,尾字节码位分 别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第 一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。

2014112600004_thumb

四、参考文献&进一步阅读

编码:http://baike.baidu.com/subview/237708/11062012.htm(百度百科)

字符:http://baike.baidu.com/view/263416.htm(百度百科)

字符集:http://baike.baidu.com/view/51987.htm(百度百科)

字符编码:http://baike.baidu.com/view/1204863.htm(百度百科)

字符集和字符编码:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html吴秦

ASCII:http://baike.baidu.com/view/15482.htm

GB2312:http://baike.baidu.com/view/443268.htm

GBK:http://baike.baidu.com/view/931619.htm

GB18030:http://baike.baidu.com/view/889058.htm


—–原文出自:http://cmsblogs.com/?p=1412请尊重作者辛勤劳动成果,转载说明出处.

—–个人站点:http://cmsblogs.com