安卓

雇用 Top 3%自由职业者Android开发商

Toptal.是Android开发人员,工程师,程序员,编码器,建筑师和顾问的市场。顶级公司和初创公司选择Toptal Android自由职业者为他们的关键任务软件项目。

无风险审判,仅在满意时付款。

客户率 Toptal. Android Developers4.4 / 5.0平均截至2021年4月1日的665条评论

通过领先的品牌和初创公司信任

聘请自由职业者Android开发人员和工程师

Jasmin Kurti.

自由职业者Android开发商

波斯尼亚和黑塞哥维那(简称:波黑Toptal. Member Since June 16, 2016

Jasmin是一个负责任的开发人员,具有开发创新和复杂的Android应用程序的大量经验。他'S非常有组织,以他的沟通方式为自己骄傲,并享受团队工作的好处。 Jasmin颁发挑战和解决它们。

展示更多

Patrick Keenum.

自由职业者Android开发商

美国Toptal. Member Since June 11, 2018

Patrick是一名高级全堆员工程师,拥有超过10年的经验,开发美观,可靠和可扩展的产品。他对从概念到发射的想法引发的热情,与各级技术敏锐的客户合作,并建立帮助公司成长的产品。

展示更多

Muhammed MutaHr.

自由职业者Android开发商

美国Toptal. Member Since March 2, 2018

Muhammad是一名高级软件工程师,拥有几年的行业经验,包括来自公共教育部门(WSU),私营的医疗保健公司(经络)和汽车行业的公共财富500强公司(GM&aam)。在他的职业生涯中,他在HTML / CSS中设计了Web应用程序,使用JavaScript Frameworks(Aganular / Ionic)开发的客户端应用程序,并使用Java和C#以开发强大的服务器端应用程序。

展示更多

Boris Yordanov.

自由职业者Android开发商

葡萄牙Toptal. Member Since July 4, 2017

Boris是一家全日制的Web开发人员,主要与Vanilla JavaScript合作,以及最受欢迎的JavaScript框架,如角,反应和流星。他在14岁的时候制作了他的第一个网站,从那时起,他在自由职业生涯中制作了400多个WordPress网站。如今,他设计并构建自定义Web应用程序和网站。

展示更多

丹纳帕尔斯基

自由职业者Android开发商

美国Toptal. Member Since December 20, 2015

丹是一种软件架构师和技术专业专业专注于区块链技术的应用。他拥有多年的经验,为客户提供专业的咨询服务,从初创公司到全球公司。他专门为艰难的工程挑战带来严格的测试和防弹码。他在人工智能,区块链,机器学习和自动化的许多方面都有深刻的专业知识。

展示更多

Richard Kolkovich

自由职业者Android开发商

美国Toptal. Member Since May 6, 2015

Richard已经从技术支持中运行了对联合创始人的歌剧院。在他的职业生涯中,理查德已经积累了深度水平的技术理解,以及对建筑物的其他必要元素和成功业务的广泛理解。他的经验和技术专业知识使他非常适合解决技术问题。

展示更多

Branislav Zlatkovic.

自由职业者Android开发商

塞尔维亚Toptal. Member Since September 30, 2014

Branislav是一名软件工程师,拥有五年的Android开发经验,适用于Sony Mobile,Bottle Rocket Studios和Mindgeek等公司。广泛的经验涵盖了各种不同的项目设置,从开始到完成应用程序,以完成大规模的长期项目的开发和连续交付。他是一个适度的完美主义者'对任何开发团队的有价值的贡献者。

展示更多

阿德里安świętoń.

自由职业者Android开发商

波兰Toptal. Member Since March 24, 2016

阿德里安是一个优秀的开发商,拥有各种技能,在他的处置经验中有十年。他在信息学中拥有专业的学位,并在每个级别的项目上工作,从低级装配编码到多平台桌面和移动应用程序。最近的备注项目包括飞行/种族模拟器,在两个轴上旋转了360°旋转,支持多个游戏和OpenGL音乐可视化应用程序。

展示更多

Hubert Orlik-Grzesik

自由职业者Android开发商

波兰Toptal. Member Since January 21, 2014

休伯特是一个非常快的学习者; - 曾经曾经能够在早上拿起乐器,并在下午玩得很好。他在与新技术和新项目上工作时具有相同的技能。他重视高质量的代码和对细节的关注,他深深地关心大型UX。

展示更多

德米特里·雷祖瑟赛德

自由职业者Android开发商

俄罗斯Toptal. Member Since September 21, 2015

Dmitry是一个拥有六年多的经验的Android开发人员,他们沟通好,总是试图找到适合该项目的最佳技术。他'曾经有过Git,Lua(Corona SDK),Rxjava,匕首等。他'S与大型团队合作,开发yandex浏览器,拥有超过1000万的安装。他'S还开发了自己的项目:一个有250,000个安装的游戏,并发布了其他几个应用程序。

展示更多

Ivan Dimoski.

自由职业者Android开发商

瑞典Toptal. Member Since November 26, 2013

Ivan是一个专业,拥有超过10年的Android开发经验。他最近的作用包括唯一的贡献,团队领导和工程管理,为TrueCaller 17中17个敏捷的跨职能团队,将惊人的功能带来了250万百万个以上的活跃用户。作为一个充满激情的人,他重视开放性和简单性,因为创造一个成功的故事。

展示更多

立即注册以查看更多档案。

开始招聘

需要一个专业管理的软件开发项目
从开始到结束?

无论您的业务需求是什么,我们都会策划全球顶级人才的全面托管团队,为您提供最高质量的解决方案。

招聘指南

聘请伟大的Android开发人员指南

真正的Android专家不仅仅知道如何代码一个应用程序。他们对平台进行了全面的欣赏'S细微差别和可用的不同实现选项。本指南中提出的问题有助于识别这些Android开发人员,以便在Android平台上生成大量结果的经验。

阅读招聘指南

安卓招聘资源

TrustPilot.
Toptal. in the press

...允许公司快速组装具有特定项目的合适技能的团队。

尽管对编码人员的需求加速了,Toptaltal旨在自行为几乎常春藤联盟级审查。

我们的客户
构建一个全球使用的跨平台应用程序
Thierry Jakicevic.
构建一个全球使用的跨平台应用程序
1
2
3
为游戏创建一个应用程序
Conor Kenney.
为游戏创建一个应用程序
1
2
3
领导数字转型
Elmar Platzer.
领导数字转型
1
2
3
推荐书

三普国不会'T存在没有顶尖。顶部项目使我们能够用产品经理,铅开发商和高级设计师迅速发展我们的基础。在60多天内,我们从概念到阿尔法。速度,知识,专业知识和灵活性是秒数。 Toptaltal团队作为三级队员的三级队员的一部分。他们贡献并就像其他人一样贡献并获得了发展的所有权。我们将继续使用TOPTAL。作为一个启动,他们是我们的秘密武器。

布兰特利步长,首席执行官& Co-Founder

三级

我对Toptaltal的经验非常满意。我必须与我一起工作的专业人士在几个小时内与我一起。我知道在与他讨论我的项目后,他是我想要的候选人。我立即雇了他,他浪费了浪费时间来到我的项目,甚至通过添加一些优秀的设计元素来加强额外的英里,以增强我们的整体外观。

Paul Fenley,导演

k dunn.& Associates

我与令人难以置信的 - 聪明,驱动和响应性的开发人员。它曾经很难找到优质的工程师和顾问。现在它是't.

Ryan Rockefeller,CEO

辐射群

Toptal.立即了解我们的项目。我们与阿根廷的特殊自由职业者与阿根廷,从第1天沉浸在我们的行业中,与我们的团队无缝混合,理解我们的愿景,并产生了顶级缺口结果。 Toptal与卓越的开发人员和程序员相连,非常容易。

Jason Kulik,联合创始人

PROHATCH.

作为一个有限资源的小公司,我们可以'不起赚得昂贵的错误。 Toptal为我们提供了一个经验丰富的程序员,他们能够击中地面运行并立即开始贡献。这是一个伟大的经历和我们'd再次在心跳中重复。

斯图尔特Pocknee,校长

站点特定的软件解决方案

我们使用Toptal聘请开发人员,具有广泛的亚马逊网络服务体验。我们采访了四名候选人,其中一个候选人竟然有适合我们的要求。该过程快速有效。

ABNERGUZMÁNVILLA,CTO和首席科学家

照片kharma.

Sergio是一个令人敬畏的开发人员。顶级陷波,响应,并有效地完成了工作。

Dennis Baldwin,首席技术专家和联合创始人

PriceBlink.

与马林一起工作是一种快乐。他是有能力,专业,灵活的,非常快速地了解所需的内容以及如何实现它。

和réFischer,CTO

发布

我们需要一个专家工程师,他们可以立即启动我们的项目。辛巴纳斯与他的工作超出了我们的期望。不得不采访和追逐专家开发商是一个优秀的时光,让每个人都对我们的选择感到更加舒适,以改变平台来利用更强大的语言。 Toptog易于方便地制作了该过程。 Toptal现在是我们寻找专家级别帮助的第一名。

Web开发的高级VP德里克未成年人

NetWorld Media Group.

Toptal.'S开发人员和建筑师都非常专业,易于使用。他们生产的解决方案相当定价和最高品质,减少了推出的时间。再次感谢,Toptal。

Jeremy Wessels,CEO

Kognosi.

我们拥有Toptal的伟大体验。他们将我们与完美的开发人员配对,为我们的应用程序并使过程非常容易。它也很容易超出初始时间范围,我们能够在我们的项目中保持相同的承包商。我们绝对推荐顶尖,用于快速和无缝地找到高质量的人才。

Ryan Morrissey,CTO

应用业务技术,LLC

I'M Toptal令人难以置信地印象深刻。我们的开发人员每天与我沟通,是一个非常强大的编码器。他'真正的专业人士,他的工作很棒。顶部5星。

Pietro Casoar,CEO

Ronin Play Pty Ltd

与Toptal一起工作是一个很好的体验。在使用它们之前,我花了很长时间采访其他自由职业者和尚未'找到我需要的东西。与Toptal一起参与后,他们在几天内与完美的开发人员匹配。开发商I.'m不仅可以提供质量代码,而且他还提出了我达到的事情的建议't thought of. It'对我来说清楚,阿拉夫里知道他在做什么。强烈推荐!

乔治城,首席执行官

Buravard,Inc。

作为顶级合格的前端开发人员,我也运营了自己的咨询练习。当客户来找我来帮助填补他们的团队上的关键角色时,Toptal是我唯一舒适的推荐的地方。 Toptal.'整个候选池是最好的。 Toptal是我的最佳价值我'在近一年的专业在线工作中发现了。

Ethan Brooks,CTO

Langlotz专利&商标作品,Inc。

在嘻嘻哈哈'早期,我们以及时的方式,我们需要一流的开发商,以实惠的价格。 Toptal送货!

Lara Aldag,CEO

h

Toptal.让候选人非常容易,让您能使他们有能使他们有能力提供。我肯定会向寻求高技能开发人员的人推荐他们的服务。

Michael Gluckman,数据经理

mxit.

Toptal.迅速匹配我们的项目与最佳开发人员的能力只是一流的。开发商已成为我们团队的一部分,我对他们中的每一个都证明了专业承诺的水平。对于那些希望远程工作的人与最好的工程师来说,看起来不仅仅是Toptaltal。

Laurent Alis,创始人

临身

Toptal.让找到合格的工程师微风。我们需要经验丰富的ASP.NET MVC架构师来指导我们的启动应用程序的开发,并在不到一周内为我们提供三位伟大的候选人。在我们选择后,工程师立即在线并击中地面运行。它比我们自己发现和兽医候选人更快和更容易。

杰夫凯利,联合创始人

协调解决方案

我们需要在Scala中的一些短期工作,Toptal在24小时内发现了我们一个伟大的开发人员。这不仅仅是通过任何其他平台都无法实现。

Franco Arda,联合创始人

whatadswork.com

Toptal.为正在进行快速发展和规模的企业提供禁令解决方案。每个工程师我们'通过Toptal签约已经很快集成到我们的团队中,并将其工作持有最高标准的质量,同时保持炽热的发展速度。

Greg Kimball,联合创始人

nifti.com.

如何通过Toptal雇用Android开发人员

1

与我们的行业专家交谈

Tophteal Engineering主任将与您合作,了解您的目标,技术需求和团队动态。
2

与手工选择的人才合作

在几天内,我们'LL向您介绍您的项目的正确的Android开发人员。平均匹配时间在24小时内。
3

右边合身,保证

与您的新的Android开发人员合作进行试用期(仅在满意的情况下付款),确保他们'在开始参与之前,右边适合。

常见问题解答

  • Toptal Android开发人员如何不同?

    在Toptal,我们彻底屏蔽了我们的Android开发人员,以确保我们与最高口径的人才相匹配。每年申请加入Toptal Network的100,000多人,削减少于3%。您将与工程专家(从不泛化招聘人员或人力资源代表)合作,了解您的目标,技术需求和团队动态。最终结果:来自我们网络的专家审计人才,习惯符合您的业务需求。 现在开始。

  • 我可以在不到48小时穿过Toptal雇用Android开发人员吗?

    根据可用性以及您可以进行的快速,您可以在注册的48小时内开始使用Android开发人员。 现在开始。

  • Toptal Android开发人员的无风险试用期是多少?

    我们确保您和您的Android开发人员之间的每次参与开始于最多两周的试用期。这意味着您有时间确认订婚将是成功的。如果您对结果完全满意,我们会为您收取时间并继续接触,只要您想要。如果你没有完全满意,你将不会收取费用。从那里,我们可以通过部分方式,或者我们可以为您提供可能更适合的另一个专家,并与我们将开始第二名,无风险的审判。 现在开始。

分享
安卓

如何聘请一个伟大的Android开发人员

与任何技术一样,知道Android,然后真的知道Android。本指南提供了对评估候选人掌握Android移动框架掌握的宽度和深度的关键的问题,这些问题在寻求聘请Android应用程序开发人员兼职或全职时,请访问候选人的掌握框架。

挑战

安卓已成为 主导智能手机 地球上的平台超过81%的市场份额(超过Apple IOS的​​15%和Microsoft Windows'4%合并)和全球2.4亿移动设备。不是太寒酸。对于开发人才的需求巨大,所以定位 精英 Android应用程序开发人员可以是一个令人生畏的任务。

发现它们需要一个高效的招聘过程,如我们的帖子所述 寻找精英少数 - 寻找和雇用业内最佳的软件开发人员。然后可以增加这种过程 - 例如本文所呈现的问题 - 以识别全球的那些稀疏分布的候选者是真正的Android专家。

安卓是一个基于Java和XML的Linux之上内置的智能手机操作系统。由于Android操作系统不仅仅是一种语言,而且是一个完整的,丰富而越来越多的软件框架,它有一个 很多 掌握。截至本文的撰写,Android在第7年,现在在4.4版(“Kitkat”)并经过了19个SDK发布。

谷歌在2007年推出了Android作为开源项目(见 AOSP.)所以它可以在新兴智能手机市场上立足。众多硬件供应商使用了Android的手机(三星,HTC,索尼,摩托罗拉和LG只是为了命名几个),通常添加自己的自定义功能和代码。当出现不兼容或特定于供应商的错误时,这有时会为开发人员创造额外的头痛(阅读:解决方法)。 Android本身并不是一个完美的移动应用程序开发操作系统,当然 - 有时缺乏文档和一些古怪的行为代码 - 但它仍然是估计的力量。

安卓应用程序开发平台提供了丰盛的功能和支持课程:

  • 用户界面,动画,图形,不同屏幕大小支持和方向
  • 触摸屏键盘和手势识别
  • 数据库,内容提供商,内容解析器,适配器
  • 位置检测,传感器,服务
  • 线程选项
  • 加速计算
  • 应用间通信
  • 媒体播放和录制
  • 网络和连接
  • 谷歌 Play商店和应用内结算
  • 本土化
  • 调试工具
  • 以及更多…

这种复杂性可以使任何开发人员的头部旋转,更不用说招聘经理。那么在采访Android程序员时,我们在哪里开始?

真正的Android专家将对不同的实施方案提供全面而原则性的升值以及其影响和后果。

来自Neophyte的专家Android Mobile App Developer的专家超出了如何编写应用程序的知识。面对复杂的任务时,真正的Android专家将对不同的实施方案提供全面而原则性的欣赏,以及其影响和后果。本指南中提出的问题可以帮助您识别具有此理解的罕见的Android大师,并且因此可以显着提高项目的生产力和吞吐量。

用户界面

用户界面 (UI)是您的应用程序的脸。应用程序的UI至关重要,因为它形成了用户如何与您的应用程序进行交互的基础。 Android提供众多课程,开发人员利用和定制,同时还提供用户来依赖的一般框架。

例如,Android为顶级导航系统提供通用解决方案 ActionBar.。它还提供支持 导航拖车 该用户可以通过点击ActionBar Menu按钮或刷屏幕的左边缘来滑动打开并关闭。 Android提供丰富的UI类和小部件来铺设视图,创建动画,执行自定义绘图,显示 可爱的 (图标,位图,形状等)等等。

可以使用XML指定大部分Android UI,但是一个也可以编写扩展Android UI类的自定义子类以创建自定义视图和行为。 UI的范围非常广泛(例如,它甚至包括媒体播放,视频,音频,电话振动),因此我们无法覆盖在此处的所有内容,但我们将突出显示某些可靠的Android开发人员应该的关键区域精通。

问:活动和碎片是什么?什么时候和为什么你应该用一个呢?

一个 活动 是一个用户界面组件,表示在屏幕上关注的主要焦点。相比之下, 碎片由于具有较大屏幕出现的平板电脑而引入,是可重复使用的组件,其在活动中附加并显示。可以在活动中立即显示多个片段。虽然可以仅使用活动开发UI,但这通常是一个坏主意,因为他们的代码后来不能在其他活动中重复使用。 Elite开发人员知道这个并写下片段(有时在琐碎的活动中使用) 未来证明 他们的应用程序。通过这种方法,活动支持其附加的碎片,让碎片,布局和视图处理狮子的用户界面的份额。

例如,假设您希望用户能够水平滚动一组页面,每个页面都可以显示列表,照片,照片库,仪表板或表单。在这里,您可以使用a viewPager. 在您的活动中,其项目是处理每个唯一用户界面功能的片段。如果开发人员将这些页面写为活动,则他们必须将它们重构为碎片。

另请注意,虽然您可以使用没有片段的活动,但反向不是真的。

问:它们是什么适配器,何时以及如何以及如何使用?

在不使用某个适配器的情况下开发Android应用程序很难,因为它们是如此重要。

适配器在哪里适合?他们弥合了模型和视图(例如 AdapterViews.listviews., Gridviews., 旋转器俯视员)具有底层数据。它们提供对数据项的访问权限,并负责为数据集中的每个项目创建视图。

安卓并未采用MVC模式本身。您定义适合您的模型。 Android可帮助您布局和呈现视图,您自定义Android的活动和通常充当控制器的片段。

新手开发人员可能会尝试使用简单 帮手 adapters like ArrayAdapter, SimpleAdapterSimpleCursorAdapter when possible, but these are usually too limiting for some of the more complex views typically required by today’s apps. Master developers will write adapters that extend BaseAdapter directly, because it is more powerful and flexible than the subclass helpers mentioned above.

以下代码段显示了一个自定义联系人,在ListView中显示联系人。 (注意:仅显示所需的更重要的方法。)

// A basic data model for illustrative purposes
class Contact {
    public int id;
    public String name;
    public String phone;
}

public class ContactAdapter extends BaseAdapter implements ListAdapter {
    Context mContext;
    List<Contact> mContacts;

    public ContactAdapter(Context context) {
        mContext = context;
    }
    
    // Call this method to attach data to this adapter, and call when the data changes.
    public void newData(List<Contact> data) {
        mContacts = data;
        // Inform AdapterView that data has change and to redraw if necessary.
        notifyDataSetChanged(); 
    }

    // The crux of the adapter -- bind data to the view layout.
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Contact contact = mContacts.get(position);
        LinearLayout view = (LinearLayout) convertView;
        if (view == null) {
            // "Inflate" our contact.xml view into existence.
            LayoutInflater inflater = (LayoutInflater)
                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = (LinearLayout) inflater.inflate(R.layout.contact, null);
        }
        // Bind the data to their appropriate TextViews in the layout.
        ((TextView)view.findViewById(R.id.name)).setText(contact.name);
        ((TextView)view.findViewById(R.id.phone)).setText(contact.phone);
        // ... etc. ...
        return view;
    }
}

性能和响应能力

用户如此苛刻。您的应用程序必须履行并响应,或者人们会沮丧,只需停止使用它。

虽然应用程序的要求应明确定义可接受的响应时间(虽然较短总是更好),但是开发人员本身应该对合理的合理和采取措施相应地优化性能的一般意义。例如,当从服务器获取批次数据时,应该采取步骤以避免锁定用户界面(即,通过加载背景线程上的数据)。

经验丰富的Android开发人员可以预期拥有各种性能优化伎俩。遵循这方面的问题旨在评估他们的敏锐。

问:优化视图使用的方法是什么?

如果不小心,则不知不觉的Android开发人员可以轻松地带走,并在其布局中创建更多的观点而不是必需的。您可以从布局中删除的视图越多,您的应用程序就越多。较少的视图意味着消耗和减少垃圾收集的内存较少,以及少量工作初始化,布局,绘图和遍历视图。

例如,当试图通过未优化的布局迅速滚动时,差的设计变得很快明显,这可能出现迟钝和生涩。如果特别糟糕,滚动体验可能变得无法使用,特别是在具有较慢的CPU的下端设备上。以下是一些View优化技术,应熟悉经验丰富的Android开发人员。

技术#1:优化布局中的视图。

布局是XML资源文件,用于定义活动和片段的视图。由于他们的设计对应用程序性能如此重要,因此谷歌已经编写了关于主题的整个培训指南 优化布局层次结构.

让我们拍下行布局:

This layout consists of four views: a root level horizontal LinearLayout that encapsulates an ImageView 和 a vertical LinearLayout that contains two TextViews. This results in a three level hierarchy.

This layout can be optimized by flattening its hierarchy to two levels by using a single root RelativeLayout 和 dropping the second LinearLayout altogether. The ImageView can be positioned to hug the left side of the parent RelativeLayout 和 the TextViews can hug the ImageView or the right side of the parent. The savings in speed and memory may not seem like much individually, but when applied to numerous ListView elements (for example), it can add up quickly and dramatically affect performance.

技术#2:使用 <merge> 标记在您的布局文件中。

It’s smart to use the <merge> tag if possible when defining a view that is intended to be inflated and added to an existing ViewGroup, such as a GridView or ListView. This avoids creating an unnecessary 中间人 ViewGroupRelativeLayout or LinearLayout just to encapsulate child views. The <merge> tag is simply a placeholder for the parent view that its children will be attached to. In the following example, only the ImageView will be added to the parent, thereby eliminating the need for one of the encapsulating views.

考虑以下布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

这 above use of RelativeLayout, though standard practice, can be eliminated by using a <merge> tag as follows, thereby optimizing this layout:

<!-- The merge tag represents the parent view of this layout -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge>

现在我们使用一个较少的观点!

技术#3:考虑使用观众模式,但是明智地这样做。

使用观众模式可以提高性能,但这不是一个完美的解决方案。事实上,有些人会争辩说它真的是一个 反模式。在下一个问题中,我们讨论了观众方法的优缺点。在决定何处和何时采用这种技术之前,应仔细称重和考虑这些问题。

问:什么是观众模式,它是如何雇用的?使用它的原因和反对是什么?什么是替代品?

介绍了第一个模式NoviceS和谐开发人员是视为观众模式 - 如前所述,如前所述,除了将进一步讨论的情况下,有些可能称为反模式。

当我们希望在Android UI中显示项目列表时,我们通常会使用:

  • A concrete AdapterView subclass such as ListView, GridView, etc.
  • 底层数据集,通常是数组 Pojos. 或者 光标 (一组数据库行)
  • 一个 Adapter class responsible for creating and populating Views with specified data elements

AdapterView attempts to recycle Views that are no longer displayed on-screen. This simple but effective technique allows applications to avoid:

  • 产生垃圾收集的成本
  • 产生布局通货膨胀的成本

一个 additional cost that can be avoided relates to calling View.findViewById() repeatedly to locate child views within a layout. Calls to View.findViewById() are expensive because sizable chunks of the layout (a hierarchical structure) must be traversed on each call to find a desired child View within a potentially complex layout. There can be noticeable lag when rapidly scrolling through a list with nested layouts, leaving most developers with an ugly problem in search of a solution.

输入 观点 缓存模式。但首先,让我们把它陷入历史的角度。在Android 2.2(Froyo)之前,Dalvik VM及其垃圾收集器的表现令人沮丧,因此在这方面,并帮助解决了观众模式的这个问题。

However, with the inclusion of a JIT compiler and vast improvements in the Garbage Collector, the cost of not caching View.findViewById() has decreased dramatically (although it’s still worthwhile and not expensive in terms of developer effort). ViewHolder has therefore become a less necessary approach, which is particularly problematic given some of its negative side effects, such as:

这是这一点 谷歌必须说的最新消息 about ViewHolder, in a nutshell. Define a class to cache the results of View.findViewById():

static class ViewHolder {
  		TextView text;
  		TextView timestamp;
  		ImageView icon;
  		ProgressBar progress;
  		int position;
}

一个d then in getView() 的 your Adapter class, cache its results:

观点 holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);

Savvy developers recognize that ViewHolder is a struct that is populated via calls to View.findViewById(). The ViewHolder struct is stored in the parent View via View.setTag(). When recycling a View, we can tap the ViewHolder cache:

观点 holder = (ViewHolder) convertView.getTag(); 

Now this technique is great for writing tutorials. However, for example, when you need to add OnClickListeners, change drawables according to state changes, etc, you wind up with your Adapter class doing a huge amount of work that it should not be doing.

What can we do differently? Referencing the 接触Adapter code from a previous question, we’ll modify the inflated View (in this case LinearLayout) to cache child views in a 单独关注,父视图本身:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   Contact contact = mContacts.get(position);
   ContactView view = (ContactView) convertView;
   if (view == null) {
       // "Inflate" our contact.xml view into existence.
       LayoutInflater inflater = (LayoutInflater)
           mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       view = (LinearLayout) inflater.inflate(R.layout.contact, null);
        }
   // Bind contact data to appropriate child Views in the layout.
   view.setModel(contact);
   return view;
}

All we need to do now is edit our Contact layout and replace its root element with 接触View (shown below) instead of LinearLayout, say. That’s it! We now have proper separation of concerns, single purpose (less cluttered) classes, and we avoid using View.setTag()View.getTag() methods without overhead while caching child Views.

public class ContactView extends LinearLayout {
  private Contact model;
  private TextView name;
  private TextView phone;

  @Override
  protected void onFinishInflate() {
  	this.name = (TextView)view.findViewById(R.id.name);
    this.phone = (TextView)view.findViewById(R.id.phone);
  }
  
  public void setModel(Contact model) { 
    this.model = model; 
    bindModel();
  }
  
  private void bindModel() {
    this.name.setText(model.name);
    this.phone.setText(model.phone);
  }
}

问:ANR是什么?导致它们以及如何避免是什么?

ANR. 是指Android的臭名昭着 应用程序没有响应 当应用程序在主线程上花费太多时间计算时,应用程序可以触发对话框。主线程处理Android UI,所以做更多的工作,减慢了 响应能力。因此,当您没有背景运行任务时,ANR通常是尾裤。

可能导致ANR的任务示例包括:

  • 从云上载/加载数据
  • 将缓存数据保存/从磁盘
  • 排序,过滤和搜索数据

这些操作的共同之处是它们都能慢。它们通常是资源限制,这意味着他们经常需要时间,有时比​​所需或预期的要长。

考虑到这一点,应在背景线程上完成任何与UI相关的工作,特别是上述资源限制任务。 Android有几种方法可以完成背景工作,并为此产生了一些好的第三方开源库。

存在几种线程选项,每个选项都具有自身的优点和缺点。异步计算本质上是复杂的,这些类和接口尝试简化努力。查看谷歌的 流程和线程 导游更详细的信息。

让我们探索Android中的一些更有用的线程选项:

Asynctask.

Asynctask. 是一个辅助课,让你产生短的背景操作。它最常用于在UI线程上显示结果。这通常是第一级新手开发人员学习如何在处理ASychronicity时使用,因为它避免了必须直接设置和使用线程。

Unfortunately, Asynctask. has some serious gotchas. It has become somewhat of a crutch when other, more advanced, threading options ought to be used. Google has flip-flopped over the years on the runtime behavior of Asynctask., from first being run serially (with other Asynctask.s on a single background thread), to being run in parallel, and then back to serial! This means that, if the type of concurrency (i.e., serial vs. parallel) is important to your app, you must check the running SDK version of Android before using an Asynctask.. Developers may be better off using a 处理程序thread. or Executor as a result.

线

线 class is Android’s most basic execution environment with its own call stack, arguments, and local variables. Every app has one main thread (for user interface) and other threads in a system thread group. You can either (a) subclass 线 和 execute code within its run() method or (b) pass a 逃货 to its constructor which then starts its execution by calling its start() method. Once started, the thread can yield to other threads or can sleep. You can’t externally stop a thread though; your only options are to interrupt it, wait for it to complete on its own, or join() it.

处理程序thread.

Whereas Threads don’t have Loopers by default, a 处理程序thread. is a Thread that has a 随附的。弯刀提供了一个 处理程序 允许在线程之间传递消息。处理程序还允许执行 逃货 在其附加线程上的任务立即或在稍后的时间点。

Here is how you might instantiate a 处理程序thread. on which to post tasks to be executed:

class VotingActivity {
    private Runnable processVotes = new Runnable() {
        public void run() {
        }
    };
    
    public void onCreate (Bundle savedInstanceState) {
        HandlerThread handlerThread = new HandlerThread("Voting Tasks");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());
        // Now let's execute a Runnable task ASAP on the new thread we just created:
        handler.post(new Runnable() {
            public void run() {
                // Accept a vote, say.
            }
        });
        // Let's also schedule a task to execute 10 seconds in the future on the new thread:
        handler.postDelayed(processVotes, 10000);
    }
}

在这是我们如何将HandlerThread设置为顺序处理消息:

class DownloadThread extends HandlerThread {
    public static final int START_MSG = 0;
    public static final int STOP_MSG = 1;

    DownloadThread(String name) {
        super(name);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case START_MSG:
                // Start downloading...
                break;
            case STOP_MSG:
                // Stop downloading...
                break;
            default:
                break;
        }
    }
}

然后我们可以产卵并使用此线程如下:

class MainActivity extends Activity {
    public void onCreate (Bundle savedInstanceState) {
        // Set up our DownloadThread for receiving messages.
        DownloadThread downloadThread = new DownloadThread("Image Downloader");
        downloadThread.start();
        Handler downloadHandler = new Handler(downloadThread.getLooper());
    }
    
    public void startDownloading() {
        downloadHandler.sendEmptyMessage(DownloadThread.START_MSG);
    }
    
    public void stopDownloading() {
        downloadHandler.sendEmptyMessage(DownloadThread.STOP_MSG);
    }
}

Executorservice.线PoolExecutor.

线PoolExecutor. implements the Executorservice. interface that executes submitted tasks on one of several pooled threads. Thread pooling usually improves performance when executing many tasks due to the reduced overhead of per-task invocation. If you need to execute numerous tasks asynchronously, you can spawn workers fairly easily with this mechanism. Google notes that 线PoolExecutor. is somewhat of a configurable kitchen sink, and developers are encouraged to use preconfigured versions such as newCachedThreadPool(), newFixedThreadPool()newSingleThreadExecutor().

问:加载器是什么?他们什么时候使用?

在不断追求主线程的卸载工作中,Android引入了装载机(参见 LoaderManagerLoader 课程)。装载机简化了通常馈送适配器的活动和片段中的数据的异步加载。它们监控其数据源并在内容更改时提供新的结果。因此,而不是阻止和等待数据到达(例如,从云或磁盘),使用加载器。看谷歌 装载机指南 for more details.

问:什么是rxjava,为什么这么酷?

不是每个Android开发人员都知道这个创业板,所以它在我们的书中分为我们的书中的主要果仁巧克力点。这是一个很大的创新,也许是我们帖子最令人兴奋的部分。 rxjava. 是Netflix的Microsoft的开源端口 反应延伸 图书馆。 反应规划 是一个有关数据流程和变化的编程范式。反应性编程已经存在一段时间,但rxjava没有。 RXJava非常有用,可用于编写基于同步/异步,基于事件的可观察序列。它旨在有效地查询和消耗数据(运动)。

rxjava不是一个特定于Android的库,但可以制作一个 巨大的 对Android应用程序的影响,取决于它的使用方式。它对需要低延迟的并发和/或异步应用程序有用。例如,素数用例是为了异步加载数据,而无需考虑线程,处理程序或执行者。您可能会使用rxjava来加载适配器的数据;例如,订阅UI线程上感兴趣的数据,调度要在后台线程上执行的工作,然后将结果返回到UI线程以进行显示。

rxjava允许您链接数据和事件,并在使用结果通知最终观察者之前,创建选择,过滤,转置,撰写和组合数据的序列。我们不能在这里覆盖rxjava的深度,但我们想提到它,因为精英开发人员应该了解它。您可以阅读更多关于它的信息 这里.

问:您如何从网络中缓存众多大型图像?

如果您正在开发类似Instagram或Pinterest等图像库应用程序,则缓存来自服务器的许多(大)图像变得至关重要。在寻求最佳性能中,您希望快速呈现图像,因此缓存它们以避免从网络重新加载它们是必不可少的。由于您无法缓存太多的RAM中的大型多兆字节图像(因为Android内存是易失性的并且是有限的资源),因此您真正没有替代,而是在磁盘上缓存图像(闪存)。

而不是编写自己的缓存类,而不是杠杆和包裹 disklrrucache.。这是一个不可或缺的开源解决方案,经验丰富的Android开发人员应该了解。它可用于将任何类型的数据缓存到文件系统目录,由您指定的大小限制。

超越Android正确

虽然谷歌的Android团队雇用了许多伟大的工程师,但它无法提供或预测每个可想而知的开发人员面临的新问题的解决方案。这就是第三方开源,甚至是其他谷歌团队的地方。

因此,Savvy Android开发人员将熟悉近年来出现的一些更有价值的库。这些学位可用于将新的Android功能改装给旧手机,增强现有功能或引入新功能。

然而,由于用户升级到较旧手机向旧手机扩展新的Android特征的人正在变得越来越重要 较新的Android版本和设备。但是,说,Android开发人员有一个 安卓设备的大碎片,版本和品牌 与iOS不同。

问:什么是有些有用的Android开源库,以及如何利用它们?

从谷歌和其他地方可以有许多开源库和加载项,调整的Android开发人员通常会杠杆。一些更有用的包括:

  • ActionBar.sherlock. - ActionBarsherlock是Android的延伸 支持库 旨在促进在所有版本的Android版本中使用动作栏设计模式,使用单个API。它允许您轻松开发一个应用程序栏,用于从2.x和Up的每个版本的Android。
  • disklrrucache. - 如上所述,DiskLucache是​​一个功能强大,但最简单,最近使用的(LRU)缓存实现,用于存储数据 在磁盘上,有界池大小。
  • 浓咖啡谷歌于2013年10月宣布 仍然在开发人员预览中,espresso是一个新的UI测试框架,其目标是使开发人员能够轻松地编写可靠的UI测试。最重要的是,espresso除去了需要考虑多线程测试的复杂性的需要。浓缩咖啡已经被许多Google应用程序(驱动器,地图,Google+等)使用。
  • 郭瓦 - Google的Guava Project包含几个核心库,谷歌内部积极使用:集合,缓存,基元支持,并发库,常见注释,字符串处理,I / O,以及一些非常有用的类的MishMash。看 番石榴的维基 了解更多信息。其目的是使Java“更令人愉快” 防御计划,添加优化并提高效率。它填写并改善了常见的类,如集合,数学,反射,字符串,范围,散列,I / O等。
  • Nineoldandroids. - Nineoldandroids为旧版本提供了众多新的和改进的Android HoneyComb(3.0)动画API,返回1.0并转发到最新版本的Android。蜂窝前的动画是漂亮的Darn Limited。新API可以提供更大的功率和灵活性,可以使用旋转,翻译,alpha和刻度基元进行动画对象和实际重新定位视图。该库提供了一个跨所有Android版本的包装器。
  • 协议缓冲区 - Google的协议缓冲区是一种语言 - 中性,平台 - 中性,可扩展机制,用于序列化结构化数据,为JSON或XML提供了可行的替代方案。它是传输对象数据的有效方法,例如以其原始二进制格式而不需要(UN)元帅。传输的数据“较小,更快,更简单” - 在谷歌的单词中。
  • rxjava. - 如上所述,RxJava是一个反应扩展,允许您使用可观察序列创建基于异步的事件的代码,这在许多情况下可以是非常宝贵的。
  • - 凌空是一个相对近期的谷歌库 在2013年5月在Google I / O介绍 这使Android应用程序提供了更快更容易的网络。奇怪的是,谷歌尚未公布自己的教程或文件以外的来源,使一些开发人员持怀疑态度或警惕,但有几位书面教程如 这个这个。高光包括一个自动加载图像,http请求排队的视图,以及最佳HTTP库的自动android版本的选择。

调试和调整

经验丰富的开发人员依靠伟大的工具来帮助他们构建伟大的软件,特别是用于测试和优化目的。 Android起初有点慢,提供它们,但它的工具胸部终于填写了。 Android提供运行时检测问题,附加的类可以有助于检测出现问题。还有外部工具 DDMS. 要查看内存使用情况,请查找泄漏,查看线程使用情况,观察视图层次结构等。

问:什么是禁止活动开发人员选项,为什么它有用?

谷歌提供了各种运行时 调试选项 对于可以在设置下激活的设备>开发人员选项。一个更有用的是 不要保留活动 which immediately destroys an activity when the user leaves it. It’s useful for testing activity save and restore (i.e., the onSaveInstanceState(Bundle)onCreate(android.os.Bundle) code path), which would otherwise be difficult to trigger. It can also uncover other symmetry problems with your activity’s life cycle, such as properly opening and closing resources between onResume()onPause() callbacks, for instance.

问:什么是StrictMode,为什么它有用?

在永无止境的追求中,以改善应用程序响应,并保持UI顺利运行, strictmode. 是一个有价值的Android工具,可以帮助检测主线程(或任何线程)上的意外磁盘和网络访问)。

在您的应用程序的开发版本中(切勿在发布的应用程序中启用StrickMode!),您告诉Android您对查找并定义要应用的“惩罚”的问题(即,要做什么)检测到。虽然并非每个都有必要固定的所有问题都需要修复,但您也不能确定它会发现每个问题,它为您的应用程序的不完美(如果有的话)提供了一个非常有用的窗口。

以下是您在应用程序的OnCreate方法中启用StrictMode的方式:

public void onCreate() {
    // Only enable when developing your app!
    if (DEVELOPER_MODE) {
        // Tell Android what thread issues you want to detect and what to do when found.
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            .detectDiskReads()
            .detectDiskWrites()
            .detectNetwork()    // or use .detectAll() for all detectable problems
            .penaltyLog()
            .build());
        // Tell Android what VM issues you want to detect and what to do when found.
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
            .detectLeakedSqlLiteObjects()
            .detectLeakedClosableObjects()
            .penaltyLog()       // Log the problem
            .penaltyDeath()     // Then kill the app
            .build());
    }
    super.onCreate();
}

问:什么是“棉绒”工具?它做了什么,你会如何使用它?

皮棉 是一个扫描项目的Android工具,并在您可能考虑修复的代码和资源文件中生成包含错误和警告的详细报告。它并不完美,有时它会报告误报(那个顶级开发人员知道带有一粒盐),但它仍然是一个有用的工具。例如,它可以:

  • 检测未使用的文件和资源以减少应用程序膨胀
  • Tell you where you should be recycling TypedArrays after use
  • 确定您可能是覆盖覆盖视图的背景
  • ...加上许多其他问题

您可以在编辑时启用IDE以提醒您在源文件中的这些问题,但是在命令行上运行Lint通常是一个好主意,以便定期生成完整的报告,也可以是自动构建的自动构建的Biproduct。有关更多信息,请参阅 用棉绒改善你的代码.

包起来

我们只刚刚划伤了Android应用程序的表面,突出了一些更重要的方面和平台的细微差别,以及杠杆的工具。

鉴于Android的复杂性,它可以采取移动应用程序开发者年度才能真正熟练。 Android提供了巨大的潜力,因为它的巨大的市场渗透率及其丰富的框架。找到Android Jedi Masters鉴于他们的需求以及成为一个人的需求是一项挑战。我们希望您找到本职位中提出的问题,以帮助您在寻找精英,奶油的开发人员时对该目标有所帮助。

特色Toptal Android出版物

顶级Android开发人员需求量很高。

开始招聘