Android 入门到精通 (Hello,Android World)
使用搭建好的Eclipse + ADT 环境。
在Eclipse中选择 File > New > Project 菜单项。如果你已经成功安装了Android 插件,你会在弹出的新项目对话框中看到一个叫做“Android”的条目,包含一个”Android Project”的项目
选中"Android Project",点击 Next进行入下一步。弹出一个项目属性窗口,要填写如下域:
Project Name :这是计算机中保存项目文件目录的名称。
Package Name :这是和Java语言意义相同的包名(Package namespace)—你的源代码将属于这个包名。同时stub Activity也将据此生成
Activity Name : Android插件将根据这个名称来创建一个stub类。他是一个继承自Activity类的子类。Activity类似一个简单的可以运行和工作的类。它能够根据你的需要创建用户界面,当然了这不是必须的。
SDK : 从列表中选取一个SDK, 现在可以从SDK1.1 SDK1.5中选取一个。
自动生成一些代码:
Android插件执行完毕后将创建一个叫做HelloAndroid类,他的内容如下:
public class HelloAndroid extends Activity { /** Called when the activity is first created. */ /**在activity被创建后执行*/
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); }
}
可以把这些代码改成:
public class HelloAndroid extends Activity { /** Called when the activity is first created. */ /**在activity被创建后执行*/
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); TextView tv = new TextView(this); tv.setText("Hello, Android"); setContentView(tv); }
}
现在可以编译运行了。
Android提供的Eclipse插件使得运行我们的程序非常简单。选择Run > Open Run Dialog菜单;你会看到一个对话框,在这个对话框中就像配置J2ME运行环境一下,配置一个Luncher.
大功告成!点击run按钮,Androi模拟器将运行。当模拟器启动完成你将看到你的程序。到这里我们就完成了!
按照正常思路,一定会想,程序入口点在哪里呢?为什么会从这个Activity 启动呢?
现在用我们自己的最容易理解的方式来表述:
这是因为当启动这个程序的映像文件时,会发送一个事件对象Intent, 带有MAIN的行为属性,而自动生成的代码及文件, 有一个AndroidManifest.xml
会为HelloWorld这个Activity 配置一个事件过滤器,表明实现了MAIN action,LAUNCHER category的入口点行为。请注意其中的几行:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Application的生命周期
在多数情况下, 每个Android应用运行在自己的Linux进程中. 当一个应用的某段code需要运行的时候这个进程将会被创建, 直到不再需要该应用或系统要为其他的应用释放内存的时候才停止.
一个非常重要且少有的特性是, 应用进程的存活时间不是由这个应用直接控制的. 而是由系统决定的, 系统会根据每个已知的正在运行的应用情况来定夺, 包括, 该应用对用户的重要性和系统全部可用内存.
对于开发人员来讲, 了解每个应用组件(尤其是, Activity, Service, 和IntentReceiver)对于应用进程存活时间的影响是非常重要的. 如果没有正确使用, 可能会导致应用进程在处理重要工作的时候被系统杀掉.
在对应用进程生命周期的理解中, 一个典型的错误就是当一个IntentReceiver 接收到Intent 之后, 会在自己的onReceiveIntent()方法中开起一个线程, 而后return这个方法. 一旦这个方法return, 系统会认为这个IntentReceiver 不在处于活跃状态, 也就认为他的宿主进程不再需要(除非还包有其他活跃的应用组件). 以至于当系统需要回收内存的时候会随时释kill掉这个进程, 中止其中的子线程. 解决这个问题的办法是在IntentReceiver中启动一个Service, 这样系统会知道在这个进程中还有活跃的任务需要完成.
为了决定在内存较低的时候杀掉哪个进程, Android会根据运行在这些进程内的组件及他们的状态把进程划分成一个"重要程度层次". 其重要的程度按以下规则排序:
-
- 前端进程可以是一个持有运行在屏幕最前端并与用户交互的Activity的进程(onResume方法被调用时),也可以是持有一个正在运行的IntentReceiver(也就是说他正在执行自己的onReceiveIntent方法)的进程. 在系统中, 只会有少数这样的进程, 并且除非内存已经低到不够这些进程运行, 否则系统不会主动杀掉这些进程. 这时, 设备通常已经达到了需要内存整理的状态, 所以杀掉这些进程是为了不让用户界面停止响应.
-
- 可视进程是持有一个被用户可见, 但没有显示在最前端 (onPause方法被调用时) 的Activity的进程. 举例来说, 这种进程通常出现在一个前端Activity以一个对话框出现并保持前一个Activity可见时. 这种进程被系统认为是极其重要的, 并且通常不会被杀掉, 除非为了保持所有前端进程正常运行不得不杀掉这些可见进程.
-
- 服务进程是持有一个Service的进程, 该Service是由startService()方法启动的, 尽管这些进程用户不能直接看到, 但是通常他们做的工作用户是十分关注的(例如, 在后台播放mp3或是在后台下载 上传文件), 所以, 除非为了保持所有的前端进程和可视进程正常运行外, 系统是不会杀掉服务进程的.
-
- 后台进程是持有一个不再被用户可见的Activity(onStop()方法被调用时)的进程. 这些进程不会直接影响用户体验. 加入这些进程已经完整的,正确的完成了自己的生命周期(访问Activity查看更多细节), 系统会在为前三种进程释放内存时随时杀掉这些后台进程. 通常会有很多的后台进程在运行, 所以这些进程被存放在一个LRU列表中, 以保证在低内存的时候, 最近一个被用户看到的进程会被最后杀掉.
-
- 空进程是没有持有任何活动应用组件的进程. 保留这种进程的唯一理由是为了提供一种缓存机制, 缩短他的应用下次运行时的启动时间. 就其本身而言, 系统杀掉这些进程的目的是为了在这些空进程和底层的核心缓存之间平衡整个系统的资源.
当需要给一个进程分类的时候, 系统会在该进程中处于活动状态的所有组件里掉选一个重要等级最高作为分类依据. 查看Activity, Service,和IntentReceiver的文档, 了解每个组件在进程整个生命周期中的贡献. 每一个classes的文档详细描述他们在各自应用的生命周期中所起得作用.