和其他技术一样,我们需要了解安卓,并且真正了解安卓. 本指南提供了一些问题样本,在招聘兼职或全职安卓应用程序开发人员时,这些问题是评估应聘者掌握安卓移动框架的广度和深度的关键.
所面临的挑战

安卓已经成为 主流智能手机 该平台在全球拥有超过81%的市场份额(超过苹果iOS的15%和微软窗户的4%之和)和2.4亿台移动设备. 还不算太糟. 随之而来的是对开发人才的巨大需求,所以要定位 精英 安卓应用程序开发人员可能是一项艰巨的任务.
找到他们需要一个高效的招聘过程,正如我们在文章中描述的那样 在寻找精英少数-发现和雇用最好的软件开发人员在行业. 这样的过程可以通过问题来扩充——就像本文中提出的问题——来识别那些分布在全球各地的真正的安卓专家.
安卓是一个基于Java和XML的基于Linux的智能手机操作系统. 因为安卓操作系统不仅仅是一种语言, 但一个完整的, 丰富和不断增长的软件框架, 它有一个 很多 掌握. 在撰写本文时,安卓已经是第7个年头了,现在是第4版.4(“奇巧”)和已经经历了19个SDK发布.
谷歌在2007年将安卓作为一个开源项目引入 AOSP),以便在新兴的智能手机市场站稳脚跟. 许多硬件供应商已经在他们的手机上使用了安卓系统(三星, 宏达电, 索尼, 摩托罗拉和LG只是举几个例子), 经常添加自己的自定义特性和代码. 当不兼容或特定于供应商的bug出现时,这有时会给开发人员带来额外的麻烦(也就是变通方法)。. 安卓本身也不是一个完美的移动应用开发操作系统, 当然,由于它有时缺乏文档和一些行为怪异的代码,但它仍然是一股不可忽视的力量.
安卓应用开发平台提供了大量的特性和支持类:
- 用户界面,动画,图形,不同屏幕尺寸和方向的支持
- 触摸屏键盘和手势识别
- 数据库、内容提供者、内容解析器、适配器
- 位置检测、传感器、服务
- 线程的选项
- 加速计算
- Inter-app沟通
- 媒体播放和录制
- 网络和连接
- 谷歌播放商店和应用内部计费
- 本地化
- 调试工具
- 和更多…
这种复杂性会让任何开发人员晕头转向,更不用说招聘经理了. 那么,在采访安卓程序员时,我们应该从哪里开始呢?
真正的安卓专家将会对不同的实现选项以及它们的影响和后果有一个全面和有原则的理解.
安卓移动应用开发专家和新手的区别不仅仅在于如何编写应用程序. 当面对复杂的任务时, 真正的安卓专家将会对不同的实现选项以及它们的影响和后果有一个透彻和有原则的理解. 本指南中提出的问题可以帮助你找到那些少有的安卓大师,他们有这种理解,并可以显著提高你的项目的生产力和吞吐量.
用户界面
的 用户界面 (UI)是应用的外观. 应用的UI非常重要,因为它构成了用户如何与你的应用进行交互和感知的基础. 安卓提供了许多开发者可以利用和定制的类,同时也提供了一个用户可以依赖的通用框架.
例如,安卓为顶部导航系统提供了一个通用的解决方案 ActionBar. 它还提供了对 NavigationDrawer 用户可以通过点击ActionBar菜单按钮或滑动屏幕的左边缘来滑动打开和关闭. 安卓提供了大量的UI类和小部件来布局视图, 创建动画, 执行自定义图, 显示 画板 (图标、位图、形状等.),更.
安卓 UI的大部分内容都可以用XML指定, 但也可以编写自定义子类来扩展安卓 UI类来创建自定义视图和行为. UI的范围相当广泛(它甚至包括媒体播放, video, audio, 手机振动, 例如), 所以我们不能涵盖所有内容, 但我们将强调一些关键领域,这是可靠的安卓开发者应该精通的.
问:什么是活动和片段? 什么时候以及为什么应该使用其中一种而不是另一种?
An 活动 用户界面组件是否代表屏幕上的主要关注焦点. 相比之下, 片段, 随着屏幕更大的平板电脑出现而推出, 附加到活动并在活动中显示的组件是可重用的吗. 多个片段可以在一个活动中同时显示. 虽然可以只使用Activities来开发UI, 这通常是一个坏主意,因为他们的代码以后不能在其他活动中重用. 精英开发人员知道这一点,并编写片段(有时在琐碎的活动中使用) 未来的证明 他们的应用程序. 使用这种方法, 该活动支持其附加的片段, 让碎片, 他们的布局和视图处理了大部分用户界面.
例如, 假设您希望用户能够水平滚动一组页面,其中每个页面可能显示一个列表, 照片, 相片画廊, 指示板, 或形式. 这里你可以用 : 视图page 在你的活动中,它的条目是片段,分别处理每个独特的用户界面功能. 如果开发人员将这些页面编写为Activities, 他们必须将它们重构为片段.
还要注意的是,虽然你可以使用一个活动而不使用Fragment,但是反过来是不正确的.
问:什么是适配器,何时以及如何使用它们?
如果不使用适配器,就很难开发安卓应用程序,因为适配器非常重要.
适配器适用于何处? 它们架起了模型和视图的桥梁.g. 适配器视图s 如 列表视图, 显示数据表格, 纺纱 和 : 视图pages)和基础数据. 它们提供对数据项的访问,并负责为数据集中的每个项创建视图.
安卓本身并没有采用MVC模式. 您定义适合您的模型. 安卓帮助你布局和渲染视图, 你可以定制安卓的activity和片段,它们通常作为控制器.
新手开发人员可能会尝试使用简单的方法 助手 适配器等 Array适配器
, Simple适配器
和 Simple光标适配器
在可能的情况下, 但对于当今应用程序通常需要的一些更复杂的视图来说,这些视图通常太有限了. 熟练的开发人员将编写扩展的适配器 Base适配器
直接,因为它比上面提到的子类助手更强大、更灵活.
下面的代码片段显示了在列表视图中显示联系人的自定义联系适配器. (注:只显示较重要的方法.)
//用于说明目的的基本数据模型
类接触{
公共int id;
公共字符串名称;
公共字符串电话;
}
公共类联系适配器扩展Base适配器实现List适配器 {
上下文mContext;
List<联系> m联系s;
公共联系适配器(Context Context) {
mContext =上下文;
}
//调用此方法将数据附加到该适配器,并在数据更改时调用.
public void newData(List<联系> data) {
m联系s =数据;
//通知适配器视图数据已经改变,并在必要时重新绘制.
notifyDataSetChanged ();
}
//适配器的关键——绑定数据到视图布局.
@Override
public 视图 get视图(int position, 视图 convert视图, 视图Group parent) {
联系 联系 = m联系s.(位置);
LinearLayout视图= (LinearLayout) convert视图;
If (视图 == null) {
//“膨胀”我们的联系人.XML视图的出现.
LayoutInflater充气器= (LayoutInflater)
mContext.getSystemService(上下文.LAYOUT_INFLATER_SERVICE);
视图 = (LinearLayout)膨胀器.充气(右.布局.接触,零);
}
//将数据绑定到布局中相应的text视图.
((Text视图)视图.find视图ById (R.id.的名字).setText(联系.的名字);
((Text视图)视图.find视图ById (R.id.手机)).setText(联系.电话);
// ... 等. ...
返回视图;
}
}
用户的要求很高. 你的应用程序必须执行和响应,否则人们会感到沮丧,并干脆停止使用它.
而对应用程序的要求应该明确定义可接受的响应时间(尽管越短越好), 开发人员自己应该对什么是合理的有一个大致的认识,并采取相应的措施来优化性能. 例如, 当从服务器获取大量数据时, 应该采取步骤避免锁定用户界面(i.e.,通过在后台线程加载数据).
经验丰富的安卓开发者应该有各种各样的性能优化技巧. 下面的问题旨在评估他们在这方面的敏锐性.
问:有哪些方法可以优化视图的使用?
如果不小心, 不知情的安卓开发者很容易在布局中创建更多的视图. 你可以从布局中移除的视图越多,你的应用程序的响应速度就越快. 更少的视图意味着更少的内存消耗和更少的垃圾收集, 以及更少的初始化工作, 布局, 画, 和遍历视图.
糟糕的设计很快就会显现出来, 例如, 当试图快速滚动未优化的布局, 哪些会显得迟钝和不稳定. 如果特别坏, 滚动体验可能无法使用, 特别是在cpu速度较慢的低端设备上. 下面是一些有经验的安卓开发者应该熟悉的视图优化技术.
技术#1:优化布局中的视图.
布局是为活动和片段定义视图的XML资源文件. 因为它们的设计对应用程序性能非常重要, 谷歌写了一整本培训指南关于 优化布局层次结构.
让我们以以下布局为例:

这个布局由四个视图组成:一个根水平视图 LinearLayout
封装了一个 Image视图
和一个垂直 LinearLayout
包含两个 两个
. 这就形成了一个三层的层次结构.
这个布局可以通过使用一个根将其层次结构扁平化为两个级别来优化 使用
放弃第二个 LinearLayout
完全. 的 Image视图
可以定位拥抱左边的父母吗 使用
和 两个
可以拥抱的 Image视图
或者父结点的右边. 在速度和内存上的节省似乎不是单独的,但当应用到大量 列表视图
元素(例如),它可以快速地加起来并显著地影响性能.
技巧2:使用
标签在你的布局文件.
聪明的做法是使用
如果可能的话,在定义一个想要膨胀并添加到现有视图中的视图时 视图Group
,例如 显示数据表格
or 列表视图
. 这避免了创建不必要的 中间人 视图Group
如 使用
or LinearLayout
只是为了封装子视图. 的
Tag只是父视图的占位符,它的子视图将被附加到父视图中. 在下面的示例中,只有 Image视图
将被添加到父视图中,从而消除了对封装视图的需要.
考虑以下布局:
<使用 xmlns:安卓="http://schemas.安卓.com/apk/res/安卓”
安卓: 布局_width = " match_parent "
安卓:布局_height="match_parent">
使用>
上述用法 使用
,虽然是标准的做法,但可以通过使用
标签如下所示,从而优化这个布局:
现在我们少用了一个视图!
技巧#3:考虑使用视图Holder模式,但要谨慎使用.
使用视图Holder模式可以提高性能,但它不是一个完美的解决方案. 事实上,有些人会说这真的是一个 反模式. 在下一个问题中,我们将讨论视图Holder方法的优缺点. 这些问题都应该仔细考虑,然后再决定是否, 在哪里, 以及何时使用这种技术.
什么是视图Holder模式,它是如何使用的? 支持和反对使用它的理由是什么? 有什么替代方案吗?
视图Holder模式是安卓开发新手接触到的第一个模式之一, 如前所述, 我们还会进一步讨论, 有些人可能称之为反模式.
当我们希望在安卓 UI中显示项目列表时,我们通常使用:
- 一个具体的
适配器视图
子类,如 列表视图
, 显示数据表格
等.
- 一种基础数据集,通常是 pojo 或者一个 光标 (一组数据库行)
- An
适配器
类,负责用指定的数据元素创建和填充视图
的 适配器视图
试图回收不再显示在屏幕上的视图. 这个简单但有效的技术可以让应用程序避免:
另一项可以避免的额外费用与呼叫有关 视图.find视图ById ()
重复地在布局中定位子视图. 调用 视图.find视图ById ()
是昂贵的,因为相当大的块的布局(一个层次结构)必须遍历在每个调用,以找到所需的子视图在一个潜在的复杂布局. 当快速滚动带有嵌套布局的列表时,可能会出现明显的延迟, 这给大多数开发人员留下了一个丑陋的问题来寻找解决方案.
进入 视图Holder 缓存模式. 但首先,让我们从历史的角度来看. 在安卓 2.2 (Froyo), Dalvik虚拟机和它的垃圾收集器的性能是令人沮丧的, 正是在这种情况下,为了帮助解决这个问题,视图Holder模式应运而生.
然而, 包括JIT编译器和垃圾收集器的巨大改进, 不缓存的代价 视图.find视图ById ()
已经大大减少了(尽管从开发人员的角度来看,这仍然是值得的,而且并不昂贵). 因此,视图Holder已成为一种不太必要的方法, 考虑到它的一些负面影响,哪个是特别有问题的, 如:
这是 谷歌说的最新的 简单地说,是关于视图Holder的. 定义一个类来缓存的结果 视图.find视图ById ()
:
静态类视图Holder {
Text视图文本;
Text视图时间戳;
Image视图图标;
ProgressBar进展;
int位置;
}
然后在 get视图 ()
,缓存它的结果:
视图Holder 持有人 = new 视图Holder();
持有人.icon = (Image视图) convert视图.find视图ById (R.id.listitem_image);
持有人.text = (Text视图) convert视图.find视图ById (R.id.listitem_text);
持有人.时间戳= (Text视图) convert视图.find视图ById (R.id.listitem_timestamp);
持有人.progress = (ProgressBar) convert视图.find视图ById (R.id.progress_spinner);
convert视图.setTag(持有人);
精明的开发人员认识到视图Holder是一个通过调用来填充的结构体 视图.find视图ById ()
. 视图Holder结构体被存储在父视图通过 视图.setTag ()
. 当回收一个视图时,我们可以点击视图Holder缓存:
视图Holder 持有人 = (视图Holder) convert视图.getTag ();
现在,这种技术对于编写教程非常有用. 但是,例如,当您需要添加 onclicklistener
, 根据状态变化改变绘图等, 您最终会让您的适配器类做大量它不应该做的工作.
我们能做些什么改变呢? 引用 联系适配器
代码,我们将修改膨胀的视图(在本例中 LinearLayout
)将子视图缓存在 单独的关注,父视图本身:
@Override
public 视图 get视图(int position, 视图 convert视图, 视图Group parent) {
联系 联系 = m联系s.(位置);
联系视图视图= (联系视图) convert视图;
If (视图 == null) {
//“膨胀”我们的联系人.XML视图的出现.
LayoutInflater充气器= (LayoutInflater)
mContext.getSystemService(上下文.LAYOUT_INFLATER_SERVICE);
视图 = (LinearLayout)膨胀器.充气(右.布局.接触,零);
}
//绑定联系人数据到适当的子视图布局.
视图.setModel(接触);
返回视图;
}
我们现在需要做的就是编辑我们的联系布局,并将其根元素替换为 联系视图
(如下所示)而不是 LinearLayout
说,. 就是这样! 我们现在有了适当的关注点分离, 单一用途(更少杂乱)的类, 我们避免使用 视图.setTag ()
和 视图.getTag ()
在缓存子视图时没有开销的方法.
公共类联系视图扩展LinearLayout {
私人接触模型;
私人Text视图名称;
私人Text视图电话;
@Override
onfinishinflation () {
这.的名字 = (Text视图)视图.find视图ById (R.id.的名字);
这.电话= (Text视图)视图.find视图ById (R.id.电话);
}
public void setModel(联系 model) {
这.模型=模型;
bindModel ();
}
private void bindModel() {
这.的名字.setText(模型.的名字);
这.电话.setText(模型.电话);
}
}
问:什么是ANR? 是什么引起的?如何避免?
ANR 指的是臭名昭著的安卓 应用程序没有响应 对话框,当应用程序花费太多时间在主线程上计算时,可以触发. 主线程处理安卓 UI,所以在那里做更多的工作会变慢 响应性. 因此,当你不再后台长时间运行任务时,ANR经常是一种鞭笞.
导致ANR的任务示例包括:
- 上传/加载数据到/从云
- 保存/加载缓存数据到/从磁盘
- 对数据进行排序、过滤和搜索
这些操作的共同之处在于它们可能都很慢. 它们通常是资源限制的, 这意味着他们经常需要时间, 有时比预期的要长得多.
记住这一点, 任何要执行的与ui无关的工作, 特别是上述类型的资源约束任务, 应该在后台线程上完成吗. 安卓有几种方法来完成后台工作,并且已经衍生出一些不错的第三方开源库.
存在几个线程选项,每个都有自己的优点和缺点. 异步计算本身就很复杂,这些类和接口试图简化这方面的工作. 看看谷歌的 进程和线程 更多详细信息的指南.
让我们来看看安卓中一些更有用的线程选项:
AsyncTask
AsyncTask
是一个帮助类,让您生成一个简短的后台操作. 它最常用来在UI线程上显示结果. 这通常是新手开发人员在处理异步性时学习的第一个类, 因为它避免了直接设置和使用线程.
不幸的是, AsyncTask
有什么严重的问题吗. 当需要使用其他更高级的线程选项时,它已经成为了一种支持. 多年来,谷歌在运行时行为方面发生了转变 AsyncTask
,从第一次连续运行(与其他 asynctask
在单个后台线程上),以并行方式运行,然后回到串行方式运行! 这意味着,如果并发的类型(i.e.、串行和. 并行)对你的应用很重要, 您必须检查正在运行的SDK版本的安卓使用 AsyncTask
. 开发人员最好使用 处理程序线程
or 遗嘱执行人
作为一个结果.
线程
的 线程
类是安卓最基本的执行环境,有自己的调用栈, 参数, 和局部变量. 每个应用程序都有一个主线程(用于用户界面)和系统线程组中的其他线程. 你可以(a)子类 线程
并在 run ()
方法或(b)传递a 可运行的
返回到它的构造函数,然后通过调用其 start ()
方法. 一旦启动,线程可以让位给其他线程,也可以休眠. You can’t externally stop a thread though; your only options are to interrupt it, 等待它自己完成, or 加入()
it.
处理程序线程
然而线程在默认情况下没有循环器 处理程序线程
是一个线程有一个 电影 附加. 环形器提供一个 处理程序 这允许消息在线程之间传递. 处理程序也允许执行 可运行的 其附加线程上的任务,可以是立即的,也可以是稍后的某个时间点上的.
下面是实例化的方法 处理程序线程
在上面发布要执行的任务:
类Voting活动 {
private 可运行的 processVotes = new 可运行的() {
Public void run () {
}
};
public void onCreate (Bundle savedInstanceState) {
处理程序线程 = new 处理程序线程(“投票任务”);
处理程序线程.开始();
处理程序 = new 处理程序(处理程序线程.get电影 ());
//现在让我们在刚创建的新线程上尽快执行一个可运行的任务:
处理程序.邮报》(新可运行的 () {
Public void run () {
//接受投票.
}
});
//让我们也安排一个任务在未来的新线程上执行10秒:
处理程序.postDelayed (processVotes, 10000);
}
}
下面是我们如何设置一个处理程序线程来依次处理消息:
类Download线程扩展处理程序线程 {
int START_MSG = 0;
public static final int STOP_MSG = 1;
Download线程(字符串名称){
超级(名称);
}
@Override
public void h和leMessage(Message msg);
开关(味精.什么){
案例START_MSG:
/ /开始下载...
打破;
案例STOP_MSG:
/ /停止下载...
打破;
默认值:
打破;
}
}
}
然后我们可以产卵和使用这个线程如下:
Main活动类扩展活动 {
public void onCreate (Bundle savedInstanceState) {
//设置我们的Download线程接收消息.
下载线程下载线程= new Download线程("Image Downloader");
download线程.开始();
处理程序download处理程序 = new处理程序(下载线程.get电影 ());
}
public void startDownloading() {
download处理程序.sendEmptyMessage (Download线程.START_MSG);
}
public void stopDownloading() {
download处理程序.sendEmptyMessage (Download线程.STOP_MSG);
}
}
遗嘱执行人Service 和 线程Pool遗嘱执行人
线程Pool遗嘱执行人
实现了 遗嘱执行人Service
接口,它在几个池化线程中的一个上执行已提交的任务. 当执行许多任务时,由于每个任务调用的开销减少,线程池通常可以提高性能. 如果您需要异步执行许多任务, 使用这个机制,你可以很容易地生成工人. 谷歌指出, 线程Pool遗嘱执行人
有点像可配置的厨房水槽吗, 并且鼓励开发人员使用预先配置好的版本,例如 newCached线程Pool ()
, newFixed线程Pool ()
和 newSingle线程遗嘱执行人 ()
.
问:什么是装载机? 什么时候和为什么使用它们?
在不断寻求从主线程中卸载工作的过程中,安卓引入了加载器(loader) 加载程序Manager
和 加载程序
类). 加载器简化了通常提供适配器的活动和片段中的数据的异步加载. 它们监视数据源,并在内容更改时交付新的结果. So, 而不是阻塞和等待数据到达(从您的云或磁盘, 例如), 使用一个加载器. 看到谷歌的 加载器指南 为更多的细节.
Q:什么是RxJava ?为什么它这么酷?
并不是每个安卓开发者都知道这一点, 所以当他们这么做的时候,我们的书里会给他们加分. 这是一个巨大的创新,也许是我们文章中最令人兴奋的部分. RxJava Netflix的开源端口是微软的吗 反应性的扩展 图书馆. 反应性编程 编程范例是否与数据流和变化有关. 反应式编程已经出现一段时间了,但是RxJava还没有. RxJava对于编写同步/异步、基于事件的可观察序列非常有用. 它是为高效查询和消费数据而设计的(动态).
RxJava不是一个特定于安卓的库,但可以使 巨大的 对安卓应用的影响,取决于它的使用方式. 它对于需要低延迟的并发和/或异步应用程序非常有用. 例如, 它的一个主要用例是异步加载数据,而无需过多考虑线程, 处理程序, 或执行人. You might use RxJava to load data f或者一个dapters; e.g., 在UI线程上订阅感兴趣的数据, 安排要在后台线程上执行的工作, 然后在UI线程上观察显示的结果.
RxJava允许你链接数据和事件, 然后创建选择的序列, 过滤器, 转置, 组成, 在最终的观察者收到结果通知之前合并数据. 这里我们不可能深入讨论RxJava, 但我们之所以想提及这一点,是因为精英开发者应该意识到这一点. 你可以阅读更多有关它的信息 在这里.
问:如何从网上缓存大量的大图像?
如果你正在开发一个图像库应用程序,如Instagram或Pinterest, 从服务器缓存许多(大型)映像变得非常关键. 为了追求最佳性能, 您希望快速呈现图像, 因此,缓存它们以避免从网络重新加载它们是必要的. 因为你不能在RAM中缓存太多的大的几兆字节的图像(因为安卓内存是不稳定的,是一个有限的资源), 你真的别无选择,只能将图像缓存到磁盘上(闪存).
不需要编写自己的缓存类,您可以利用和包装 DiskLruCache
. 这是一个必不可少的开源解决方案,经验丰富的安卓开发者应该意识到这一点. 它可以用于将任何类型的数据缓存到文件系统目录, 由您指定的大小限制.
除了安卓适当
谷歌的安卓团队雇佣了很多优秀的工程师, 它不能为开发人员面临的新问题提供或预期所有可以想象到的解决方案. 这就是第三方开源,甚至其他谷歌团队的切入点.
因此,精明的安卓开发人员将熟悉近年来出现的许多更有价值的库. 这些技术可以用来为旧手机升级新的安卓系统功能, 增加现有功能, 或者引入新功能.
那些将新的安卓功能扩展到老款手机的公司, 然而, 随着用户升级到 更新的安卓版本和设备. 但也就是说,安卓开发者确实有一个 安卓设备、版本和品牌的巨大分裂性 与iOS不同.
问:有哪些更有用的安卓开源库,你如何利用它们?
有许多可用的开源库和附加组件, 来自谷歌和其他地方, 这是经验丰富的安卓开发者通常会利用的. 一些更有用的方法包括:
- ActionBarSherlock ActionBarSherlock是安卓的扩展 支持库 设计的便利使用操作栏设计模式跨越所有版本的安卓与单一的API. 它允许您轻松地开发一个应用程序与操作栏的每个版本的安卓 2.x和了.
- DiskLruCache -如上所述, DiskLruCache是一个强大的, 然而,简单的, 最近最少使用的(LRU)缓存实现,用于存储数据 在磁盘上,池大小有限制.
- 浓缩咖啡 — 谷歌于2013年10月宣布 仍然在开发人员预览, 浓缩咖啡是一个新的UI测试框架,其目标是让开发人员轻松编写可靠的UI测试. 最重要的是,浓缩咖啡不再需要考虑多线程测试的复杂性. 浓缩咖啡已经被许多谷歌应用程序使用(Drive, Maps,谷歌+等).
- 番石榴 谷歌的番石榴项目包含了谷歌内部使用的几个核心库:collections, 缓存, 原语支持, 并发库, 常见的注释, 字符串处理, I/O, 和一些非常有用的类的大杂烩. 看到 番石榴的维基 的更多信息. 它的目的是使Java“更愉快”,改进 防御性编程,添加优化,提高效率. 它填充并改进了集合等公共类, 数学, 反射, 字符串, 范围, 哈希, I / O和更多.
- NineOld安卓s - NineOld安卓s推出了全新改进的安卓 Honeycomb系统.0)动画API可用于旧版本1.0和向前兼容的最新版本的安卓. 在《PT视讯官网》之前的动画是非常有限的. 新的API提供了更强大的功能和灵活性来动画对象,并通过旋转来重新定位视图, 翻译, Alpha和scale基元, 例如. 该库提供了一个可跨所有安卓版本工作的包装器.
- 协议缓冲区 谷歌的协议缓冲区是语言中立的, 平台无关的, 序列化结构化数据的可扩展机制, 它提供了JSON或XML的可行替代方案. 这是一种传输对象数据的有效方法, 例如,在原始二进制格式中,不需要(un)marshal. 用谷歌的话说,数据传输是“更小、更快、更简单”的.
- RxJava -如上所述, RxJava是一个响应式扩展,可以让你创建异步, 使用可观察序列的基于事件的代码, 在很多情况下,这是无价的.
- 凌空抽射 - 凌空抽射是一个相对较新的谷歌库 于2013年5月在谷歌I/O上推出 这使得安卓应用的联网更快更容易. 奇怪的是, 除了源代码,谷歌还没有发布自己的教程或文档, 这让一些开发者怀疑或谨慎, 但也有几个人写了这样的教程 这 和 这. 高亮显示包括一个自动加载图像的视图, 具有优先级的HTTP请求队列, 以及自动选择特定于安卓版本的最佳HTTP库.
调试和调优
有经验的开发人员依赖于伟大的工具来帮助他们构建伟大的软件, 特别是为了测试和优化的目的. 安卓一开始提供这些服务的速度有点慢,但它的工具箱终于填满了. 安卓提供了问题的运行时检测,附加的类可以帮助检测问题. 还有一些外部工具,比如 摘要讨论 查看内存使用情况,查找泄漏,查看线程使用情况,查看视图层次结构等.
问:什么是“不保留活动”开发选项?为什么它有用?
谷歌提供了大量的运行时 调试选项 for devices that can be activated under Settings > Developer options. 一个更有用的方法是 不要让活动 当用户离开activity时,立即销毁它. 它对于测试活动的保存和恢复非常有用.e., onSaveInstanceState(包)
和 onCreate(安卓.os.包)
代码路径),否则很难触发. 它还可以发现活动生命周期的其他对称问题, 如正确打开和关闭资源之间 onResume ()
和 onPause ()
回调,例如.
问:什么是StrictMode,为什么它有用?
在不断提高应用程序响应性和保持UI平稳运行的过程中, StrictMode 是一个很有价值的安卓工具,可以帮助检测偶然的磁盘和网络访问的主线程(或任何线程).
在你的应用的开发版本中(永远不要在发布的应用中启用StrictMode!), 你告诉安卓你感兴趣的问题是什么,并定义应用的“惩罚”(i.e.如果它们被发现,该怎么办. 然而,并不是它发现的每个问题都需要修复, 你也不能肯定它会找到所有的问题, 它提供了一个非常有用的窗口来了解你的应用的缺陷(如果有的话).
下面是如何在你的应用程序的onCreate方法中启用StrictMode:
public void onCreate() {
//仅在开发应用程序时启用!
如果(DEVELOPER_MODE) {
//告诉安卓你想检测什么线程问题,当发现时该做什么.
StrictMode.set线程Policy(新StrictMode.线程Policy.构建器()
.detectDiskReads ()
.detectDiskWrites ()
.detectNetwork() //或使用 .detectAll()用于所有可检测的问题
.penaltyLog ()
.build ());
//告诉安卓你想要检测什么VM问题,当发现时该做什么.
StrictMode.setVmPolicy(新StrictMode.VmPolicy.构建器()
.detectLeakedSqlLiteObjects ()
.detectLeakedClosableObjects ()
.penaltyLog () //记录问题
.penaltyDeath() //然后杀死应用程序
.build ());
}
超级.onCreate ();
}
问:什么是“lint”工具? 它是做什么的?你会如何使用它?
线头 是一个安卓工具,扫描你的项目,并生成一个详细的报告,包含错误和警告在你的代码和资源文件,你可能考虑修复. 它不是完美的, 有时它报告的是假阳性(顶级开发人员知道要有所保留), 但它仍然是一个有用的工具. 例如,它可以:
- 检测未使用的文件和资源,以减少应用程序膨胀
- 告诉你应该在哪里回收
TypedArrays
在使用后
- 确定您可能在何处透支覆盖视图的背景
- 加上许多其他问题
您可以使IDE在编辑源文件时提醒您这些问题, 但无论如何,在命令行上运行lint以定期生成完整的报告通常是一个好主意, 或者作为自动构建的双产物. 有关更多信息,请参见 使用lint改进代码.
总结
我们只是触及了安卓应用开发的表面, 突出平台的一些更重要的方面和细微差别, 以及杠杆工具.
鉴于安卓的复杂性, 手机应用程序开发人员可能需要数年时间才能真正精通. 安卓拥有巨大的市场渗透率和丰富的框架. 考虑到他们的需求和成为绝地大师所需要的时间,寻找安卓绝地大师是一个挑战. 我们希望你在这篇文章中提出的问题能在你寻找精英的时候对你的目标有所帮助, 精华的开发人员.