一、Android应用的理解
对一般的操作系统而言,程序通常就是操作系统中进程的概念。以Windows里面的办公软件Word为例,如图1所示,当启动Word程序后,Windows的任务管理器中会出现一个名为“winword.exe”的进程,而这个winword.exe其实就是MS Office软件包中的一个可执行文件。只是除了这个winword.exe文件之外,还需要若干个依赖的.dll动态链接库文件一起配合才能执行,如图2所示。
图1 Windows中的进程
图2 winword.exe程序依赖的动态链接库
从这里可以看出,一个Windows系统上的应用程序,可以简单理解为由.exe可执行程序和.dll动态链接库文件共同构成。当应用程序启动加载到内存中,就变成了“进程”的概念了。同样,
在Linux平台上,一个应用程序也是由一个可执行文件(比如gzip)和若干.so的文件构成,其中.so文件是一些共享对象(shared object)文件,它们的作用与.dll动态链接库是类似的。
现在回过头来看看Android平台上的应用程序。当我们开发Android应用程序时,一般需要在ADT集成开发环境中新建一个Android Application Project项目,图3是一个典型的Android项目结构:
图3 Android项目结构
当然,Android项目最终还是要被打包成.apk文件(比如这里的BMI.apk)才能使用,这个.apk表面上看起来与Windows平台上的.exe是类似的,都是用来执行的程序,对Android的初学者而言,这种类比更容易理解。
实际上,Android平台的.apk文件的角色,只是承载Android组件的一个载体,.apk并不等同于.exe文件。
二、Android组件模型
我们知道,在开发Android应用程序时,一般都会涉及到Acivity、Service、BroadcastReceiver和ContentProvider这四大组件。那么,到底什么是组件呢?所谓组件,我们可以将它理解成是Android应用程序的组成部分,一个Android应用程序通常都要包括若干个组件,这些组件可以来自于一个apk文件,也可以来自多个apk文件。值得注意的是,这里说的组件概念更为宽泛,并不是一般意义上所说的按钮、下拉框之类的控件,而是一种抽象意义上的“软件单元”。
下面使用一张图来对Android平台的组件进行说明,如图4所示。
图4 Android组件模型
对Android来说,外部的应用程序通常都是以.apk软件包的形式安装的。在图3的BMI项目结构中,共定义了两个Activity组件(BMIActivity和InfoActivity),当我们把项目打包成.apk文件并安装到Android系统时,BMIActivity和InfoActivity就成了Android系统管理的两个组件了。
此时,Acivity、Service、BroadcastReceiver和ContentProvider这四大组件实际上就变成了Android平台上的“积木块”,安装某一个.apk软件包到Android平台,实际上只是往Android平台上安放了几个积木块,如图4所示,这就是Android所谓的“组件”概念。在图4中,X.apk中承载了Activity1和Activity2两个组件,Y.apk中承载了Activity3、Service1和BroadcastReceiver0这三个组件,Z.apk中承载了ContentProvider0这个组件。
还记得每个Android应用程序项目都有一个AndroidMenifest.xml文件吗,这个文件其实就是组件的注册文件(类似Windows平台的.reg文件),每个定义的Acivity、Service、BroadcastReceiver和ContentProvider组件都必须在AndroidMenifest.xml中予以声明,否则在Android上是不可用的,至多只是一个普通的Java类而已。当.apk软件包安装到Android中时,Android会读取AndroidMenifest.xml中声明的组件,然后集中管理这些组件,就像Windows注册表所做的那样。
一个真正意义上的Android应用程序,其中用到的组件并不一定恰好在一个.apk中,它可以是Android上组件“积木块”的任意组合。比如我们开发了一个应用,这个应用的项目中定义了Activity1和Activity2两个组件,然后打包成X.apk安装到Android,但在Activity1的代码中还用到了Activity3组件,这个Activity3组件是Android系统上已经安装好的一个组件(比如Activity1调用Activity3这个照相机组件,而Activity3组件是通过Y.apk安装进来的)。
三、Task栈与Intent组件调用
与传统操作系统不同的是,Android应用程序的概念并不是一个apk,而是一个Task,即任务。所谓Task,就是根据需要将Android平台上的若干组件组合起来,通过这些组件的配合达到预期的目的。Windows中的应用程序体现出来的是“进程”,而Android应用程序体现出来则是“Task”,即任务。当然,Android底层的Linux操作系统上最终的跑的还是进程,但这些进程不是由我们的应用程序直接控制的,所以,Android组件是被托管到进程中运行的。所以,Android应用程序并不与.apk文件一一对应,我们可以根据需要对Android上的组件任意组合,就像搭乐高积木一样,而Android应用包含的各组件在哪个进程中,已经变得不重要了,系统会帮忙处理好一切。
一般情况下,当我们运行某个应用程序时,实际上是找到这个应用程序的“起始组件”,通常都是Activity组件,因为只有Activity组件才有可视界面,可以响应用户的操作,然后以起始组件为出发点调用其它组件,从而完成我们希望的功能。在开发Android应用程序时,通常都会声明处理如下动作的Activity组件:
<activity
android:name="mytest.Activity1"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
其中,“android.intent.category.LAUNCHER”的含义是允许Android桌面启动器(Launcher)检测应用软件的包名,然后把当前应用的图标和名称解析出来显示在应用列表里。这样,当我们点击桌面启动器的应用程序图标时,声明了“android.intent.action.MAIN”动作的Activity将被启动,类似于Java语言程序的main()方法。
顺带提一下,如果你希望自己的应用程序不会在桌面启动器中出现图标,只需将“android.intent.category.LAUNCHER”的声明去掉即可。
现在假定应用程序要从Activity1开始启动,然后在Activity1中有一个按钮,点击按钮能启动到Activity2,Activity2中也有一个按钮能启动到Activity3,此时,这三个组件就共同完成了当前应用程序的功能。对Android来说,这三个组件是一任务栈的方式进行管理的,如图5所示。
图5 Android任务栈(应用程序当前组件为Activity3)
严格来说,由Activity1、Activity2和Activity3共同形成的任务栈才是Android应用程序的概念。如果当前显示的是Activity3组件,然后点击两次返回键,此时任务栈中就剩下Activity1了,如图6所示。
图6 Android任务栈(应用程序当前组件为Activity1)
当然,在任务栈中管理的只是Activity组件,其它组件也可以在应用程序中使用,只不过它们不会出现在任务栈中而已。到现在,我们应该明白Android应用程序是怎么回事,说白了,Android应用程序是由若干组件共同配合所构成的一个动态过程(任务栈),它用到的组件可能来自一个或多个.apk文件中定义的组件。
在应用程序中,当你需要启动某个组件时,因为组件是被托管在底层的进程中,因此我们不能直接创建组件的对象,而是通过Android的Intent意图机制来达到目的。引入Intent的原因,就是因为组件是被托管的,既然是被托管,我们不能直接决定其生死(比如new Activity1()),而是需要构造一个Intenet对象,丢给Android系统,Android系统会根据Intent中提供的意图信息去查找所有注册过的组件,找到后启动该组件。也正是因为Android组件的生死不是有我们来控制的,我们只能向Android请求需要用到某个组件,所以才会出现Activity、Service等组件声明周期的说法。
下面以Activity1启动Activity2为例来说明Intent的工作原理,如图7所示:
图7 通过Intent启动其它组件
Intent intent = new Intent();
intent.putExtra("bmi", 1.5);
intent.setClass(Activity1.this, Activity2.class);
startActivity(intent);
从这里可以看出,我们要启动Activity2,要做的只能是新建一个Intenet对象,然后通过startActivity()方法将这个Intent对象发给Android。当Android收到这个要求时,它会查找符合条件的组件,然后启动这个组件。
在Android中,通过Intent机制启动组件分为显式启动和隐式启动。这里给的例子就是显式启动,组件Activity1的代码中完全知道Activity2,因此通过intenet.setClass()就提供了所要的组件信息,而且还使用intenet.putExtra()方法将某些数据传递给Activity2组件。而对于隐式启动组件的方法,首先要在配置文件中声明被启动组件Activity2,设置其能够处理的<intent-filter>,然后在调用者Activity1的代码中,就要通过Intent设置希望匹配的动作信息,比如:
// 调用Web浏览器
uri = Uri.parse("http://www.google.com");
intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
总之,Android的组件机制要求组件之间不能相互直接调用或使用,因此你不能在Activity1的代码中直接创建一个Activity2的对象(new Activity2()),永远不要这样做!组件之间的调用必须通过Android统一进行调度,有点类似于“中央集权”。组件之间的调用,必须通过Intent,无论是显式Intent还是隐式Intent都是如此。
四、Context的理解
在Android应用程序开发时,还有一个经常用到的Context概念,即“上下文”。这个Context就像一只无形的手,很多类和方法的调用都需要借助Context,通过它可以访问当前包的资源(getResources()、getAssets()),也能启动其它组件(Activity、Service、BroadcastReceiver),还可以得到各种服务(getSystemService()),因此,实际上Context是提供了应用程序的运行环境,在Context这个大环境里,各个组件才可以访问资源,才能完成和其他组件、服务的交互。
我们首先来看一下Context与Application、Service、Activity等几个常用类之间的关系:
图8 Context/Activity/Service/Application之间的关系
最上面的Context是一个抽象类,下面的Application、Service、Activity类都间接继承了这个Context抽象类。ContextWrapper类是Context抽象类的实现者,但它实际上只是一个Context抽象类所要求功能的一个“封装”(抽象类中有抽象方法,子类必须提供抽象方法的实现代码),真正提供具体功能代码的实际上是ContextImpl类,因此ContextImpl类才是那只真正伸向Android核心框架服务的手,Application、Service、Activity类可以通过ContextWrapper类间接将手伸向Android核心框架服务。比如向Android要求获取应用程序的资源文件,用到的getResource()方法就是通过ContextWrapper调用ContexImpl的具体方法来得到的。
因为Activity、Service类都继承了ContextWrapper,换句话说Activity和Service组件都是上下文,都有获取系统资源的能力。对于Application,这是一个应用对象,Acivity、Service、BroadcastReceiver和ContentProvider这四大组件都必须在<application>应用对象内部声明才能被Android系统所接受。在Activity和Service中要获得这个Application对象,可以通过调用getApplication()得到,此外还可以通过调用getApplicationContext()得到这个Application对象,它同时也代表一个Context。
值得注意的是,尽管Acivity、Service和Application都是继承自Context,虽然它们都代表Context,但它们并不是同一个,因为各个组件都是独立的。
参考资料:
http://www.cnblogs.com/android100/p/Android-Context.html
相关推荐
此外,理解Android的组件模型是关键,如Activity(活动)、Service(服务)、BroadcastReceiver(广播接收器)和ContentProvider(内容提供者),这些构成了Android应用的核心架构。 PPT中可能详细讲解了如何创建...
2. Android组件:深入探讨Activity、Service、BroadcastReceiver、ContentProvider和Intent的工作原理及其交互方式。 3. UI设计:介绍布局管理器如LinearLayout、RelativeLayout和ConstraintLayout,以及自定义视图...
在这里,Model表示数据模型,View是用户界面,ViewModel作为两者之间的桥梁。 4. **XML布局文件**: XML文件定义了应用的用户界面元素,如TextView、EditText和Button等,以及它们的布局属性。 5. **Adapters**: ...
- **Android 5.x新特性**:如Material Design的设计风格更新、新的权限模型等。 - **运行时权限管理**:Android 6.0引入的新特性,用户可以在应用运行时选择授予或拒绝特定权限。 - **多窗口支持**:针对大屏设备的...
在Android平台上,开发一款原创的小游戏是学习移动应用编程的好方式。这个名为“九宫格”的小游戏就是一个典型的示例,它结合了基本的Android开发技术和逻辑思维元素。下面我们将深入探讨这款游戏中涉及到的关键知识...
1. UI层:主要包括Activity、Fragment和Adapter等组件,负责用户界面的展示和交互。 2. 业务逻辑层:包括Presenter类,处理UI层与Model层的通信,执行具体的业务逻辑。 3. 数据模型层:包括Model类,封装数据处理和...
- `原创android界面效果全汇总.pdf`:这份文档可能包含了各种Android界面设计和实现的实例,包括但不限于滑动菜单、动画效果、自定义控件等。开发者可以通过学习这些案例,提升应用的视觉吸引力和交互性。 2. **...
理解Android的组件模型,如Activity、Service、BroadcastReceiver和ContentProvider。 2. **用户界面设计**:遵循Material Design指南创建直观、响应式的用户界面,使用XML布局文件定义界面元素,可能涉及...
Android开发平台为开发者提供了完善的开发环境,包括集成开发环境(IDE)如Eclipse,它支持面向对象的编程语言Java,使得开发者能够构建高效、稳定的移动应用。对于Android计算器的实现,首先需要理解Android的基本...
Socket是网络编程中的基础组件,它允许两个程序通过网络进行数据交换。在Android应用中,我们通常使用`java.net.Socket`类来创建和管理连接。源码中的Socket通信可能涉及到以下几个步骤:建立连接、发送数据(如玩家...
通过React的声明式编程模型和组件化思想,开发者可以轻松地创建丰富的用户界面。 针对"react-native progress bar",我们主要会用到React Native的Progress组件。这个组件提供了两种类型的进度条:Progress.Circle...
7. **权限管理**:考虑到Android的权限模型,源码可能包含了对运行时权限的管理,例如使用AndroidX的PermissionRequester或者EasyPermissions库。 8. **支付集成**:为了实现在线支付,源码可能集成了支付宝、微信...
6. **Android应用开发**:涉及到Android SDK、Android Studio等开发工具的使用,以及对Android编程模型的理解,包括Activity、Intent、BroadcastReceiver等组件的使用,以及XML布局设计和Java/Kotlin编程语言的应用...
这有助于理解Android的异步编程模型和生命周期管理。 5. **服务与广播接收者**: 音乐播放器可能包含后台服务,以便在应用被关闭后仍能继续播放音乐。同时,应用可能注册了广播接收者来监听系统事件,如耳机插拔或...
设计Android新闻客户端,需要掌握Android SDK、Java编程语言,以及XML布局设计。应用通常包括以下几个关键组件: - 数据获取:通过API接口与新闻服务器进行数据交换,获取最新、热门的新闻资讯。 - 数据解析:使用...
【标题】"应用源码之TestSwitchButton.zip" 提供了一个深入学习Android源码的机会,特别是聚焦于`SwitchButton`这一组件。`SwitchButton`在Android应用开发中扮演着重要角色,它是一种开关控件,用户可以切换其状态...
6. MVC设计模式:模型-视图-控制器(MVC)是一种广泛使用的软件设计模式,将应用分为三个核心组件:模型(Model)负责数据和业务逻辑,视图(View)负责展示数据,控制器(Controller)负责接收用户输入并调用模型和...
8. **事件监听与响应**:Android的事件驱动模型在源码中会有体现,如点击事件、滑动事件等,通过OnClickListener、OnSeekBarChangeListener等接口实现。 9. **异步编程与线程管理**:为了保证UI线程不被阻塞,源码...
该压缩包“应用源码在线词典源码.zip”包含了一个Android应用项目,其设计目标是实现一个在线词典功能,这对于学习Android编程以及Java编程的开发者来说是一个宝贵的资源。源码学习是提升技能的重要途径,通过阅读和...