Android应用开发基础简介

时间:2022-10-11 03:24:21


Android中,每一个应用都在自己的Linux线程里面跑,与其他应用都是隔绝隔绝的(有自己的VM),每一个应用都给予了一个唯一的Linux ID. 但是两个应用也可以有一样的Linux ID,分享 VM,数据和资源(res).


Android应用没有一个像Java的main函数一样的唯一的entry point,Android应用在需要的时候初始化和运行必要的组件。一个Android应用有四种组件:

  • Activity:Activity 提供用户看到的窗口,窗口的内容是由View提供的,每一个View负责窗口内一个rectangle的区域。父View控制和组织它的子View. 最底层的View负责与用户事件在那个区域的反应。因此View是直接与用户进行交互的组件。

          我们使用setContentView()方法将一个View对象放到Activity窗口中。ContentView是一个View的子类,处在View类结构的根部。

  • Service: 没有UI, 在背景中运行。可以运行无限长的时间。每一个service对象都继承Service父类。
  1. Service可以通过在Activity中调用Context.startService(Intent i)启动。Android调用并把这个intent i参数传给Service的onService(Intent i)方法(IoC控制反转)。
  2. 如果Service还没有开始的话,也可以使用Context.bindService(Intent i)方法在调用这个方法的组件和目标service之间建立通讯连接。Android把intent i传给Service的onBind(Intent i )这个方法。
  • Broadcast receivers: 除了接受和对broadcast的声明反应外,什么都不做!一个应用程序可以有多个继承自同一个broadcast 基类的broadcast receivers来应对不同的系统announcements. broascast receiver没有UI.
  • Content Receiver:让程序的一组数据可以被其他应用程序使用。数据可以是保存在文件,SQLite数据库,等中。应用使用contentResovler通过调用ContentReceiver中定义的方法来获得数据。

Intents

ContentProviders是被从ContentResolver发来的request激发的。其他三个组件都是被Intent激发的。Intent包含了一些必要的信息,例如:intent包含所要求的action的名字等。

  • 通过把一个intent对象传给Context.startActivity(Intent i)或Context.startActivityForResult(Intent i)方法来启动Activity.Activity可以使用getIntetn()方法来看启动它的Intent的信息。一个Activity如果想启动另一个Activity, 让用户做些什么并想获得结果的话,通过调用Context.startActivityForResult(Intent i),结果就会被包含在之前传给Context.startActivityForResult(Intent i)的intent对象中返回回来。
  • 通过调用Context.startService(Intent i), 把intent对象传给这个方法来启动Service。 如果方法还没有启动的话,也可以通过调用Context.bindService(Intent i)启动Service。这个方法在调用组件和目标Service间建立了一个连接。 Android把这个Intent传给service的onBind(Intent)方法。 Activity通过Service中定义的方法来控制Service.
  • 应用通过把|Intent对象赋给Context.sendBroadcast(), Context.sendOrderedBroadCast(),或Context.sendStickyBroadcast() 方法来启动一个broadcast. Android把Intetnt发送给所有感兴趣的Broadcast receivers(通过调用他们的onReceive()方法)

Shutdown components

因为ContenyProvider只有当对一个ContentRolver的要求做反应时才会启动。 broadcast receiver只有在要对broadcast msg做反应的时候才会启动。所以他们俩都不需要考虑关闭


Activity, 提供UI,运行较长时间,或能在不使用的时候也保持运行。

  • Activity通过finish()方法关闭自己
  • Actibvity通过finishActivity()方法把之前通过startActivityForResult()方法调用的另一个Activity关闭

Service 可以通过调用它的stopItself() 或 Context.stopServie()方法关闭


The Manifest.xml file

它的作用是

  • 声明组件
  • 确定应用运行所需要的被赋予的权限
  • 首要任务是告知Android它里面声明的组件。

Intentfilter

如果Intent明确的知道要调用的activity或组件的名称的话,那么intent对象可以在java code中动态地调用。

如果不知道的话,Android必须要找到最适合应对intent的组件。 Android通过比较intent和Manifext.xml中的Intent-filter来确定要调用哪一个组件。组件的intent-filter告诉android它能处理哪种Intent.


Activity--action:android.intent.action.MAIN

            |-category:android.int.category:LAUNCHER


有这个intent-filter的activity是应用程序的entry-point. ACTIVITY作为程序的进入点会在在applicaiton launcher中显示应用程序的icon和label。


组件可以有好多个intent-filter,每一个声明这个组件拥有的不同的处理intent的能力。如果一个组件没有intent-filter,它只能被显性的调用(直接的)。

Activities and Tasks

 

描述A: 一个应用程序中的所有的activity,是以一个整体保存在一个stack上的。应用程序从前带到后台的转换都是把包含所有activities等组件的stack作为一个整体来使用的。例如,假设有一个有四个activities的应用A,当用户启动另一个新应用B时,应用A被整体放入后台运行。用户点击BACK键,应用A又整体被带回前台运行。


以上的描述A是默认情况下应用和activities之间的关系。应用中的activities的关系和行为是由创建一个ACTIVITY对象的那个intent对象的FLAG的值和在manifest.xml文件中<ACTIVITY>的attributes set元素共同控制的。

 

Activity可以启动另一个应用中的activity.


stack根部的activity是启动应用程序的组件。最上面的那个是当前正在运行的activity.一个新运行的activity被放在当前的activity之上并被当做当前的activity. 用户点击BACK按钮可以回到之前的activity.

affinity and new tasks

一个应用中所有的activities之间有affinity来让他们属于一个应用。可以在<ACTIVITY>中用<taskaffinity>单独设置一个affinity的值. 不同的应用中的activity可以有一样的affinity. 一个应用中也可以有不同affinity的activity。

当intent对象有FLAG_ACTIVITY_NEW_ACTIVITY和activity自己launch activity的allowTaskReparenting = true时,

  • The FLAG_ACTIVITY_NEW_TASK
    flag 默认情况下,新启动的ACTIVITY是属于启动它的那个task的stack的。 如果intent对象的包含FLAG_ACTIVITY_NEW_TASK, 新activity会是一个新的应用的root,但是也不是必然,如果现有的一个应用的affinity与新的activity相同,就把这个activity放到这个应用上。
  • The allowTaskReparenting
    attribute: If an activity has its allowTaskReparenting attribute set to "true", it can move from the task it starts in to the task it has an affinity for when that task comes to the fore.

If an .apk file contains more than one "application"from the user's point of view, you will probably want to assign different affinities to the activities associated with each of them.

Launch modes

<activity> 组件的launchMode变量可以有四个值:

  • standard(default)  A:
  • singleTop              B:
  • SingleTask           C   
  • singleInstance      D

根据以下四点的不同可以区分ABCD的不同。


能否把响应Intent的Activity放到应用的stack上?


C和D mode 的activity是stack的根activity,所以一定会被放到应用的stack上。一般来说如果A 和 B mode 的activity响应的Intent对象的FLAG不是FLAG_ACTIVITY_NEW_TASK, 就会被放在发出intent对象的应用的stack上;否则就放到其他的应用的stack上。C和D用来定义一个应用,因此从来不会被创建到其他新的应用的stack之上的。


ACTIVITY是否可以有多个实例?


基本上来说,A和B的activity可以被多次实例化,可以属于不同的应用,可以在一个应用中有多个实例对象。然而,C和D则必须出现在STACK的根ROOT, 仅仅能有一个实例,即在任何时间,任何device上,在所有应用程序上,总共不能有多于1个C或D的activity实例。


应用的STACK上的ACTIVITY是否还可以有其他的ACTIVITY?


D  --表示应用stack中唯一仅有的一个activity,如果它创建一个activity实例,新创建的activity实例必须被放到其他应用的stack上,就好像调用的intent对象的FLAG是FLAG_ACTIVITY_NEW_TASK一样。除此之外,D与C没有区别。C模式的ACTIVITY永远是应用stack的根activity, 可以创建其他的Activity. 是应用中这个ACTIVITY类型的唯一实例。


除了D模式以外,其他三种都准许其他ACTIVITY被创建到它们应用的stack上。A和B可以在应用的stack的任何地方出现。


一个ACTIVITY类型的实例会不会被新创建来处理对应的Intent?


A模式的activity可以有很多实例,c模式的activity创建一个新的实例来响应它能处理的所有的intent.

B模式的activity 如果是在STACK的顶部的话,即是当前使用的ACTIVITY,那么这个ACTIVITY的实例就会被再次使用来处理Intent, 如果不在顶部的话,就创建个新的实例来处理。

C和D是整个STACK中唯一的它们STACK类的实例,所以它们不会创建新的实例来处理到达它们那里的intent。 因为D是STACK上仅有的一个ACTIVITY,所以它会一直在处理指向它而来的INTENT. 然而,C模式的ACTIVITY也许有其他的ACTIVITY实例在它上面。如果有的话,以它为目标的Intent无法被处理,将会被drop。


一个现有的ACTIVITY如果被要求来处理新的INTENT的话,新的INTENT对象会在onNewActity()方法中传给这个ACTIVITY。启动这个ACTIVITY的原来的INTENT可以通过getIntent()方法获得。


在应用的STACK结构中,如果一个新的ACTIVITY的实例被创建来处理到达的INTENT, 像我们已经知道的,这个activity会被放到应用的STACK上,用户还可以回到前一个activity. 但是,如果一个现有的activity被用来处理一个新到达的intent的话,用户无法会到这个现有的activity在新的intent之前处理的那个intent。


注:

清除STACK

默认情况下,如果一个用户离开应用的时间太长,Android会把应用的STACK除了root activity之上所有的activity清除掉。当用户回来的时候, 就只会展现root activity。 还有一些其他的变量来控制和改变这一行为。

The alwaysRetainTaskState
attribute: 应用会保存所有的activities很长一段时间。


The clearTaskOnLaunch
attribute:如果用户离开,从上到下包括root activity全部没抹清。
The finishOnTaskLaunch
attribute: 作用在单一的activity上,而不是全部的应用。让任何一个activity包括root, 在和用户交互的时候一切正常,用户离开就会被删除。

There's another way to force activities to be removed from the stack. If an Intent object includes the FLAG_ACTIVITY_CLEAR_TOP
flag,而且目标应用的stack中有一个能处理这个intent的activity的实例,那么所有在这个实例之上的activities都会被清除好让这个实例在top来处理这个intent.
If the launch mode of the designated activity is "standard", it too will be removed from the stack, and a new instance will be launched to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard".

 

 

FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunctionwith FLAG_ACTIVITY_NEW_TASK. When used together, 可以把一个activity放到另一个应用的stack之上,这样它就能够处理intent.


Starting tasks

只有当ACTIVITY的intent-filter是main和launcher时,在<ACTIVITY>中使用SINGLETASK和SINGLEINSTANCE 启动模式。


Processes and Threads

当应用程序的第一个组件要运行的时候,Android启动了一个Linux process(single thread),默认情况下,这个应用的所有组件都在这个进程内运行。也可以把组件放到其他的线程中运行,为进程提供多余的线程。组件一般情况下只是进程的主线程中运行,当然,对于不能够迅速完成的任务要放在其他的线程中。

 

Processes

一个组件在哪一个进程里面运行是在manifest.xml文件中设置的。组件 <activity>,<service>,<receiver>, and <provider> 每一个组件都有一个process变量来指定它在哪一个进程里面运行。<application>组件也有一个process变量,为application内所有的组件指定一个process. 不同的应用中的组件可以在一个进程中运行,如果应用们共用一个linux user ID并被signed by the same authorities.

 

所有的组件都是在进程的主线程中被初始化的,系统对组件的命令也是从主线程中发出的。系统并不为每一个实例都创建不同的线程,结果就导致响应这些命令的函数都是在主线程中运行,例如:View.onKeyDown(). 这就表示主线程中不应该有执行长时间或block operations(such as networking operations or computation loops),, 因为这样会影响进程中的其他组件。最好是在其他线程中运行。

 

线程

虽然应用时在单进程中运行的,但是也有需要生成一个线程来做其他工作。因为用户的界面必须能快速的响应用户。运行一个activity的线程同时不应该也在运行一个下载工作。任何不能快速结束的任务都应该被分配给一个不同的线程。

 

线程由标准的java thread创建, Android还有Looper类来在线程中running a message loop, Handler class for processing messages, and HandlerThread class for setting up a thread with a message loop.

Component Lifecycles

Activity Lifecycle

Android应用开发基础简介

activity有三个必要的状态:

activity/running: 在前台运行中,stack最上面。

paused: 用户仍能看到这个窗口,仍保存所有的状态和成员信息并且仍attach在window manager上。可能是有个对话框弹出,这个activity的窗口一部分仍然是可见的,但是lost focus.

stopped: 已经不可见,仍保存所有的状态和成员信息。


在paused或stopped状态中的activity可以被android系统用finish()方法清除出内存或者kill the process. Android系统通过调用以下的protected方法来把activity从一个状态转到另一个状态。


void onCreate(Bundle savedInstanceState
)
  用来初始化global state
void onStart()

void onRestart()

void onResume()  it is called when an activity result or a new intent is delivered
void onPause()  持久化数据或准备onStop()。 it is called when the device goes to sleep or a new activity is called .

无论在这个方法中做什么,都要快,因为如果这个方法不完成,新的actvity就无法显示。
void onStop()

void onDestroy()  用来注销所有的未注销资源。

Method Description Killable? Next
onCreate()
Called when the activity is first created. This is where you should do all of your normal static set up — create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's previous state, if that state was captured (see Saving Activity State, later).

Always followed by onStart().

No onStart()
     onRestart()
Called after the activity has been stopped, just prior to it being started again.

Always followed by onStart()

No onStart()
onStart()
Called just before the activity becomes visible to the user.

Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.

No onResume()
or
onStop()
     onResume()
Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it.

Always followed by onPause().

No onPause()
onPause()
Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns.

Followed either by onResume() if the activity returns back to the front, or by onStop() if it becomes invisible to the user.

Yes onResume()
or
onStop()
onStop()
Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it.

Followed either by onRestart() if the activity is coming back to interact with the user, or by onDestroy() if this activity is going away.

Yes onRestart()
or
onDestroy()
onDestroy()
Called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called finish()
on it), or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing()
method.
Yes nothing


可以被KILLABLE表示系统是否可以包运行这个activity的进程killt any time after the method returns, without executing anotherline of the activity's code. Three methods (onPause(),onStop(), and onDestroy()) are marked "Yes." BecauseonPause() is the first of the three, it's the only one that'sguaranteed to be called before the process is killed — onStop() and onDestroy() may not be. Therefore, you should use onPause() to write any persistent data (such as user edits) to storage.


一个activity的visible lifetime是从onStart() -> onStop(). 这个过程可以被调用多次。

一个activity的foreground lifetime是从onRusme() -》onPause(). 这个过程中, 在屏幕上,activity 是在其他的activities之上并且和用户在交互。一个activity经常地从onRusme() 《-》onPause()之间转换。

Saving activity state

When the system, rather than the user, shuts down an activity to conserve memory, the user may expect to return to the activity and find it in its previous state.


To capture that state before the activity is killed, you can implementan onSaveInstanceState()
method for the activity. Android calls this method before making the activity vulnerable to being destroyed —that is, before onPause() is called. Itpasses the method a Bundle
object where you can record the dynamic state of the activity as name-value pairs. When the activity is again started, the Bundle is passed both to onCreate() and to amethod that's called after onStart(), onRestoreInstanceState()
, so that either or both of them can recreate the captured state.


onSaveInstanceState() and onRestoreInstanceState() arenot lifecycle methods. They are not always called. 因为如果是用户点击BACK键回到前一个activity的话,就没有必要保存状态。Because onSaveInstanceState() is not always called, you should use it only to record the transient state of the activity, not to store persistent data. Use onPause() for that purpose instead.


Coordinating activities

  1. The current activity's onPause() method is called.
  2. Next, the starting activity's onCreate(), onStart(),and onResume() methods are called in sequence.
  3. Then, if the starting activity is no longer visibleon screen, its onStop() method is called


Service lifecycle

A service can be used in two ways:

  1. 被开始后运行到有人停止它或它自己停止自己。In this mode, it's started by calling Context.startService()
    and stopped by calling Context.stopService()
    .It can stop itself by calling Service.stopSelf()
    orService.stopSelfResult()
    . Only one stopService() call is needed to stop the service, no matter how many times startService() was called.
  2. 根据它提供的接口,客户可以建立到service的连接并用这个连接控制service. The connection is established by calling Context.bindService()
    ,and is closed by callingContext.unbindService()
    .Multiple clients can bind to the same service.If the service has not already been launched, bindService() can optionallylaunch it.

The two modes are not entirely separate. You can bind to a service that was started with startService()。 For example, a background musicservice could be started by calling startService() with an Intentobject that identifies the music to play. Only later, possibly when the user wants to exercise some control over the player or get information about the current song, would an activityestablish a connection to the service by calling bindService(). In cases like this, stopService() will not actually stop the service until the last binding is closed.


Service有三个public, not protected lifecycle方法来监视状态的变化。

void onCreate()
void onStart(Intent intent
)

void onDestroy()


By implementing these methods, you can monitor two nested loops of theservice's lifecycle:

  • The entire lifetime of a service happens between the timeonCreate()
    is called andthe time onDestroy()
    returns. Like an activity, a service does its initial setup in onCreate(), and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), and then stop the thread in onDestroy().
  • The active lifetime of a service begins with a call to onStart()
    . This method is handed the Intent object that was passed to startService().The music service would open the Intent to discover which music to play, and begin the playback.

The onCreate() and onDestroy() methods are called for allservices, whether they're started by Context.startService()
or Context.bindService()
.However, onStart() is called only for services started by startService().



If a service permits others tobind to it, there are additional callback methods for it to implement:

IBinder onBind(Intent intent
)

boolean onUnbind(Intent intent
)

void onRebind(Intent intent
)


曾经给bindService方法的intent给onBind方法了,给unbindService()方法的intent给onUnbind方法了。如果service准许bingding, onBing()方法把用户用来与service交流的通道返回。The onUnbind() method can ask for onRebind()
to be called if a new client connects to the service。


The following diagram illustrates the callback methods for a service. Although, it separates services that are created via startServicefrom those created by bindService(), keep in mind that any service,no matter how it's started, can potentially allow clients to bind to it,so any service may receive onBind() and onUnbind() calls.




Android应用开发基础简介


Broadcast receiver lifecycle

只有一个callback方法


void onReceive(Context curContext, Intent broadcastMsg
)


当broadcast msg到达时,android调用上面的方法并把包含broadcast msg的intent传给他。broadcast receiver只有在执行这个方法时才是alive的,当这个方法返回时也就inactive了。


因为一个main process with an active broadcast receiver is protected from being killed. 所以如果对这个broadcast msg的反应时间会比较长的话,如果用另一个线程来运行onReceive()并同时返回的话, Android系统会认为整个过程包括new Thread()是inactive, 并且会被kill. 所以解决这个问题的方法是让onReceive()方法start a service() and let service do the job. so the system knows that the process is still active.


Processes and lifecycles

当memory lows的情况下,Android会根据运行在process上的component的重要性和state,对所有的process进行一个分级。最不重要的回先被kill,并以此类推向上。


1. foreground: 还在于用户交流。 A process is considered to be in the foreground if any of the following conditions hold:

  • It is running an activity that the user is interacting with (the Activity object's onResume()
    method has been called).
  • It hosts a service that's bound to the activity that the user is interacting with.

  • It has a Service
    object that's executingone of its lifecycle callbacks (onCreate()
    , onStart()
    , or onDestroy()
    ).

  • It has a BroadcastReceiver
    object that's executing its onReceive()
    method.

2. visible: 没有foreground组件,但是对用户能看到的屏幕还有影响。

  • It hosts an activity that is not in the foreground, but is still visible to the user (its onPause()
    method has been called). This may occur, for example, if the foreground activity is a dialog that allows the previous activity to be seen behind it.
  • It hosts a service that's bound to a visible activity.

3. service process: 一个被start service启动的service,并且这个服务不属于以上任何一种

4. background process: is one holding an activity that is not currently visible to the user(onSTOP()). 对用户体验无影响。系统中同时有许多background process, 用一个least recently used list来最后删除用户最近用过的activity.

5. empty process: 没有任何的active component. 仅用来作为下次这个组件运行时的cache.


进程最先从5开始被清除出memory.


因为service的级别比backgroud高,所以如果activity有需要长期运行的任务最好用service而不是thread来运行。