标签:
我们常说的“安卓应用”可能有三种不同的概念:
软件,能够完成一个特定功能的软件。例如“安装一个应用”、“这个应用可以帮助你寻找附近的美食”。
安装包,应用的实体,是我们摸得着、看得见的APK包,是一个很具体的东西。
应用运行起来后在内存中存在的形态。安装在设备上的APK文件在系统中运行起来就是Application。Android应用开发中,常说的Application就是它。它就是Android SDK中的Application
类。
在讨论程序的开发、执行、存在周期的时候,我们说的Application
就是第三种意思。
Activity
、Service
、ContentProvider
与BroadcastReceiver
被称作Android应用的四大组件,它们分别对应着一个应用程序可能用到的表现形式。
这是应用的显示组件。通常来讲,我们能看到的设备上的内容,除了状态栏(statusbar)、导航栏(navigation bar)、锁屏界面,凡是显示出来的内容都属于Activity
。
(为了便于理解,这里讲的是大多数情况,一些窗口类型的界面–例如popupwindow,toast,输入法、壁纸等等,不应该称作Activity。)
Activity
中显示的是一个应用希望呈现给用户的内容。我们开发的应用基本上一定会有一个Activity
,用来向用户展示我们希望呈现的内容。例如电话拨号界面,设置界面,日历界面。
这是应用可以在后台运行的服务组件,不需要有用户看得见的界面。它通常需要和Activity
配合,借助Activity
给用户提供控制的界面。
最典型的例子就是音乐播放器。音乐播放器的界面就是一个提供了音乐控制方式的Activity
,当我们点击Activity
上的播放按钮之后,Activity
通知播放器的Service
组件,让Service
组件开始播放音乐;之后即使用户选择退出了音乐播放器的Activity
界面,音乐仍然在被播放着,没有随着界面的退出而停止播放。
这是一个应用的数据存储组件。在Android系统中,出于数据安全的考虑,应用之间是被严格的隔离的,应用A不能访问到应用B的数据。但是如果应用B使用了ContentProvider
组件,就能让应用A通过Android系统制定好的规则获取到应用B愿意提供的数据了。
它就像是一个拥有某种数据的网站,安卓系统运行的其它组件可以通过“网址”访问这个网站,获取需要查询的数据。
ContentProvider
可以是私有的,只能为它所在的应用提供数据访问请求;ContentProvider
也可以是公开的,为别的应用程序提供数据访问请求。这是应用获取系统或者获取某些应用发出特定消息的组件。
例如,有个应用叫“换壁纸”,它希望设备开机完成后,自动更换桌面壁纸。可是开机后“换壁纸”还没有运行起来,用户也不会主动的告诉“换壁纸”“手机已经启动了,换一张壁纸吧”。
这时,就可以通过BroadcastReceiver组件获取开机完成后系统主动发出的“开机完成通知”。得到“通知”后,“换壁纸”就可以按照预想设计工作了。
BroadcastReceiver
组件有个特点,就是包含它的应用不一定要正在运行,系统可以根据“通知”类型,先把这个“通知”告诉关注它的BroadcastReceiver
,由BroadcastReceiver
决定是否需要启动一个Activiy或者Service来做相应的处理。
如果将Activity
、Service
与BroadcastReceiver
这些组件比喻成一座一座的岛屿,那么Intent就是穿梭于这些小岛之间的小船。
Intent不仅能将这些组件联系了起来。Intent也能穿梭于各个应用之间,把它们也联系起来。
在创建Intent的时候,可以使用下面的方式指定小船的目的地。
就像给某个机构发货,只需要发送给某个机构,但不需要知道这个机构中具体是哪个人。
//action_name可以指定那一类组件可以收到这个Intent发出的请求
Intent i = new Intent("action_name");
就像发货时写下接收方具体的名字和地址。
Intent i = new Intent();
i.setClassName("接收方的包名", "接收方的类名");
小船可以携带货物,Intent也可以携带各种类型的数据。在创建Intent对象后,使用如下的方法,你就可以把想要在“岛屿”之间传递的数据放到小船上。
Intent i = new Intent();
i.putExtra("索引关键字",goods);
这些数据包括String
、char
、long
、int
、boolean
、float
、double
、byte
等等常用的基本类型,也包括它们的数组。甚至还能传递自定义类
封装的对象。
不过要传递自定义类
封装的对象,需要这个类做特殊的处理,
继承了Serializable
接口,
class data implements Serializable
{
}
Intent i = new Intent();
i.putExtra("DATA", new data());
继承了Parcelable
接口,
class data implements Parcelable
{
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
}
Intent i = new Intent();
i.putExtra("DATA", new data());
Parcelable
的性能要比Serializable
好很多,传输的效率要高上10倍左右;但是Parcelable
需要开发者自己定义数据序列化和反序列化的规则,所以编码量比使用Serializable
要大很多。
在实际的开发场景中要根据实际的情况作选择。
在应用工程的源码目录下,都有一个AndroidManifest.xml文件,它是这个应用的配置文件,当应用安装到设备上后,Android系统会从这个文件中获取很多关于这个应用的配置信息。
Manifest文件内容,大体如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.anddle.activitytest">
<uses-permission />
<permission />
<permission-tree />
<permission-group />
<instrumentation />
<uses-sdk />
<uses-configuration />
<uses-feature />
<supports-screens />
<compatible-screens />
<supports-gl-texture />
<application
android:icon="@mipmap/ic_launcher"
android:name=".MyApplication">
<activity android:name=".MainActivity"/>
<service android:name=".MyService"/>
<provider android:name=".MyContentProvider"
android:authorities="com.anddle.authoriteies"/>
<receiver android:name=".MyReceiver"/>
</application>
</manifest>
不是所有的项都需要在Manifest文件中使用,通常只会用到最常用的。
应用使用了哪些组件,都要在这个配置文件中登记。不然在程序启动这些组件的时候,系统会找不到它们,导致程序崩溃。
<application
android:icon="@mipmap/ic_launcher"
android:name=".MyApplication">
<activity android:name=".MainActivity"/>
<service android:name=".MyService"/>
<provider android:name=".MyContentProvider"
android:authorities="com.anddle.authoriteies"/>
<receiver android:name=".MyReceiver"/>
</application>
这个应用要使用系统的哪些权限,也要在这个配置文件中声明。这样在安装的时候,系统会根据填写的内容,告诉用户,让用户判断是否接受应用使用这些系统的功能。
例如,一个应用要读取磁盘存储器上的内容,就需要申请权限,如果用户同意,才能成功读取磁盘。
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
在Android系统中,很多模块是互用的。例如当我们启动“相机”拍摄了一张照片,然后通过“图库”浏览刚拍的照片,最后选择“微信”将照片分享出去。为了实现这一些列的操作,达到我们希望的目的,整个过程就利用了3个不同应用,分别使用了它们对应的Activity。
我们将使用到的这些Activity串在一起,称作Task。它们就像一个叠叠乐,后启动的放在另一个的上面–我们给这个叠叠乐一个专业的术语–栈。Task中包含的Activity是以栈的形式存放的。
假如此时,我们按返回按钮一步一步返回,Task中位于顶部的Activity就被一步一步退出,直到退出这个Task中所有的Activity,然后回到了系统主界面。
假如此时,我们按home按钮,就会返回到系统主界面,同时将这个Task保存下来。如果你再启动主界面上的另一个应用,一个新的Task就会被建立起来。
通过上面的描述,我们可以知道:Task只和Activity有关。
另外,Task可以在系统中存在多个,例如启动应用A,创建Activity A,这里就有一个Task A了;然后按“home”键返回,再启动应用B,创建Activity B,这里就有一个Task B了;以此类推,会有Task C Task D。
不过运行在最前台的只有一个Task,这就是前台Task。其他的Task都是后台Task。
站在系统的角度看,Application就是运行着组件的那个线程环境。这个线程环境中运行着正在工作的组件---即那些在它Manifest中声明了的、正运行着的组件。以上面微信分享照片的task作为例子。
相机应用:虽然没有被看见,但它还有Activity存在着,它运行的线程环境还存在着,所以这个application正在运行着;
图片浏览应用:虽然没有被看见,但它还有Activity存在着,它运行的线程环境还存在着,所以这个application正在运行着;
微信应用:很明显,它有Activity运行着,它运行的线程环境存在,所以这个application正在运行着;可以想象微信一定有个正在后台接受网络发送了消息的Service 。这个Service也是application的一部分--因为他们在同一个线程当中(这种说法并不严谨,如果Service被指定了在单独的进程中运行,那么application就不是同一个了。不过这里为了举一个贴近实际场景的例子,就没有去做详细的区分了);
Application可以看做是这些组件的集合,是这些组件对外共同的名字。
Application被运行起来的情况有:
站在系统的角度看,当应用运行起来时,系统为这个应用创造了一个线程环境,这个线程环境就是Application,那些组件运行的环境都在这个线程当中。
由此可知,Application是一个安装应用的入口。不过通常来讲,在通过Android Studio创建工程的时候,并没有给我们指出这个Application,而是使用了系统默认的Application。
另外Android Studio还为我们创建了一个Activity。这多少会让我们误以为Activity才是应用程序被最早启动的地方。
要自己定义应用的Application环境,首先要在代码中继承Application类。这里列出了一部分可以被覆盖的Application类方法。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
public void onTerminate() {
super.onTerminate();
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
}
}
这里的onCreate()
函数才是一个应用被启动的第一个地方(而非Activity的onCreate())。
创建Application类后,我们要再manifest文件中,指明我们的应用要使用这个自定义的Application:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.anddle.activitytest">
......
<application
android:icon="@mipmap/ic_launcher"
android:name=".MyApplication"> -->指定我们自定义的Application
</application>
</manifest>
如果这里不指定android:name
,那么系统将使用默认的Application。
不是所有的应用都需要使用自定义的Application,对于那些有很多组件(Activity Service等等)都需要做相同初始化都应用,就可以使用它。
例如,有个应用包含一个Activity和一个Service,无论是哪个先启动,都首先要去做一个共同的操作。这种情况就可以考虑把那个共同的操作放到Application中进行。
Application还可以作为各个组件共享变量和数据的仓库。
Activity和Service都是有生命周期的,一旦生命结束,它们保存的一些数据就会被释放掉。但是它们的生命结束了,不代表Application的生命结束了(Application是整个应用的生命)。为了其他组件还能继续使用这些数据,我们就可以把数据放着这个生命更长的Application中。
标签:
原文地址:http://blog.csdn.net/anddlecn/article/details/51424721