Whether you’re a seasoned professional or just beginning with Android development, this list of resources (including tools, libraries, and blogs) is useful for any developer or team on just about any project, big or small.
OkHttp, a product of Square, is an open-source HTTP and SPDY library for Android and Java. Android comes with two existing HTTP frameworks (HttpURLConnection and HttpClient) but over various Android OS versions have been rife with bugs that can make any normally-sane developer go nuts trying to nail down an HTTP problem. Fortunately, OkHttp solves many of the problems. OkHttp is built upon HttpUrlConnection — so the API should be familiar — but stays up-to-date with fixes from the Android codebase, meaning no compatibility nightmares with older OS versions. Oh, and if you’re looking for something that implements the Apache HttpClient API, that exists as a module: okhttp-apache.
Check out OkHttp
Retrofit, also a product of Square, is an open-source, type-safe REST client for Android and Java. The Android platform doesn’t lend itself much to simple client-server interaction when it comes to APIs. Retrofit aims to provide that, at least for REST requests. Retrofit supports quite a bit of customization, but out of the box will use GSON for JSON-parsing and saves a ton of time building form and multipart requests by simplifying it all into a straightforward interface. Bonus: Retrofit will use OkHttp if it’s available.
Check out Retrofit
Alright, this is the last Square open-source project I’ll list here, I promise (but there are plenty more you should check out). Picasso is an image downloading and caching library sporting a fluent interface for ease of use. Picasso has many options for customizing how it handles the downloaded image (including things like resizing and cropping, as well as providing an interface allowing you to transform the image how you see fit, such as performing a circle crop on it). Picasso will download the image (if not cached) and load it into the given target, which can be anything implementing the Target interface or in its simplest and most common usage, an ImageView.
Check out Picasso
AndroidViews.net is a site that aims to bring together many of the different tools, libraries, and resources into a browsable index. Unfortunately, there’s no search functionality and the site definitely isn’t comprehensive, so you’ll probably also want to check out the next resource on my list…
Check out AndroidViews
If there’s any mailing list you should ever want to be on, this is probably the first. Android Weekly is a newsletter of various musings in the Android development community, including new libraries, tools, blog posts, and more. If you don’t have email (is that a possibility?) or you just don’t like the prospect of giving them your email address, you can always check the site every Monday for the latest issue.
Check out Android Weekly
Android Niceties is a great collections of well-designed and thoughtfully-developed experiences in the Android ecosystem. Android Niceties has covered great, from major brand apps like Duolingo, Expedia, and Etsy to perhaps previously lesser-known apps like Muzei, Timely, and Pocket.
Check out Android Niceties
Touting itself as the “Complete Android Fragment & Activity Lifecycle” (I haven’t completely verified this, but it looks right…), this graph outlines the flow of Activity and Fragment in relation to user interaction within and outside of your application.
Check out Android Lifecycle
This site has a myriad of tools built into it to simplify the creation of various Android-related resources including launcher icons, notification icons, navigation drawer icons, and more…
Check out Android Asset Studio
Built upon the Android Asset Studio, this tool simplifies the previously design-resource encumbering process of creating custom Holo-style Android widgets. Just plug in a color, specify your action bar theme, and get going!
Check out Android Holo Colors Generator
It is what it says it is. This tool is simple and elegant, allowing the user to plug in a number at any density (yeah, even tvdpi) and will calculate the value for any other density. This one’s a keeper for sure.
Check out DPI Calculator for Android
This one might seem a bit more obvious, but maybe you’re not subscribed to it. If you aren’t, you should be. Google is shifting its focus for Android (and the rest of its company, I hear) to be more design-oriented. This is and almost certainly will continue to be where you can find out much more about Android development, design, and UX — old and new. I also recommend the Google Developers channel if you’re into that kind of thing.
Check out the Android Developers YouTube Channel
Thinking about switching to Gradle and need some help with your dependencies? Have been on Gradle but just want to simplify the dependency search? Look no further than Gradle, please. Plug in the name of your favorite library (heck, I dunno, maybe OkHttp, Picasso, or Retrofit?) and Gradle, please will spit out your dependencies “compile” line ready to go. If you’re looking for something a little more complex, you can always check out The Central Repository. Gradle, please also happens to provide all of the standard Google-provided dependencies at the top of the page for your convenience.
Check out Gradle, please
… and last but certainly, not least:
You might be wondering why I’m listing this. Well, I can’t tell you how many times I’ve been through this codebase. I don’t generally sift through on my local machine; rather, I peruse the Android source on Github’s website. Typically, I’ll be wondering how something works (like the complexities of ListView/AdapterView, or the new hotness that is TransitionManager) and want to check it out — this is the best place to really dig in. Oh, and in case you’re still feeling adventurous, there’s also the support library source to browse.
Check out android/platform frameworks base
Happy developing, everyone. Please, share your favorite resources in the comments!
]]>Context objects are so common, and get passed around so frequently, it can be easy to create a situation you didn’t intend. Loading resources, launching a new Activity, obtaining a system service, getting internal file paths, and creating views all require a Context (and that’s not even getting started on the full list!) to accomplish the task. What I’d like to do is provide for you some insights on how Context works alongside some tips that will (hopefully) allow you to leverage it more effectively in your applications.
Not all Context instances are created equal. Depending on the Android application component, the Context you have access to varies slightly:
is a singleton instance running in your application process. It can be accessed via methods like getApplication() from an Activity or Service, and getApplicationContext() from any other object that inherits from Context. Regardless of where or how it is accessed, you will always receive the same instance from within your process.
inherit from ContextWrapper which implements the same API, but proxies all of its method calls to a hidden internal Context instance, also known as its base context. Whenever the framework creates a new Activity or Service instance, it also creates a new ContextImpl instance to do all of the heavy lifting that either component will wrap. Each Activity or Service, and their corresponding base context, are unique per-instance.
is not a Context in and of itself, but the framework passes a Context to it in onReceive() each time a new broadcast event comes in. This instance is a ReceiverRestrictedContext with two main functions disabled; calling registerReceiver() and bindService(). These two functions are not allowed from within an existing BroadcastReceiver.onReceive(). Each time a receiver processes a broadcast, the Context handed to it is a new instance.
is also not a Context but is given one when created that can be accessed via getContext(). If the ContentProvider is running local to the caller (i.e. same application process), then this will actually return the same Application singleton. However, if the two are in separate processes, this will be a newly created instance representing the package the provider is running in.
##Saved References
The first issue we need to address comes from saving a reference to a Context in an object or class that has a lifecycle that extends beyond that of the instance you saved. For example, creating a custom singleton that requires a Context to load resources or access a ContentProvider, and saving a reference to the current Activity or Service in that singleton.
Bad Singleton
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
The problem here is we don’t know where that Context came from, and it is not safe to hold a reference to the object if it ends up being an Activity or a Service. This is a problem because a singleton is managed by a single static reference inside the enclosing class. This means that our object, and ALL the other objects referenced by it, will never be garbage collected. If this Context were an Activity, we would effectively hold hostage in memory all the views and other potentially large objects associated with it; creating a leak.
To protect against this, we modify the singleton to always reference the application context:
Better Singleton
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Now it doesn’t matter where our Context came from, because the reference we are holding is safe. The application context is itself a singleton, so we aren’t leaking anything by creating another static reference to it. Another great example of places where this can crop up is saving references to a Context from inside a running background thread or a pending Handler.
So why can’t we always just reference the application context? Take the middleman out of the equation, as it were, and never have to worry about creating leaks? The answer, as I eluded to in the introduction, is because one Context is not equal to another.
The common actions you can safely take with a given Context object depends on where it came from originally. Below is a table of the common places an application will receive a Context, and in each case what it is useful for:
Capabilitiy | Application | Activity | Service | ContentProvider | BroadcastReceiver |
---|---|---|---|---|---|
Show a Dialog | NO | YES | NO | NO | NO |
Start an Activity | NO1 | YES | NO1 | NO1 | NO1 |
Layout Inflation | NO2 | YES | NO2 | NO2 | NO2 |
Start a Service | YES | YES | YES | YES | YES |
Bind to a Service | YES | YES | YES | YES | NO |
Send a Broadcast | YES | YES | YES | YES | YES |
Register BroadcastReceiver | YES | YES | YES | YES | NO3 |
Load Resource Values | YES | YES | YES | YES | YES |
You can see from looking at the previous table that there are a number of functions the application context is not properly suited to handle; all of them related to working with the UI. In fact, the only implementation equipped to handle all tasks associated with the UI is Activity; the other instances fare pretty much the same in all categories.
Luckily, these three actions are things an application doesn’t really have any place doing outside the scope of an Activity; it’s almost like the framework was designed that way on purpose. Attempting to show a Dialog that was created with a reference to the application context, or starting an Activity from the application context will throw an exception and crash your application…a strong indicator something has gone wrong.
The less obvious issue is inflating layouts. If you read my last piece on layout inflation, you already know that it can be a slightly mysterious process with some hidden behaviors; using the right Context is linked to another one of those behaviors. While the framework will not complain and will return a perfectly good view hierarchy from a LayoutInflater created with the application context, the themes and styles from your app will not be considered in the process. This is because Activity is the only Context on which the themes defined in your manifest are actually attached. Any other instance will use the system default theme to inflate your views, leading to a display output you probably didn’t expect.
Invariably, someone will arrive at the conclusion that these two rules conflict. There is a case in the application’s current design where a long-term reference must be saved and we must save an Activity because the tasks we want to accomplish include manipulation of the UI. If that is the case, I would urge you to reconsider your design, as this would be a textbook instance of fighting the framework.
In most cases, use the Context directly available to you from the enclosing component you’re working within. You can safely hold a reference to it as long as that reference does not extend beyond the lifecycle of that component. As soon as you need to save a reference to a Context from an object that lives beyond your Activity or Service, even temporarily, switch that reference you save over to the application context.
]]>这份文档是Google Java编程风格规范的完整定义。当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合Google的Java编程风格。
与其它的编程风格指南一样,这里所讨论的不仅仅是编码格式美不美观的问题, 同时也讨论一些约定及编码标准。然而,这份文档主要侧重于我们所普遍遵循的规则, 对于那些不是明确强制要求的,我们尽量避免提供意见。
在本文档中,除非另有说明:
@interface
)其他的术语说明会偶尔在后面的文档出现。
本文档中的示例代码并不作为规范。也就是说,虽然示例代码是遵循Google编程风格,但并不意味着这是展现这些代码的唯一方式。 示例中的格式选择不应该被强制定为规则。
源文件以其最顶层的类名来命名,大小写敏感,文件扩展名为.java
。
源文件编码格式为UTF-8。
除了行结束符序列,ASCII水平空格字符(0x20,即空格)是源文件中唯一允许出现的空白字符,这意味着:
对于具有特殊转义序列的任何字符(\b, \t, \n, \f, \r, \“, \‘及),我们使用它的转义序列,而不是相应的八进制(比如\012
)或Unicode(比如\u000a
)转义。
对于剩余的非ASCII字符,是使用实际的Unicode字符(比如∞),还是使用等价的Unicode转义符(比如\u221e),取决于哪个能让代码更易于阅读和理解。
Tip: 在使用Unicode转义符或是一些实际的Unicode字符时,建议做些注释给出解释,这有助于别人阅读和理解。
例如:
1 2 3 4 5 |
|
Tip: 永远不要由于害怕某些程序可能无法正确处理非ASCII字符而让你的代码可读性变差。当程序无法正确处理非ASCII字符时,它自然无法正确运行, 你就会去fix这些问题的了。(言下之意就是大胆去用非ASCII字符,如果真的有需要的话)
一个源文件包含(按顺序地):
以上每个部分之间用一个空行隔开。
如果一个文件包含许可证或版权信息,那么它应当被放在文件最前面。
package语句不换行,列限制(4.4节)并不适用于package语句。(即package语句写在一行里)
即,不要出现类似这样的import语句:import java.util.*;
import语句不换行,列限制(4.4节)并不适用于import语句。(每个import语句独立成行)
import语句可分为以下几组,按照这个顺序,每组由一个空行分隔:
com.google
imports(仅当这个源文件是在com.google
包下)java
importsjavax
imports组内不空行,按字典序排列。
每个顶级类都在一个与它同名的源文件中(当然,还包含.java
后缀)。
例外:package-info.java
,该文件中可没有package-info
类。
类的成员顺序对易学性有很大的影响,但这也不存在唯一的通用法则。不同的类对成员的排序可能是不同的。 最重要的一点,每个类应该以某种逻辑去排序它的成员,维护者应该要能解释这种排序逻辑。比如, 新的方法不能总是习惯性地添加到类的结尾,因为这样就是按时间顺序而非某种逻辑来排序的。
当一个类有多个构造函数,或是多个同名方法,这些函数/方法应该按顺序出现在一起,中间不要放进其它函数/方法。
术语说明:块状结构(block-like construct)指的是一个类,方法或构造函数的主体。需要注意的是,数组初始化中的初始值可被选择性地视为块状结构(4.8.3.1节)。
大括号与if, else, for, do, while
语句一起使用,即使只有一条语句(或是空),也应该把大括号写上。
对于非空块和块状结构,大括号遵循Kernighan和Ritchie风格 (Egyptian brackets):
示例:
1 2 3 4 5 6 7 8 9 10 11 |
|
4.8.1节给出了enum类的一些例外。
一个空的块状结构里什么也不包含,大括号可以简洁地写成{}
,不需要换行。例外:如果它是一个多块语句的一部分(if/else 或 try/catch/finally) ,即使大括号内没内容,右大括号也要换行。
示例:
1
|
|
每当开始一个新的块,缩进增加2个空格,当块结束时,缩进返回先前的缩进级别。缩进级别适用于代码和注释。(见4.1.2节中的代码示例)
每个语句后要换行。
一个项目可以选择一行80个字符或100个字符的列限制,除了下述例外,任何一行如果超过这个字符数限制,必须自动换行。
例外:
package
和import
语句(见3.2节和3.3节)。术语说明:一般情况下,一行长代码为了避免超出列限制(80或100个字符)而被分为多行,我们称之为自动换行(line-wrapping)。
我们并没有全面,确定性的准则来决定在每一种情况下如何自动换行。很多时候,对于同一段代码会有好几种有效的自动换行方式。
Tip: 提取方法或局部变量可以在不换行的情况下解决代码过长的问题(是合理缩短命名长度吧)
自动换行的基本准则是:更倾向于在更高的语法级别处断开。
非赋值运算符
处断开,那么在该符号前断开(比如+,它将位于下一行)。注意:这一点与Google其它语言的编程风格不同(如C++和JavaScript)。 这条规则也适用于以下“类运算符”符号:点分隔符(.),类型界限中的&(<T extends Foo & Bar>
),catch块中的管道符号(catch (FooException | BarException e
)赋值运算符
处断开,通常的做法是在该符号后断开(比如=,它与前面的内容留在同一行)。这条规则也适用于foreach
语句中的分号。自动换行时,第一行后的每一行至少比第一行多缩进4个空格(注意:制表符不用于缩进。见2.3.1节)。
当存在连续自动换行时,缩进可能会多缩进不只4个空格(语法元素存在多级时)。一般而言,两个连续行使用相同的缩进当且仅当它们开始于同级语法元素。
第4.6.3水平对齐一节中指出,不鼓励使用可变数目的空格来对齐前面行的符号。
以下情况需要使用一个空行:
多个连续的空行是允许的,但没有必要这样做(我们也不鼓励这样做)。
除了语言需求和其它规则,并且除了文字,注释和Javadoc用到单个空格,单个ASCII空格也出现在以下几个地方:
(
)(如if, for catch
等)。}
)(如else, catch
)。{
),两个例外:
* @SomeAnnotation({a, b})
(不使用空格)。
* String[][] x = foo;
(大括号间没有空格,见下面的Note)。<T extends Foo & Bar>
)。
* catch块中的管道符号(catch (FooException | BarException e
)。
* foreach
语句中的分号。, : ;
及右括号()
)后new int[] {5, 6}
和new int[] { 5, 6 }
都是可以的。Note:这个规则并不要求或禁止一行的开关或结尾需要额外的空格,只对内部空格做要求。
术语说明:水平对齐指的是通过增加可变数量的空格来使某一行的字符与上一行的相应字符对齐。
这是允许的(而且在不少地方可以看到这样的代码),但Google编程风格对此不做要求。即使对于已经使用水平对齐的代码,我们也不需要去保持这种风格。
以下示例先展示未对齐的代码,然后是对齐的代码:
1 2 3 4 5 |
|
Tip:对齐可增加代码可读性,但它为日后的维护带来问题。考虑未来某个时候,我们需要修改一堆对齐的代码中的一行。 这可能导致原本很漂亮的对齐代码变得错位。很可能它会提示你调整周围代码的空白来使这一堆代码重新水平对齐(比如程序员想保持这种水平对齐的风格), 这就会让你做许多的无用功,增加了reviewer的工作并且可能导致更多的合并冲突。
除非作者和reviewer都认为去掉小括号也不会使代码被误解,或是去掉小括号能让代码更易于阅读,否则我们不应该去掉小括号。 我们没有理由假设读者能记住整个Java运算符优先级表。
枚举常量间用逗号隔开,换行可选。
没有方法和文档的枚举类可写成数组初始化的格式:
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
由于枚举类也是一个类,因此所有适用于其它类的格式规则也适用于枚举类。
不要使用组合声明,比如int a, b;
。
不要在一个代码块的开头把局部变量一次性都声明了(这是c语言的做法),而是在第一次需要使用它时才声明。 局部变量在声明时最好就进行初始化,或者声明后尽快进行初始化。
数组初始化可以写成块状结构,比如,下面的写法都是OK的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
中括号是类型的一部分:String[] args
, 而非String args[]
。
术语说明:switch块的大括号内是一个或多个语句组。每个语句组包含一个或多个switch标签(case FOO:
或default:
),后面跟着一条或多条语句。
与其它块状结构一致,switch块中的内容缩进为2个空格。
每个switch标签后新起一行,再缩进2个空格,写下一条或多条语句。
在一个switch块内,每个语句组要么通过break, continue, return
或抛出异常来终止,要么通过一条注释来说明程序将继续执行到下一个语句组, 任何能表达这个意思的注释都是OK的(典型的是用// fall through
)。这个特殊的注释并不需要在最后一个语句组(一般是default
)中出现。示例:
1 2 3 4 5 6 7 8 9 10 11 |
|
每个switch语句都包含一个default
语句组,即使它什么代码也不包含。
注解紧跟在文档块后面,应用于类、方法和构造函数,一个注解独占一行。这些换行不属于自动换行(第4.5节,自动换行),因此缩进级别不变。例如:
1 2 3 |
|
例外:单个的注解可以和签名的第一行出现在同一行。例如:
1
|
|
应用于字段的注解紧随文档块出现,应用于字段的多个注解允许与字段出现在同一行。例如:
1
|
|
参数和局部变量注解没有特定规则。
块注释与其周围的代码在同一缩进级别。它们可以是/* ... */
风格,也可以是// ...
风格。对于多行的/* ... */
注释,后续行必须从*
开始, 并且与前一行的*
对齐。以下示例注释都是OK的。
1 2 3 4 |
|
注释不要封闭在由星号或其它字符绘制的框架里。
Tip:在写多行注释时,如果你希望在必要时能重新换行(即注释像段落风格一样),那么使用
/* ... */
。
类和成员的modifiers如果存在,则按Java语言规范中推荐的顺序出现。
1
|
|
标识符只能使用ASCII字母和数字,因此每个有效的标识符名称都能匹配正则表达式\w+
。
在Google其它编程语言风格中使用的特殊前缀或后缀,如name_
, mName
, s_name
和kName
,在Java编程风格中都不再使用。
包名全部小写,连续的单词只是简单地连接起来,不使用下划线。
类名都以UpperCamelCase
风格编写。
类名通常是名词或名词短语,接口名称有时可能是形容词或形容词短语。现在还没有特定的规则或行之有效的约定来命名注解类型。
测试类的命名以它要测试的类的名称开始,以Test
结束。例如,HashTest
或HashIntegrationTest
。
方法名都以lowerCamelCase
风格编写。
方法名通常是动词或动词短语。
下划线可能出现在JUnit测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test<MethodUnderTest>_<state>
,例如testPop_emptyStack
。 并不存在唯一正确的方式来命名测试方法。
常量名命名模式为CONSTANT_CASE
,全部字母大写,用下划线分隔单词。那,到底什么算是一个常量?
每个常量都是一个静态final字段,但不是所有静态final字段都是常量。在决定一个字段是否是一个常量时, 考虑它是否真的感觉像是一个常量。例如,如果任何一个该实例的观测状态是可变的,则它几乎肯定不会是一个常量。 只是永远不打算
改变对象一般是不够的,它要真的一直不变才能将它示为常量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
这些名字通常是名词或名词短语。
非常量字段名以lowerCamelCase
风格编写。
这些名字通常是名词或名词短语。
参数名以lowerCamelCase
风格编写。
参数应该避免用单个字符命名。
局部变量名以lowerCamelCase
风格编写,比起其它类型的名称,局部变量名可以有更为宽松的缩写。
虽然缩写更宽松,但还是要避免用单字符进行命名,除了临时变量和循环变量。
即使局部变量是final和不可改变的,也不应该把它示为常量,自然也不能用常量的规则去命名它。
类型变量可用以下两种风格之一进行命名:
驼峰式命名法分大驼峰式命名法(UpperCamelCase
)和小驼峰式命名法(lowerCamelCase
)。 有时,我们有不只一种合理的方式将一个英语词组转换成驼峰形式,如缩略语或不寻常的结构(例如”IPv6”或”iOS”)。Google指定了以下的转换方案。
名字从散文形式
(prose form)开始:
示例:
1 2 3 4 5 6 7 8 |
|
加星号处表示可以,但不推荐。
Note:在英语中,某些带有连字符的单词形式不唯一。例如:”nonempty”和”non-empty”都是正确的,因此方法名
checkNonempty
和checkNonEmpty
也都是正确的。
只要是合法的,就把@Override
注解给用上。
除了下面的例子,对捕获的异常不做响应是极少正确的。(典型的响应方式是打印日志,或者如果它被认为是不可能的,则把它当作一个AssertionError
重新抛出。)
如果它确实是不需要在catch块中做任何响应,需要做注释加以说明(如下面的例子)。
1 2 3 4 5 6 7 |
|
例外:在测试中,如果一个捕获的异常被命名为expected
,则它可以被不加注释地忽略。下面是一种非常常见的情形,用以确保所测试的方法会抛出一个期望中的异常, 因此在这里就没有必要加注释。
1 2 3 4 5 |
|
使用类名调用静态的类成员,而不是具体某个对象或表达式。
1 2 3 4 |
|
极少会去重载Object.finalize
。
Tip:不要使用finalize。如果你非要使用它,请先仔细阅读和理解Effective Java 第7条款:“Avoid Finalizers”,然后不要使用它。
Javadoc块的基本格式如下所示:
1 2 3 4 5 |
|
或者是以下单行形式:
1
|
|
基本格式总是OK的。当整个Javadoc块能容纳于一行时(且没有Javadoc标记@XXX),可以使用单行形式。
空行(即,只包含最左侧星号的行)会出现在段落之间和Javadoc标记(@XXX)之前(如果有的话)。 除了第一个段落,每个段落第一个单词前都有标签<p>
,并且它和第一个单词间没有空格。
标准的Javadoc标记按以下顺序出现:@param
, @return
, @throws
, @deprecated
, 前面这4种标记如果出现,描述都不能为空。 当描述无法在一行中容纳,连续行需要至少再缩进4个空格。
每个类或成员的Javadoc以一个简短的摘要片段开始。这个片段是非常重要的,在某些情况下,它是唯一出现的文本,比如在类和方法索引中。
这只是一个小片段,可以是一个名词短语或动词短语,但不是一个完整的句子。它不会以A {@code Foo} is a...
或This method returns...
开头, 它也不会是一个完整的祈使句,如Save the record...
。然而,由于开头大写及被加了标点,它看起来就像是个完整的句子。
Tip:一个常见的错误是把简单的Javadoc写成
/** @return the customer ID */
,这是不正确的。它应该写成/** Returns the customer ID. */
。
至少在每个public类及它的每个public和protected成员处使用Javadoc,以下是一些例外:
对于简单明显的方法如getFoo
,Javadoc是可选的(即,是可以不写的)。这种情况下除了写“Returns the foo”,确实也没有什么值得写了。
单元测试类中的测试方法可能是不言自明的最常见例子了,我们通常可以从这些方法的描述性命名中知道它是干什么的,因此不需要额外的文档说明。
Tip:如果有一些相关信息是需要读者了解的,那么以上的例外不应作为忽视这些信息的理由。例如,对于方法名
getCanonicalName
, 就不应该忽视文档说明,因为读者很可能不知道词语canonical name
指的是什么。
如果一个方法重载了超类中的方法,那么Javadoc并非必需的。
对于包外不可见的类和方法,如有需要,也是要使用Javadoc的。如果一个注释是用来定义一个类,方法,字段的整体目的或行为, 那么这个注释应该写成Javadoc,这样更统一更友好。
本文档翻译自Google Java Style, 作者@Hawstein。
]]> 上一篇文章零基础开始学习Vim-新手入门有介绍一些学习Vim的资源.
对于从来没有用过Vim的同学,看到上一篇文章时候,有多少人马上开始动手了呢?
刚刚开始接触Vim,一定是无从下手的,甚至会找不到动力去学习和练习!!!至少开始的时候卤煮是这样的.
两个有趣的Vim入门小游戏
这个小游戏是特别有意思,可以在玩这个游戏的过程中熟悉Vim的热键
记得最初是在左耳朵耗子的博客酷壳-CoolShell.cn中看见的.
还有这个在线Vim闯关练习的网站交互做的也很有意思.可以比上面那个学到更多
http://vimgenius.com/
上面两个小游戏都分别闯关之后…… To Be Continue
]]>Vim怎么入门呢???
其实最容易的就是直接在命令行执行 vimtutor 即可进入帮助文档
一进去,又全是英文,头都大了是不是…要做一个优秀的程序员,必须英文好对吧……
要被鄙视的节奏,谁都想看英文帮助文档,但是现在(2013140101),也没能力看懂.真的
但总不能现在特别想学Vim,还得绕一大弯路去花上年把两年学好英语再开始学吧???
只能采用迂回战术了,一边编程一边学英语,嗯,真是太机智了.
那我们在命令行输入 vimtutor zh 就进入中文的新手入门了,把这篇文章看完练习完生存模式就通关了 哈哈哈
那最好的入门方式就是一边看Vim的vimtutor一边进行操作吧,很快就通关啦.记得复习
上面的练习做完之后,可以考虑接下来的练习了
直接链到左耳朵耗子的博客
如何你想学习如何基于github搭建一个自己的Octopress博客,请参考以下两篇文章哈
Mac重装了很久,一直也没有恢复Octopross的博客系统.今天是2013年最后一天啦,顺手弄弄.
这一切基于你的Mac环境什么都妥妥的了.比如xcode,git,ruby…等等
1 2 3 4 5 6 7 8 |
|
1 2 3 |
|
1 2 3 4 5 6 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 |
|
###bundle install
<div class=’bogus-wrapper’>
执行rake install的时候弹出错误提示
1 2 3 4 5 6 7 8 9 |
|
###这时候打开Octopress根目录下的Gemfile修改为如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
试试看rake preview,浏览器打开http://localhost:4000看看效果吧.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
这篇文章写完了.
rake generate && rake deploy之后……
等了十几分钟,还没刷新出网页,总感觉哪里不对劲…
执行以下命令发布Octopress到Github
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
这下好了,你们就可以看到这篇文章啦. 所以.方案肯定是本人验证过的…谢谢大家哈
]]>1
|
|
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel。
FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中(译者注:这个方法在JDK文档中的解释为将字节从给定的可读取字节通道传输到此通道的文件中)。下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 |
|
方法的输入参数position表示从position处开始向目标文件写入数据,count表示最多传输的字节数。 如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。
此外要注意,在SoketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。 因此,SocketChannel可能不会将请求的所有数据(count个字节)全部传输到FileChannel中。
transferTo()方法将数据从FileChannel传输到其他的channel中。下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 |
|
是不是发现这个例子和前面那个例子特别相似?除了调用方法的FileChannel对象不一样外,其他的都一样。
上面所说的关于SocketChannel的问题在transferTo()方法中同样存在。SocketChannel会一直传输数据直到目标buffer被填满。
]]>1
|
|
Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作。
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
Scattering Reads是指数据从一个channel读取到多个buffer中。
如下图描述
代码示例如下:
1 2 3 4 5 6 7 |
|
注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。
Scattering Reads在移动下一个buffer前,必须填满当前的buffer,这也意味着它不适用于动态消息(译者注:消息大小不固定)。换句话说,如果存在消息头和消息体,消息头必须完成填充(例如 128byte),Scattering Reads才能正常工作。
Gathering Writes是指数据从多个buffer写入到同一个channel。
如下图描述:
代码示例如下:
1 2 3 4 5 6 7 8 9 |
|
buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。
因此,如果一个buffer的容量为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息。
]]>1
|
|
Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
下面是NIO Buffer相关的话题列表:
使用Buffer读写数据一般遵循以下四个步骤:
当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。
一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
下面是一个使用Buffer的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
为了理解Buffer的工作原理,需要熟悉它的三个属性:
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。
这里有一个关于capacity,position和limit在读写模式中的说明,详细的解释在插图后面。
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity - 1.
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
Java NIO 有以下Buffer类型
如你所见,这些Buffer类型代表了不同的数据类型。换句话说,就是可以通过char,short,int,long,float 或 double类型来操作缓冲区中的字节。
MappedByteBuffer 有些特别,在涉及它的专门章节中再讲。
要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法。下面是一个分配48字节capacity的ByteBuffer的例子。
1
|
|
这是分配一个可存储1024个字符的CharBuffer:
1
|
|
写数据到Buffer有两种方式:
从Channel写到Buffer的例子:
1
|
|
通过put方法写Buffer的例子:
1
|
|
put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 更多Buffer实现的细节参考JavaDoc。
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
从Buffer中读取数据有两种方式:
从Buffer读取数据到Channel的例子:
1 2 |
|
使用get()方法从Buffer中读取数据的例子:
1
|
|
get方法有很多版本,允许你以不同的方式从Buffer中读取数据。例如,从指定position读取,或者从Buffer中读取数据到字节数组。更多Buffer实现的细节参考JavaDoc。
Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)。
一旦读完Buffer中的数据,需要让Buffer准备好再次被写入。可以通过clear()或compact()方法来完成。
如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。
如果Buffer中有一些未读的数据,调用clear()方法,数据将“被遗忘”,意味着不再有任何标记会告诉你哪些数据被读过,哪些还没有。
如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。
compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。例如:
1 2 3 4 5 |
|
可以使用equals()和compareTo()方法两个Buffer。
当满足下列条件时,表示两个Buffer相等:
如你所见,equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较。实际上,它只比较Buffer中的剩余元素。
compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:
作者:Jakob Jenkov 译者:airu 校对:丁一
Java NIO的通道类似流,但又有些不同:
既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。 通道可以异步地读写。 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。 正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。如下图所示:
Channel的实现
这些是Java NIO中最重要的通道的实现:
FileChannel 从文件中读写数据。
DatagramChannel 能通过UDP读写网络中的数据。
SocketChannel 能通过TCP读写网络中的数据。
ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
基本的 Channel 示例
下面是一个使用FileChannel读取数据到Buffer中的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
注意 buf.flip() 的调用,首先读取数据到Buffer,然后反转Buffer,接着再从Buffer中读取数据。下一节会深入讲解Buffer的更多细节。
]]>作者:Jakob Jenkov 译者:airu 校对:丁一
Java NIO 由以下几个核心部分组成:
虽然Java NIO中除此之外还有很多的类和组件,但在我看来,Channel,Buffer和Selector构成了核心的API。其他组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类。因此,在概述中我将集中在这三个组件上。其他组件会在单独的章节中讲到
基本上,所有的 IO 在 NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示:
Channel和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:
正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
与这些类一起的有一些有趣的接口,但为简单起见,我尽量在概述中不提到它们。
本教程其它章节与它们相关的地方我会进行解释。
以下是Java NIO里关键的Buffer实现:
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。
Java NIO 还有个 Mappedyteuffer,用于表示内存映射文件, 我也不打算在概述中说明。
Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。
这是在一个单线程中使用一个Selector处理3个Channel的图示:
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
]]>译文原文地址:http://ifeve.com/java-nio-all/
英文原文地址:http://tutorials.jenkov.com/java-nio/index.html
作者:Jakob Jenkov 译者:郭蕾 校对:方腾飞
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。
Java NIO: Channels and Buffers(通道和缓冲区)
标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Java NIO: Asynchronous IO(异步IO)
Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Java NIO: Selectors(选择器)
Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
下面是Java NIO系列文章的目录:
上一次已经有结果了,有三种通讯方式
文章连接:Click Me
1.使用接口,让Activity扮演管理角色,负责分发消息到该窗口的子View
2.使用LocalBroadcastManager + IntentFilter解决不同组件通讯,Intent负责搭载数据
3.EventBus
4.otto 这里不做介绍,下面有demo链接,基于注解的解偶通信组件
其实按照MVC的思想,Activity就真正的变成了Controler,
Activity中不涉及任何的业务逻辑的代码,只负责分发消息到不同的子View(Fragment)。
如果希望整个应用只有一个Activity,就需要再抽象出一层Controller,负责处理Activity与其子Controller的通讯
我们直接看代码吧,因为表达能力还训练,加上有点懒 ^_^ 😄
项目结构
###首先是布局de代码
- /layout/article_view.xml
** ArticleFragment.java ** 关联的布局
1 2 3 4 5 6 7 8 |
|
/layout/news_articles.xml
** HeadlinesFragment.java ** 关联的布局1 2 3 4 5 6 |
|
/layout-large/new_articles.xml
** HeadlinesFragment.java ** 关联的布局,在平板大分辨率的时候回被自动启用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
MainActivity.java
首页 -_- 其实就那么一页 哈哈哈 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
|
HeadlinesFragment.java
ListView菜单布局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 54 55 |
|
ArticleFragment.java
详情页布局。。就一个TextView啦。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 54 55 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
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 54 55 56 57 58 59 60 61 62 63 |
|
** 这是一篇译文 **先是在google+上看见老外分享的,然后又看见有人翻译并且之微博分享了,真的是很好的东西,当初我学Android的时候怎么没人给咱指条明路呢;
** 原文在这里 ** : Click Me
** 翻译de孩子 ** : 新浪微博
老婆大人最近想学Android开发,向我寻求帮助。所以我觉得为了避免老婆处罚并且让她在Android应用样式风格和界面一致性方面从一开始就在正确的方向上、确保让她更清楚认识到参考Google提供的UI设计规范是如此重要,我最好能收集一些学习资源。
下面是我找到的非常好的资源,也希望能帮助到大家:
如果你不知道Java编程语言或者说你是从其他语言转过来的,需要熟悉下Java的话,下面这些是很好的让你开始了解Java的学习资源。
开始学Java - “Java初学者入门” http://www.javacoffeebreak.com/tutorials/gettingstarted/
Java语言编程介绍 - Lars Vogel http://www.vogella.com/articles/JavaIntroduction/article.html
你用Java编程 (麻省理工学院) 点我跳转吧,连接太长..放出来不好看
视频 -学习Java: 第一部分: 基础介绍 http://www.youtube.com/watch?v=3MZIkY55fS0
免费Java在线互动教程(译者注:提供了在线编辑器) http://www.learnjavaonline.org/
Java初学者教程 http://www.javabeginner.com/
加的一行建议
其实我也英文不行,英文不行就看** 毕向东 ** 和 ** 马士兵 ** 的Java基础教程吧孩子
如果你要问我教程到哪里下载,对不起,这个问题应该是我问你^_^
当你** 学好了Java **,你已经准备好正式开始学习Android开发了
注: 即使你不打算看下面的,不过上面这个一定要看(译者注:上面这个真的很干货,一定要看)
开始Android开发 - 作者 Ray Wenderlich http://www.raywenderlich.com/5527/getting-started-with-android-development
始Android开发 - 作者 Chris Lacy https://plus.google.com/104649936579980037256/posts/UQD4e1jgLS1
upport Library (用于支持旧版本Android设备) http://developer.android.com/tools/extras/support-library.html
下面是视频教程 Android 训练营视频教程 Tutorial: Android Application Development - A 9,000 foot overview
Android Asset Studio http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html
ActionBarSherlock http://actionbarsherlock.com/
AndroidSideMenu https://github.com/dmitry-zaitsev/AndroidSideMenu
SlidingMenu https://github.com/jfeinstein10/SlidingMenu
ViewPagerIndicator http://viewpagerindicator.com/
UnifiedPreference https://github.com/saik0/UnifiedPreference
Pull To Refresh Views for Android https://github.com/chrisbanes/Android-PullToRefresh
SwipeListView https://github.com/47deg/android-swipelistview
开发中如何使用 Fragments http://mobile.tutsplus.com/tutorials/android/android-sdk_fragments/
Android中使用Fragment - 教程 http://www.vogella.com/articles/AndroidFragments/article.html
理解Fragment的生命周期 http://blog.csdn.net/forever_crying/article/details/8238863
当开发Android应用的时候,理解Java、界面布局和Fragment使用很重要。 不过理解Android UI设计规范并在你自己的APP 设计中保证体验一致性也同等重要,遵循这些规范能让用户体验更好。
希望上面提到的资源对你开始Android开发有所帮助。如果你已经做Android一段时间了,也许你也能在这些资源中发现一些干货让你进一步提升。
** 最后,祝大家开发愉快 :-) **
]]>###Fragment的优点 —————- * adding and removing Fragment可以做动画的效果,平滑过度
自动化堆栈管理,所以返回键可以删除动态添加的Fragment,最后销毁Activity,无需做过多判断
集成ActionBar的标签,可以替代TabHost,ActivityGrounp,与谷歌设计风格紧密结合
布局更加模块化.与原Activity中的Layout分块化,VCBase的分块化道理相同
灵活准确的生命周期去管理当前View的状态记录以及横竖屏处理
Fragment管理的View,可同时使用在Phone和Pad上,一份代码两份机器,可重用性高
Is a View, More than View
可以从startActivityForResult中接收到返回结果,但是View不能
唯一Id标识,可以从FragmentManager中获取id对应的Fragment
与其说是Fragment的缺点,不如说是每个应用程序模块之间的通讯都面临地耦合问题
该方案的缺点
该方案的缺点