对 Android 开发者有益的 40 条优化建议

来源:互联网 发布:网络词香菇是什么意思 编辑:程序博客网 时间:2024/06/14 18:02

转自 http://www.oschina.net/translate/40-developer-tips-for-android-optimization?cmp&p=2

英文原文:40 Developer Tips for Android Optimization

Tip 12: Use more XML Drawables.  Just to get you a bit more excited about XML drawables, the radar background below is a rather more complex example:

Radar View

No bitmaps were harmed in the making of this UI (except the icons).

Tip 13: Use yet more XML Drawables (with bitmaps if you must). How did we build the super cool icons for WeatherSignal – the lightbulb that dynamically fills up depending on light intensity and the pressure needle that rotates? Here we used bitmaps in conjunction with XML:

weathersignaldash

For the lightbulb we used two PNGs: icon_magnitude_min (an empty lightbulb) and icon_magnitude_max (one filled with light) and we dynamically cropped the latter. To set this up I used:


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:drawable="@drawable/icon_magnitude_min"
/>

<item >

<clip
android:clipOrientation="vertical"
android:drawable="@drawable/icon_magnitude_max"
android:gravity="top"
/>

</item>

</layer-list>

In the java I get I reference to the clipdrawable and control its level based on light intensity.

译者信息

建议12:用更多的XML绘图。再来介绍一个用XML绘图制作出能更加让你兴奋的例子,下面的雷达背景看起来是不是更加的复杂:

不用位图对你的UI是没有坏处的(除过图标)。

建议13:仍然用更多的XML绘图(如果必须,就用位图)。那我们怎样为天气信号构建一个超酷的图标-让灯泡动态的依据光的强度来进行自动填充,以及怎么点击指针后让其旋转呢?这里我们用位图和XML结合起来做个例子:

灯泡我们用PNG图:icon_magnitude_min(一个空的灯泡)和icon_magnitude_max(充满光的灯泡),然后我们动态的裁剪后者。为了实现这个目标我是这样做的:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:drawable="@drawable/icon_magnitude_min"/><item ><clipandroid:clipOrientation="vertical"android:drawable="@drawable/icon_magnitude_max"android:gravity="top"/></item></layer-list>
在java程序中我将得到回形针的引用,然后可以用它来控制光的强度。

Tip 14: Why use 9-patch (when you can use XML drawables)? Android have the option to use 9-patches to define drawables, a number of tutorials illustrate how to use them to make a button that can stretch while keeping the same corners (and avoiding pixellation). If you know how to use 9-patches already, perhaps from web design, then they might be worth using. If you’re unfamiliar with 9-patches I would advocate remaining that way. Creating 9 patches is more involved than creating most bitmaps and if you want to adjust anything – e.g. corner radius or the colours, it’s back to the graphics editor. Much of what 9-patches are used to achieve can be done through XML.

译者信息

建议14: 为什么要用9-patch (当你可以用XML drawables的时候)? Android具有使用9-patches 来定义drawables的选择,有些教程阐述了怎样用它们来做一个按钮,这样可以在伸展的时候保持几个角不变 (并且避免了像素处理)。如果你已经知道怎样使用9-patches,可能是从web设计中学会的,那么它们或许值得一用。如果你对9-patches并不熟悉,我建议你维持原样。如果你想适应什么东西——例如拐角的圆弧或者颜色,创建9个小块要比创建位图更多被涉及,这就像回到了图像编辑器的时代。许多用9-patches获得的效果也可以通过XML获得。

Tip 15: Create custom views by overriding onDraw(). There are some things XML just isn’t so great at, we draw a lot of graphs in OpenSignal and WeatherSignal and there are libraries for this, but we coded our graphs custom. It’s kind of fun. You might never need to do it, but to make graphics that are highly dynamic and custom it is often the only way to go.

Tip 16: Use SVG where you can’t use XML. Sometimes overriding onDraw() and painstakingly coding up all the lines and arcs you need to draw your custom view is overkill. After all, there is a language for vector graphics, it’s called … Scalable Vector Graphics. It’s what powers one of the coolest Android apps ever – Androidify. In fact they built the library just for that app, and they released it here:  SVG for Android It’s what we used to draw the dashboard in OpenSignal.

Tip 17: GZip your SVG files. Makes them smaller and they parse quicker.

Tip 18: The SVG library doesn’t support everything. In particular some alpha channels don’t seem to work, you may even have to edit them out in the code.

译者信息

建议15: 通过覆盖onDraw()创建自定义views. 有些事情XML并不十分在行,我们在OpenSignal和WeatherSignal中画过许多图像,为此有许多的库,但是我们要为自定义图像自己编写代码。这很有趣。或许你永远也不需要做这个,但为了使图像高度动态并自定义,这经常是唯一可行的办法。

建议16:在不能使用XML的地方使用SVG. 有时候覆盖onDraw()并勤勤恳恳的为自定义view编写代码画出需要的线条与弧线是过于技术化了。毕竟有一种量图像语言,它称作…Scalable Vector Graphics(可扩展矢量图形)。它也是史上最酷的Android应用之一—Androidify的动力来源。事实上他们创建这个库就是为了那款应用,他们将它发布在这里:SVG for Android  。这也就是我们在OpenSignal中画仪表盘所用到的。

建议17: 对SVG文件GZip压缩. 将它们变得更小它们就会处理的更快。 

建议18: SVG库并不是支持一切. 在一些特定的alpha通道中似乎不能正常工作,你甚至不得不在代码中将它们剔除。

Targeting consistent appearance across all Androids versions

Tip 19: On some Android OS’s (TouchWhizz/HTC Sense/MotoBlur etc) the default buttons and other UI widgets will look very different to how they look on stock Android. I wish it weren’t so, but there it is.

Tip 20: Customise your UI widgets. To make sure your app looks the same on all devices, you’ll need to customise everything, it’s not as hard as you might think and in doing so you’ll get a lot more control over how your app looks.

Tip 21: Selectors are super for building buttons. We saw above how to define a button background in XML, but what do you do to create a button that changes when clicked? Easy: define the background to be an XML file as below, which will receive the button state and serve up the appropriate drawable.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true" android:drawable="@drawable/btn_bg_selected" />
<item android:state_focused="true" android:drawable="@drawable/btn_bg" />
<item android:drawable="@drawable/btn_bg" /> <!-- default -->

</selector>

Tip 22: The ActionBar and many animation styles didn’t exist pre Honeycomb, use ActionBarSherlock and NineOldAndroids instead. Jake Wharton’s Android libraries are a tour de force of backwards compatibility. As a bonus, it ABS also gives you more power of customising the ActionBar.

译者信息

达到在android所有版本里表示展现一致的目标

建议19:在一些android系统里(如TouchWhizz/HTC Sense/MotoBlur等等),默认的buttons和其他UI组件会跟原生系统里的看起来差别很大。我希望这不是真的,但事实却是如此。

建议20:自定义你的UI组件。为了确定你的app在所有的设备里看起来是一致的,你将需要自定义所有的东西。这其实没有你想象中那么难,只要你做到了,你将能更加好地把握到你的app的展示外观。

建议21:Selectors是创建buttons的利器。我们在上面提到了如何在XML里定义button的背景,但是你将如何创建一个当按下去会改变的button呢?很简单:像下面那样在xml文件里定义背景。该xml文件将接收到button当前状态并且在外观上做出相应的改变。

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_pressed="true" android:drawable="@drawable/btn_bg_selected" /><item android:state_focused="true" android:drawable="@drawable/btn_bg" /><item android:drawable="@drawable/btn_bg" /> <!-- default --></selector>
建议22:在Honeycomb之前的版本里时不存在ActionBar跟很多 animation  样式的,所以可以使用ActionBarSherlock 跟NineOldAndroids来代替。Jake Wharton写的Android开源 组件都是往下兼容的精心杰作。更为惊喜的是,ABS 拥有强大的功能用来定义ActionBar。

Targeting speed

Tip 23: Test on slow phones. You’ll not only see any problems with slowness, but they’ll drive you nuts, no-one likes a slow app.

Tip 24: Keep your XML layout hierarchy flat. More layers means the system does a lot more work parsing your code and it can take views longer to deploy.

Tip 25: Use Android Lint. Right click on project folder in Eclipse>Android Tools>Run Lint. This can catch a host of things that can improve speed, or just make your code cleaner.

Tip 26: Android Lint can get it wrong. It can suggest things that will break your code in subtle ways, so do understand what it suggests before you make changes.

Tip 27: Using <merge> can help flatten your view hierarchy. Simple way of getting rid of superfluous layers. Great post explaining this and the difference it makes on Android Developers.

Tip 28: Use HierarchyViewer to see your layout hierarchy in its gory glory. This is a brilliant tool which shows just how many layers of layouts you have and which of them are slowing things down.

译者信息

把速度作为目标


建议23:在运行慢的手机上测试。你将在运行慢的手机上发现很多问题,同时它让你抓狂,没人会喜欢运行慢的程序。 

建议24:尽量减少XML布局层次。更多的层次意味着系统将为解析你的代码付出更多的工作,这将会让图像渲染的更慢。 

建议25:用Android Lint。在工程目录上右键选择Eclipse>Android Tools>Run Lint。它将会得到程序的一些信息,并能提高程序的运行速度,或者它能让你得代码更加清爽。 

建议26:Android Lint可以得到错误信息。它可以给你的代码提供很详细的信息,并在你出错之前就可以给做出提示。 

建议27:用<merge>可以帮助你减少视图层次结构。这是一种简单的方式来去除多余的层次。好的文章都对此有所解释,而且在 Android Developer中它也显得与众不同。 

建议28:用HierarchyViewer可以直观的看到你布局的层次。这个智能的工具可以显示布局中有多少层次,而且可以提示出那些可以让程序变慢。 

Tip 29: Use RelativeLayout whenever you can.  AbsoluteLayout is deprecated, don’t use it. Often you will have a choice between RelativeLayout and LinearLayout, go with RelativeLayout as you’ll almost always end up with fewer layers in your view hierarchy. An example, suppose you want to make a view something like:

Box A takes up left half of the screen | Box B takes up right half of the screen 

Your first instinct is probably to use:

<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”horizontal”
>

<TextView
android:text=”Box A takes up left half of the screen”
android:layout_width=”0dip”
android:layout_height=”wrap_content”
android:layout_weight=”1″
/>
<TextView
android:text=”Box B takes up left half of the screen”
android:layout_width=”0dip”
android:layout_height=”wrap_content”
android:layout_weight=”1″
/>

</LinearLayout>

That works just fine, but you could also use:

<RelativeLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”horizontal”
>

<TextView
android:text=”Box A takes up left half of the screen”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_toLeftOf=”@+id/dummy_center”
/>
<View
android:id=”@+id/dummy_center”
android:layout_width=”0dip”
android:layout_height=”0dip”
android:layout_gravity=”center”
/>
<TextView
android:text=”Box B takes up left half of the screen”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_toRightOf=”@+id/dummy_center”
/>

</RelativeLayout>

This second form doesn’t look much better than the first, in fact it looks worse: we’ve introduced a whole new element. But suppose we want to add in image into each box, schematically:

Box A takes up left half  IMAGE | Box B takes up right half  IMAGE

Pursuing the first method, you’d need to introduce a second level of LinearLayouts, pursuing the second you could put your images directly into the same RelativeLayout – for example by specifying that the first image should be to the left of “dummy_center” and TextView A should be to the left of that. So you’d have 7 elements across 3 levels of view hierarchy (LinearLayout way), versus 6 elements across 2 levels (RelativeLayout). All this stuff adds up.

译者信息

建议29:如果可以尽量用RelativeLayout。AbsoluteLayout已经过期了,就不要用了。你经常会遇到在RelativeLayout和LinearLayout中做出选择的情况,那就直接用RelativeLayouot吧,因为它可以让你减少视图层次。比如,你想实现一个如下视图:

盒子 A 在屏幕左半边 |盒子 B在屏幕右半边

你首先会想到这么做:

<LinearLayoutandroid:layout_width=”match_parent”android:layout_height=”wrap_content”android:orientation=”horizontal”><TextViewandroid:text=”Box A takes up left half of the screen”android:layout_width=”0dip”android:layout_height=”wrap_content”android:layout_weight=”1″/><TextViewandroid:text=”Box B takes up left half of the screen”android:layout_width=”0dip”android:layout_height=”wrap_content”android:layout_weight=”1″/></LinearLayout>That works just fine, but you could also use:<RelativeLayoutandroid:layout_width=”match_parent”android:layout_height=”wrap_content”android:orientation=”horizontal”><TextViewandroid:text=”Box A takes up left half of the screen”android:layout_width=”match_parent”android:layout_height=”wrap_content”android:layout_toLeftOf=”@+id/dummy_center”/><Viewandroid:id=”@+id/dummy_center”android:layout_width=”0dip”android:layout_height=”0dip”android:layout_gravity=”center”/><TextViewandroid:text=”Box B takes up left half of the screen”android:layout_width=”match_parent”android:layout_height=”wrap_content”android:layout_toRightOf=”@+id/dummy_center”/></RelativeLayout>
第二个表单比第一个难看的多,事实上是相当的糟糕:我们已经介绍过一个完整的新元素了。但是假如我们要给每个盒子里加入一个图片,一般的我们将这样做:

盒子 A 在屏幕左半边 图片|盒子 B在屏幕右半边 图片

用第一中方法,你得创建一个有两个层次的LinearLayout,如果用第二种方法,你可以直接在同一个RelativeLayout中加入图片,比如要指定第一个图片必须在“dummy_center”的左边,而且一个TextView A必须也在其左侧。那么你就得用7个元素3个视图层次了(LinearLayout 方式),而(RelativeLayout方式)只用6个元素2个层次,这样所有的工作添加完成。

Tip 30: Use external profilers as well as DDMS. These help you see unnecessary network calls, watch power usage, garbage collection, state changes (e.g. when onStop and onDestroy are called). LittleEye is my current favourite.

Tip 31: Use AsyncTasks. The Android team must have got so fed up with people making network calls on the UI thread that they turned it into a compile error a few API levels back. But there’s probably a lot of other work in any app that can be take off the UI thread, allowing layouts to render faster and improving its responsiveness.

译者信息

建议30:用一些扩展工具如DDMS。这可以帮助你发现一些不必要的网络调用、查看电池使用量、垃圾回收信息,状态变化(例子:当回调onStop和onDestroy时)等。LittleEye是我目前比较喜欢的工具。 

建议31:用AsyncTasks。Anroid工程团队受够了人们经常在UI线程里面实现网络调用(译注:耗时操作,容易阻塞UI刷新),所以他们实现了一些可产生编译级错误信息的API。但是仍然在很多app中的一些工作会拖垮UI线程,我们要考虑到UI布局要快以及提高UI的响应性。

Targeting low file size

Tip 32: Some Android devices have a 100mb limit. Things are changing, but there’s still a lot of users out there who will have to think a lot about whether a 5Mb app deserves its space. If you allow users to install to the SD card, it’s not a problem but you shouldn’t allow this if your app needs to start onBoot (e.g. for most widgets). Even for newer devices, users are going to be happier if your APK is small so it downloads quicker.

Tip 33: Use XML resources (last time I recommend this, I promise) These save a tonne of space over PNGs, as you only need one for many screen configurations and a single XML file is almost always smaller than a PNG showing the same thing.

Tip 34: When you must use PNGs always optimize (with PNGCrush or ImageOptim)

译者信息

目标机器空间小

建议32:一些Aandroid设备有100mb空间大小的限制。现在情况已有变化了,但是仍然有很多用户还会担心5Mb大小的app会浪费空间。如果你可以选择将app装入SD卡的话,这就不是问题了,但如果你的app需要在onBoot里启动的话你就不能装入SD卡了(例子:如一些窗体小部件).甚至对于一些新的设备,如果能很快的下载一个小的APK的话,用户还是很高兴的。 

建议33:用XML资源(我发誓上次我已经提醒过了),这将比PNG资源节省很多空间,当你仅仅需要一个可以满足很多屏幕大小的配置时,一个XML文件会比能实现同样功能的PNG省空间。

建议34:如果要用PNG,最好优化一下(用PNGCrush或ImageOptim) 

Targeting bugs

Tip 35: On the Android developer console check for any bugs that have been sent automatically.

Tip 36: ProGuard is turned on by default now. Proguard is awesome (speeds up your app and reduces filesize) but it can make StackTraces very obscure. You’ll need to retrace the StackTraces, to do this you’ll need to hang onto the Proguard mapping files created on each build, I put them into a folder with the version code’s name.

Tip 37: Adjust ProGuard config to show line numbers in StackTraces. Make sure your proguard.cfg has a line:
-keepattributes SourceFile,LineNumberTable

Tip 38: Use staged rollouts Test the waters on 5% of devices, watch for bug reports.

Tip 39: Use a device testing lab Device Anywhere and Perfecto Mobile offer virtual testing labs where you can log onto a real device. I find them sort of clunky and often the devices are kind of messed up by being so unceasingly tested on. If you work out of a co-working centre, or have several Android developer friends get a “device pool” going.

Tip 40: More code less blog posts.  Nah, sharing is caring, I just can’t think of a 40th.

This entry was posted in Android Development and tagged actionbar, app, build for Android, help, how to, optimize, tips,UI, XML. Bookmark the permalink.
译者信息

目标bugs

建议35:在Android开发者控制台里检查所有被自动检测出来的bugs. 

建议36: ProGuard现在是默认启动着的. Proguard太好用了 (提高你app的速度和降低文件大小),但这也让StackTraces 非常难以处理。你将需要重新追踪你的StackTraces,因此你将需要继续保留在每次构建中创建的Proguard的映射文件。我把它们都放到以代码版本号命名的文件夹里。 

建议37: 为了显示StackTraces里的行数,你需要修改ProGuard的配置。确认你的proguard.cfg拥有下面这句话: 
-keepattributes SourceFile,LineNumberTable 

建议38:使用staged rollouts。测试5%的基础用户,并且观察bug报告。 

建议39:使用真实设备测试平台。Device Anywhere and Perfecto Mobile提供了虚拟测试平台,在那里,你可以使用真正的移动设备。我发现他们有一些笨拙,加入连续不断地进行测试的话,会导致有一些糟糕的情况。如果你在联合办公的环境里工作,或者有一些Android开发的好友,那么去启动一个“设备池”吧。 

建议40: 多写代码少写博客。其实不是的, 分享就是关爱, 我只是想不出第40条写什么是了。 

0 0
原创粉丝点击