Android四大组件和启动模式(面试总结)

Android四大组件和启动模式(面试总结)

一、Android四大组件详解

Android四大组件分别为Activity、Service、Content Provider、Broadcast Receiver。

1、Activity

(1)一个Activity通常就是一个单独的屏幕(窗口)。

(2)Activity之间通过Intent进行通信。

(3)Android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。

2、Service

(1)继承Service类

public class SMSService extends Service{

}

service用于在后台完成用户指定的操作。service分为两种:

(a)started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。

(b)bind(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bind状态。

(2)startService()与bindService()区别:

(a)startService()(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。

(b)使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

(3)开发人员需要在应用程序配置文件中声明全部的service,使用<service></service>标签。

在AndroidManifest.xml文件中的<application>节点里对服务进行配置:

<service
    android:name=".SMSService "
</service>

(4)Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。

3、Content Provider

(1)android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。

(2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。

(3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。

(4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。

(5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。

4、Broadcast Receiver

(1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

(2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。

(3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。

二、android四大组件总结:

(1)4大组件的注册

4大基本组件都需要注册才能使用,每个Activity、Service、Content Provider都需要在AndroidManifest文件中进行配置。AndroidManifest文件中未进行声明的activity、服务以及内容提供者将不为系统所见,从而也就不可用。而broadcast receiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。

(2)4大组件的激活

内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件activity、服务和广播接收器被一种叫做intent的异步消息所激活。

(3)4大组件的关闭

内容提供者仅在响应ContentResolver提出请求的时候激活。而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。Activity关闭:可以通过调用它的finish()方法来关闭一个activity。服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。

(4)Android中的任务(activity栈)

(a)任务其实就是Activity的栈,它由一个或多个Activity组成,共同完成一个完整的用户体验。栈底的是启动整个任务的Activity,栈顶的是当前运行的用户可以交互的Activity,当一个Activity启动另外一个的时候,新的Activity就被压入栈,并成为当前运行的activity。而前一个Activity仍保持在栈之中。当用户按下BACK键的时候,当前Activity出栈,而前一个恢复为当前运行的Activity。栈中保存的其实是对象,栈中的Activity永远不会重排,只会压入或弹出。

(b)任务中的所有activity是作为一个整体进行移动的。整个的任务(即Activity栈)可以移到前台,或退至后台。

(c)Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时,也执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。为了解决这个问题,Android引入了一个新的机制,即生命周期(Life Cycle)。

 

二. Android启动模式

(1)、具体解释

Standard 标准模式 

Activity中可以有多个实例,每次启动Activity,无论任务栈中有无这个实例,系统都会创建一个新的Activity实例。

SingleTop 栈顶复用模式 

若已有一个Activity位于栈顶时,再去启动他时不会再创建新的实例。如果不位于栈顶时就会再创建一个新的实例。

SingleTask 栈内复用模式

Activity在同一个Task内只用一个实例,如果Activity已经位于栈顶,系统不会再创建新的实例。但Activity已经存在确不位于栈顶时,系统就
会把Activity移到栈顶,并把他上边的Activity移出栈。【单例模式常用】只在任务栈内单例,系统可以有多个singleTask Activity实例的。

SingleInstance 单实例模式

Activity在整个系统里只有一个实例, 启动一个SingleInstance Activity时 系统会创建一个新的任务栈,并写这个任务栈只有他一个Activity。(单例模式很少用程序启动慢)

(2)、启动模式的使用方式

1. 在 Manifest.xml中指定Activity启动模式

一种静态的指定方法,在Manifest.xml文件里声明Activity的同一时候指定它的启动模式,这样在代码中跳转时会依照指定的模式来创建Activity。样例例如以下:在activity节点下添加android:launchMode=”singleTop”,(根据需要选择启动模式。

<activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">

2. 启动Activity时。在Intent中指定启动模式去创建Activity

一种动态的启动模式,在new 一个Intent后,通过Intent的addFlags方法去动态指定一个启动模式。样例例如以下:

        Intent intent = new Intent();
        intent.setClass(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);

注意:以上两种方式都能够为Activity指定启动模式,可是二者还是有差别的。

 

(1)优先级:动态指定方式即另外一种比第一种优先级要若两者同一时候存在,以另外一种方式为准。

2)限定范围:第一种方式无法为Activity直接指定 FLAG_ACTIVITY_CLEAR_TOP 标识,另外一种方式无法为Activity指定 singleInstance 模式。

 

(3)、 Activity 的 Flags

标记位既能够设定Activity的启动模式,如同上面介绍的,在动态指定启动模式,比方 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP 等。它还能够影响Activity 的运行状态 ,比方 FLAG_ACTIVITY_CLEAN_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。

以下介绍几个基本的标记位,切勿死记,理解几个就可以,须要时再查官方文档。

1. FLAG_ACTIVITY_NEW_TASK

作用是为Activity指定 “SingleTask”启动模式。跟在AndroidMainfest.xml指定效果同样。


2. FLAG_ACTIVITY_SINGLE_TOP

作用是为Activity指定 “SingleTop”启动模式,跟在AndroidMainfest.xml指定效果同样。


3. FLAG_ACTIVITY_CLEAN_TOP

具有此标记位的Activity,启动时会将与该Activity在同一任务栈的其他Activity出栈。一般与SingleTask启动模式一起出现。它会完毕SingleTask的作用。但事实上SingleTask启动模式默认具有此标记位的作用


4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有此标记位的Activity不会出如今历史Activity的列表中,使用场景:当某些情况下我们不希望用户通过历史列表回到Activity时,此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:

android:excludeFromRecents="trure"

(4)、 启动模式的实际应用场景

这四种模式中的Standard模式是最普通的一种,没有什么特别注意。而SingleInstance模式是整个系统的单例模式,在我们的应用中一般不会应用到。所以,这里就具体解说 SingleTop 和 SingleTask模式的运用场景:

1>. SingleTask模式的运用场景

最常见的应用场景就是保持我们应用开启后仅仅有一个Activity的实例。最典型的样例就是应用中展示的主页(Home页)。

假设用户在主页跳转到其他页面,运行多次操作后想返回到主页,假设不使用SingleTask模式,在点击返回的过程中会多次看到主页,这明显就是设计不合理了。

 




2>. SingleTop模式的运用场景

假设你在当前的Activity中又要启动同类型的Activity,此时建议将此类型Activity的启动模式指定为SingleTop,能够降低Activity的创建,节省内存!

 




3>. 注意:复用Activity时的生命周期回调

这里还须要考虑一个Activity跳转时携带页面參数的问题

由于当一个Activity设置了SingleTop或者SingleTask模式后,跳转此Activity出现复用原有Activity的情况时,此Activity的onCreate方法将不会再次运行。onCreate方法仅仅会在第一次创建Activity时被运行。

而一般onCreate方法中会进行该页面的数据初始化、UI初始化,假设页面的展示数据无关页面跳转传递的參数,则不必操心此问题,若页面展示的数据就是通过getInten() 方法来获取,那么问题就会出现:getInten()获取的一直都是老数据,根本无法接收跳转时传送的新数据!

以下,通过一个样例来具体解释:

        <activity
            android:name=".activity.CourseDetailActivity"
            android:launchMode="singleTop"
            android:screenOrientation="portrait" />
public class CourseDetailActivity extends BaseActivity{
  ......
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course_detail_layout);
        initData();
        initView();
    }

    //初始化数据
    private void initData() {
        Intent intent = getIntent();
        mCourseID = intent.getStringExtra(COURSE_ID);
    }

    //初始化UI
    private void initView() {
    ......
    }
    ......
}

以上代码中的CourseDetailActivity在配置文件里设置了启动模式是SingleTop模式,依据上面启动模式的介绍可得知,当CourseDetailActivity处于栈顶时。再次跳转页面到CourseDetailActivity时会直接复用原有的Activity,并且此页面须要展示的数据是从getIntent()方法得来,可是initData()方法不会再次被调用,此时页面就无法显示新的数据。

 

当然这样的情况系统早就为我们想过了,这时我们须要另外一个回调 onNewIntent(Intent intent)方法。此方法会传入最新的intent,这样我们就能够解决上述问题。这里建议的方法是又一次去setIntent。然后又一次去初始化数据和UI。代码例如以下所看到的:

/*
 * 复用Activity时的生命周期回调
 */
@Override
protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        initData();
        initView();
}

这样,在一个页面中能够反复跳转并显示不同的内容。

启动模式事实上是初学Android时会学到的知识点,曾经也是一知半懂,有些知识点事实上跟设计模式一样,你不去使用而仅仅是学习并不是能够掌握到精髓,仅仅有真正去使用才会将这些变成你自己的,文章部分内容參考了《Android开发艺术探索》。推荐。

 

然后Android四大组件和启动模式(面试总结),基本到此结束,书到用时方恨少,纸上得来终觉浅。希望有所帮助。如有不对欢迎留言交流。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115024.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号