一、
Android is a software stack for mobile devices that includes an operating system, middleware and key applications. The Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
从android的定义看,它可不仅仅是个OS,更确切的说是software stack。以前理解的肤浅
android的开发常用tools:
1.The Android Emulator
2.DalvikDebug Monitoring Service (DDMS)
3.Android Debug Bridge (ADB)
Manage the state of an emulator instance or Android-powered device
Copy files, install compiled application packages, and run shell commands.
4.Traceview
Graphical analysis tool for viewing the trace logs from your Android application
Debug your application and profile its performance
5.MkSDCard
Creates an SDCarddisk image
据说可以在一台机器上开两个emulator,让它们相互通信。有空研究一下。哪位童鞋有知道的,希望能交流一下。O(∩_∩)O~
构成应用程序的四大组件,当然不一定全会用到
four types of components:
1.Activities:相信大家都理解它什么意思了。记住一个词 foreground就够了
2.Services:与activity对应的,它的关键词就是background。最经典的例子就是音乐的回放
3.BroadcastReceiver :receive and react to broadcast announcements。常用来接收和响应一些突发事件,比如用户时区改变了,手机突然没电了,用户很臭美,拍了一张照片(对程序来说这就是突发事件),用户还可能闲着无聊,胡乱的改变设置等等,这都要交给BroadcastReceiver
4.ContentProvider:内容提供商。就向互联网中的ICP似的。一个想要,另一个就要给(只要具备这种能力)。想要的这一方就叫做resolver,给出的一方就叫做provider。典型的privider有文件系统和数据库
三、
那这四个组件式怎么工作的呢,继续往下看
Content providers are activated when they're targeted by a request from a ContentResolver.
other three components — activities, services, and broadcast receivers — are activated by asynchronous messages called intents.
Content providers由ContentResolver的一个request激活
其他三种需要intent来激活,不得不说,intent真是了不起
下面看看intent是具体怎么做到的
An intent is an Intent
object that holds the content of the message
intent有两件法宝:action和data
For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text.
For broadcast receivers,
the Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.
可以看出,intent要携带action的名字,和data的URI。对URI代表的资源执行action的操作
后面还会看到action体现在manifest.xml的intent-filter中
以activity为例:
Activity A启动Activity B后,不需要接收B的反馈那就调用
方法。Context.startActivity()
如果希望接收B的反馈,就要调用
方法。B使用getIntent()捕获intentActivity.startActivityForResult()
这里讲到一个 onNewIntent()。SDK中介绍了3种使用场景:
1.用于设置activity的加载模式为singleTop
2.用户使用startActivity()加载activity时使用了flag——
FLAG_ACTIVITY_SINGLE_TOP
3.一个application加载多个activitity时,这些activity就会被存放到栈中——activity stack。激活一个在栈顶的、已存在的activity(不是创建一个新的activity实例)的时候,就需要调用该方法获取激活需要的intent。在这里就是使用该方法返回intent给A。
A收到后使用onActivityResult()方法处理
SDK中有这样的语句:Android calls ...这可以理解为DVM主动调用,而不用写入程序吗?
为便于区别后面都会保留这两个单词
一个activity在接收intent之前先调用onResume()使自己处于暂停状态,这可以在onResume()使用计数器看出来。
services
传递Intent对象给startService()启动一个service。Android calls 这个service的
方法来传递Intent对象给这个service。onStart()
这样是启动一个service并传intent给它。怎样传一个intent给一个正在运行的service呢?
这就需要 Context.bindService() 方法了。component调用这个方法并传递intent给这个方法,将component与接收intent的service连接起来。然后这个service调用onBind()方法,把intent接收过来
例如,一个activity与音乐回放的service就是这样连接的。
The activity would call
bindService()
to set up that connection, and then call methods defined by the service to affect the playback.
RPC(remote procedure calls)has more details about binding to a service.
BroadcastReceiver
An application can initiate a broadcast by passing an Intent object to methods like
, Context.sendBroadcast()
, and Context.sendOrderedBroadcast()
in any of their variations. Android delivers the intent to all interested broadcast receivers by calling their Context.sendStickyBroadcast()
methods.onReceive()
打算在下一篇中再好好学习,在这里做个引子
ContentResolver发出一个request激活ContentProvider。
broadcast message会激活broadcast receiver。
它们的激活与存在是有条件的,是不需要手动关闭的
activities和services如果不手动关闭可能就会长时间的存在
虽然系统会根据需要(如内存不足等)也会关闭component——这就是components Lifecycles,但我们意识到不再需要是最好还是手动关闭
finish()
method. One activity can shut down another activity (one it started with startActivityForResult()
) by calling finishActivity()
. stopSelf()
method, or by calling Context.stopService()
.
DECLARATION OF APP——MANIFEST.XML
声明你的应用和组件。其实我感觉这个文件决定了程序的逻辑,把程序的各个组成部分连接起来,指挥程序怎么运行的吧
重要性不言而喻了
声明activity:<activity></activity>
声明service:<service></service>
声明broadcast receivers:<receiver></receiver>
声明content provider:<provider></provider>
Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver
objects) and registered with the system by calling
. Context.registerReceiver()
SDK中有这么一句话:intent-filter用来告诉一个component的intent应该怎么handle这个component。
我的理解是:Intent对象可以明显的指定与哪个component连接,并执行相应的动作。
如果不指定,就要与intent filter比对来匹配(filter本身就是过滤、匹配的意思)。过程是这样的:Intent对象会读取intent-filter中的内容获取操作(action),将这个操作作用于intent-filter所在的这个component,这个component也就表现出相应的action
intent-filter也是要声明在manifest.xml中的
<?xml version="1.0" encoding="utf-8"?> <manifest . . . > <application . . . > <activity android:name="com.example.project.FreneticActivity" android:icon="@drawable/small_pic.png" android:label="@string/freneticLabel" . . . > <intent-filter . . . > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter . . . > <action android:name="com.example.project.BOUNCE" /> <data android:mimeType="image/jpeg" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> . . . </application> </manifest>
第一个intent-filter是一个常见的用法。指定当前的component(这里是一个activity)是application的入口,即application一启动就要显示这个activity
The second filter declares an action that the activity can perform on a particular type of data.
第二个filter声明这个activity的动作:特定的数据类型(图像数据的jpeg类型)
A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.
For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an IntentFilter
object. All other filters are set up in the manifest.
只有broadcast receiver 的filter可以选择在代码中创建和注册。使用IntentFilter对象实例化一个filter。其他components的filter都要写在manifest.xml中
相互协作的activity。它们可以属于一个application,也可以来自不同的application。后一种情况就可以使用已经存在的application来达到目的。这些activity会放在同一个task里,这样用户看起来就是一个application,用户就会有好的体验。这样一个task还可以看做stack,称作activities stack。在栈的底部是用户启动application时运行的root activity,在栈的顶部是当前正在运行的activity。新启动的activity会入栈,并开始运行,先前的activity还在栈中。当用户按下“后退”按钮时,栈顶的activity就会被弹出,新的位于栈顶的activity就会处于运行状态。
一个task就是一个activities stack。task可以整体退到background,也可以整体回到foreground。例如task A正在运行,用户按下“home”键回到application laucher(应用程序启动界面,显示所有的应用程序),启动另一个application(确切的说是一个task,称作task B),那么先前的task A就退到background,foreground显示的是新启动的task B。如果此时用户又回到laucher启动task A,task A 就会回到foreground,task B退到background。如果此时按下“后退”按钮,执行的是task A的出栈操作,屏幕显示的是task A位于栈顶的activity,而不是task B。
当然上面的过程是task的默认行为,是可以改动的。一个task中的activities、不同task中的activities,它们的关系可以通过标志和属性(flags and attributes)来决定。标志在启动activity的Intent对象中设置,属性在manifest的<activity>
单元中。
最重要的Intent标志有:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP
最重要的 <activity>
属性有:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
affinity 用于描述activity之间的关系
一个application中的activity之间会有默认的affinity标识它们属于同一个task,也可以在 <activity>
单元中使用taskAffinity 属性单独的设置。
Activities defined in different applications can share an affinity, or activities defined in the same application can be assigned different affinities.
affinity在两种情况下会起作用:
1.Intent对象启动一个activity时使用了FLAG_ACTIVITY_NEW_TASK 标志
默认情况下,一个activity调用startActicity()启动另一个activity时,两个activity会放在一个task中。但是,如果传给startActicity()的Intent对象带有FLAG_ACTIVITY_NEW_TASK 标志,新的activity就会被放到不同的task中。如果已存在一个task与新的activity具有相同的affinity, the activity is launched into that task。如果没有,就会新建一个task。大多数情况都要新建的,这也是这个标志的含义
2.activity的 allowTaskReparenting
属性被设为true
一个activity属于一个application并允许reparenting时:
It has the same affinity as other activities in the same application (the default affinity) and it allows reparenting。
有一个activity启动了这个activity,它就与前者在一个task中。当拥有它的application启动时,它就会回到这个application的task中。
一个activity lauch到一个task的模式:
There are four different launch modes that can be assigned to an <activity>
element's launchMode
attribute:
"standard
" (the default mode)
"singleTop
"
"singleTask
"
"singleInstance
"
模式之间的区别体现在以下四点:
1.新的activity实例登录到哪个task中去:是创建这个实例的activity相同的task,还是别的task?
2.这个activity是否允许有多个实例
3.这个activity实例是否愿意与别的activity共享一个task
4.这个activity实例是否接收一个新的intent
When an existing activity is asked to handle a new intent, the Intent object is passed to the activity in an
call. (之前的intent可以通过调用 onNewIntent()
.) getIntent()方法找回
Note that when a new instance of an Activity is created to handle a new intent, the user can always press the BACK key to return to the previous state (to the previous activity). But when an existing instance of an Activity handles a new intent, the user cannot press the BACK key to return to what that instance was doing before the new intent arrived.
默认情况,一段时间后会清除stack中除root activity之外的activity。当用户重回到这个task时需要重建其他的activity
可以使用activity的属性来改变上述默认的情况
alwaysRetainTaskState
attribute
clearTaskOnLaunch
attribute
finishOnTaskLaunch
attribute
There's another way to force activities to be removed from the stack:
当一个task中的activity可以接收带有 FLAG_ACTIVITY_CLEAR_TOP的Intent对象时,这个activity上面的activity就会被清理掉,让这个activity处于栈顶运行态,以便响应这个Intent对象。如果这个activity的lauch mode 是“standard”,它也会被清除掉,会有一个新的实例进入task接收即将到来的Intent对象。这是因为lauch mode为“standard”的activity会创建新的实例来响应新的intent
FLAG_ACTIVITY_CLEAR_TOP
经常和FLAG_ACTIVITY_NEW_TASK一起使用
一起使用提供了一种方式,可以定位一个在别的task中的activity,并把这个activity调整到合适的位置以便响应这个intent
要想设置一个activity为一个task的入口,就在它的intent-filter中作如下设置:
1.指定它的action为"android.intent.action.MAIN
"
2.指定它的category为 "android.intent.category.LAUNCHER
"
这样在application laucher中就会为这个activity生成一个图标和标签(icon和label)。
用户离开一个task后能够成功的返回是非常重要的。为了这个要求,作为初始化task的两个加载模式:"singleTask
" 和"singleInstance
"只能用于标记拥有 MAIN
和 LAUNCHER
filter的activity(也就是root activity),保证了task的唯一性。如果标记了其他的activity,用户在上面做了一些操作,然后按下“HOME”键回到application laucher,因为没有上述filter的activity在application laucher是看不见的,用户就无法返回了
标志 FLAG_ACTIVITY_NEW_TASK
tips:
1.If this flag causes an activity to begin a new task and the user presses the HOME key to leave it, there must be some way for the user to navigate back to it again.
2.If you have an activity that can be invoked by an external entity that might use this flag, take care that the user has a independent way to get back to the task that's started.
如果不想让用户返回某个activity,就在<activity>中设置finishOnTaskLaunch 为true。或者参考Clearing the stack一节
--------------------------------未完待续-----------------------------------