Toolbox/seamlessness
From Android中文网
目录 |
[编辑] 与系统无缝结合
[编辑] 不要放弃数据
Always keep in mind that Android is a phone platform. It may seem obvious to say it, but it's important to remember that another Activity (such as the "Incoming Phone Call" app) can pop up over your own Activity at any moment. This will fire the onFreeze() and onPause() methods, and will likely result in your application being killed.
If the user was editing data in your application when the other Activity appeared, your application will likely lose that data when your application is killed. Unless, of course, you save the work in progress first. The "Android Way" is to do just that: Android applications that accept or edit input should override the onFreeze() method and save their state in some appropriate fashion. When the user revisits the application, she should be able to retrieve her data.
A classic example of a good use of this behavior is a mail application. If the user was composing an email when another Activity started up, the application should save the in-process email as a draft.
请记住Andriod是一个电话平台。很明显可以这么说,最重要的是要记住,随时都有可能另外一个活动的程序抢占的当前活动的程序(比如:“来电”程序)。这将会调用OnFreeze()和OnPause()方法,并将可能导致你的程序被关闭。
如果用户正在你的程序中编辑数据,当另外一个行为出现,你的程序可能被关闭而丢失数据。
当然,除非你在处理前就保存工作进度。“Android 的方法”是这样做的:Android程序接收或编辑输入需要重载OnFreeze(),在适当的时候并保存它们的状态。当用户再次打开应用时,能够重新恢复数据。
一个经典的例子就是邮件程序。当另一个行为启动时,如果用户正在写一封邮件,程序将要保存当前的进度到草稿箱里。
[编辑] 没人想要数据是裸露的
(No One Wants to See Your Data Naked)
If you wouldn't walk down the street in your underwear, neither should your data. While it's possible to expose certain kinds of application to the world to read, this is usually not the best idea. Exposing raw data requires other applications to understand your data format; if you change that format, you'll break any other applications that aren't similarly updated.
The "Android Way" is to create a ContentProvider to expose your data to other applications via a clean, well-thought-out, and maintainable API. Using a ContentProvider is much like inserting a Java language interface to split up and componentize two tightly-coupled pieces of code. This means you'll be able to modify the internal format of your data without changing the interface exposed by the ContentProvider, and this without affecting other applications.
如果你穿着内裤是不会走在街上的,你的数据也是如此。或许可以暴露给确定的几种类型的程序,这通常不是最佳的方法。暴露有规律的数据需要其他程序能够知道你的数据格式。如果你改变了格式,你将破坏那些没有得到同步更新的程序。
”Android 的方法“ 是通过一套简洁的、深思熟虑的、可维护的API来创建一个ContentProvider(内容提供者)来暴露你的数据给其他程序。使用ContentProvider 很像插入Java 语言接口分割和组合两段紧密耦合的代码。这意味着您将是能修改您的内部数据格式而不用改变由ContentProvider 暴露接口, 你的改变不会影响其它应用。
[编辑] 不要打断正在通话中的用户
If the user is running an application (such as the Phone application during a call) it's a pretty safe bet he did it on purpose. That's why you should avoid spawning Activities except in direct response to user input from the current Activity.
That is, don't spawn Activities from IntentReceivers or Services running in the background. Doing so will interrupt whatever application is currently running, and result in an annoyed user. Perhaps even worse, your Activity may become a "keystroke bandit" and receive some of the input the user was in the middle of providing to the previous Activity. Depending on what your application does, this could be bad news.
Instead of spawning Activities directly from the background, you should instead use the NotificationManager to set Notifications. These will appear in the status bar, and the user can then click on them at his leisure, to see what your application has to show him.
(Note that all this doesn't apply to cases where your own Activity is already in the foreground: in that case, the user expects to see your next Activity in response to input.)
不要打断正在通话中的用户
如果用户正在运行一个程序(如:通话期间的电话程序),并需要高可靠性。这是为什么忽略新的活动除了用户在当前程序的输入的直接反馈。 也就是说,不要让在后台的服务程序或接收程序产生行为。这样做会打断当前运行的程序,并会导致骚扰用户。可能更糟糕是,你的行为可能变成“键盘监视"去接收一些用户的输入。如果你的程序做了这些,这将是一个坏消息。
替换在后台直接产生活动,你需要用NotificationManager来设置通知。这些通知将出现在状态栏,等用户有空的时候可以点击他们,来查看你的程序要做的事前。
(注意:以上所说的不适合于你的活动已经运行在后台,在这样情况下,用户是想看看到输入的下个的活动的)
[编辑] 做大量的事,放到线程中去
If your application needs to perform some expensive or long-running computation, you should probably move it to a thread. This will prevent the dreaded "Application Not Responding" dialog from being displayed to the user, with the ultimate result being the fiery demise of your application.
By default, all code in an Activity as well as all its Views runs in the same thread. This is the same thread that also handles UI events. For example, when the user presses a key, a key-down event is added to the Activity's main thread's queue. The event handler system needs to dequeue and handle that event quickly; if it doesn't, the system concludes after a few seconds that the application is hung and offers to kill it for the user.
If you have long-running code, running it inline in your Activity will run it on the event handler thread, effectively blocking the event handler. This will delay input processing, and result in the ANR dialogs. To avoid this, move your computations to a thread; click here to learn how.
做大量的事,放到线程中去
如果你的程序需要执行高CPU占用或长时间的计算,你需要将它挪到线程中。这可以防止显示给用户"程序没反应"的对话框,最终的结果是,你的程序将让出系统的使用权。
默认的情况下,所有的代码是运行在同一个线程中的。处理UI就是在同一个线程中。比如,当用户按下一个按键,一个key-down事件被添加到主线程队列中。事件处理处理器必须出列,然后快速的处理事件。如果不是这样的话,在几秒中后系统推断程序正在挂起中,并提示用户去关掉它。
如果你有长时间运行的代码,并运行在事件处理线程中,将会阻塞事件处理器。这使处理被延时,并会导致"程序为反应"对话框的出现。为了避免这样,需要把它移动程序中;[点击这里学习如何使用]
[编辑] Avoid Huge Activities
Any application worth using will probably have several different screens. When partitioning your UI, be sure to make effective use of Activities.
Depending on your development background, you may interpret an Activity as similar to something like a Java Applet, in that it is the entry point for your application. However, that's not quite accurate: where an Applet subclass is the single entry point for a Java Applet, an Activity should be thought of as one of potentially several entry points to your application. The only difference between your "main" Activity and any others you might have is that the "main" one just happens to be the only one that expressed an interest in the "android.intent.action.MAIN" action in your AndroidManifest..xml file.
So, when designing your application, think of your application as a federation of Activities. This will make your code a lot more maintainable in the long run, and as a nice side effect also plays nicely with Android's application history and "backstack" model.
[编辑] Extend Themes
When it comes to the look-and-feel of the user interface, it's important to blend in nicely. Users are jarred by applications which contrast with the user interface they've come to expect. When designing your UIs, you should try and avoid rolling your own as much as possible. Instead, use a Theme. You can override or extend those parts of the theme that you need to, but at least you're starting from the same UI base as all the other applications. For all the details, click here.
[编辑] Make Being Flexible part of your Resolutions
Different Android devices will sport different resolutions. Some will even be able to change resolutions on the fly, such as by switching to landscape mode. It's important to make sure your layouts and drawables are flexible.
Fortunately, this is very easy to do. Check out Implementing a User Interface for the full details, but in brief what you must do is provide different versions of your artwork (if you use any) for the key resolutions, and then design your layout to accommodate various dimensions. (For example, avoid using hard-coded positions and instead use relative layouts.) If you do that much, the system handles the rest, and your application looks great on any device.
[编辑] Assume the Network is Slow
Android devices will come with a variety of network-connectivity options. All will have some data-access provision, though some will be faster than others. The lowest common denominator, however, is GPRS, the non-3G data service for GSM networks. Even 3G-capable devices will spend lots of time on non-3G networks, so slow networks will remain a reality for quite a long time to come.
That's why you should always code your applications to minimize network accesses and bandwidth. You can't assume the network is fast, so you should always plan for it to be slow. If your users happen to be on faster networks, then that's great — their experience will only improve. You want to avoid the inverse case though: applications that are usable some of the time, but frustratingly slow the rest based on where the user is at any given moment are likely to be unpopular.
One potential gotcha here is that it's very easy to fall into this trap if you're using the emulator, since the emulator uses your desktop computer's network connection. That's almost guaranteed to be much faster than a cell network, so you'll want to change the settings on the emulator that simulate slower network speeds. You can do this in Eclipse, in the "Emulator Settings" tab of your launch configuration or via a command line option when starting the emulator.
[编辑] Different Keystrokes for Different Folks
Android will support a variety of handset form-factors. That's a fancy way of saying that some Android devices will have full "QWERTY" keyboards, while others will have 40-key, 12-key, or even other key configurations. Similarly, some devices will have touch-screens, but many won't.
When building your applications, keep that in mind. Don't make assumptions about specific keyboard layouts -- unless, of course, you're really interested in restricting your application so that it can only be used on those devices.
[编辑] Don't Assault the Battery
A wireless device isn't very wireless if it's constantly plugged into the wall. Handheld devices are battery-powered, and the longer we can make that battery last on a charge, the happier everyone is -- especially the user. Two of the biggest consumers of battery power are the processor, and the radio; that's why it's important to write your applications to do as little work as possible, and use the network as infrequently as possible.
Minimizing the amount of processor time your application uses really comes down to writing efficient code. To minimize the power drain from using the radio, be sure to handle error conditions gracefully, and only fetch what you need. For example, don't constantly retry a network operation if one failed. If it failed once, it's likely because the user has no reception, so it's probably going to fail again if you try right away; all you'll do is waste battery power.
Users are pretty smart: if your program is power-hungry, you can count on them noticing. The only thing you can be sure of at that point is that your program won't stay installed very long.
