Android进阶#(1/12)Android的构成基石——四大组件_Activity

####反正现在的 感情 都 暧昧,你大可不必为难找般配。####

####虽然Kotlin的重构之风已起,但即便30年前的汇编也是有嚼头的####

声明:本内容为何红辉所著《Android开发进阶——从小工到专家》一书读书笔记来的。

内容有三个部分:

一、Android开发核心:View与动画、多线程、网络、数据库、性能优化,深入了解开发中最为重要的知识;

二、代码规范、单元测试、版本控制、OOP与模式、重构等,使读者具备构建低耦合、灵活性强的应用软件; 

三、一个完整的示例,演示如何把一个充满问题的应用软件逐步演化为 低耦合、清晰、可测试的实现过程。其中展示了常见的重构方法、测试手段,从真实的示例中汲取知识和经验,提升技术与设计能力,绕过编程中的诸多陷阱。

另注:

本书示例代码都托管在GitHub,地址:https://github.com/bboyfeiyu/android_jtm_sourcecode,读者可通过Git进行下载。

#### 如果是单纯的版面网页文档化,逐一目录内容的去摘录,就显得赘余了。####


(1/12)Android的构成基石——四大组件

 |  Activity  |  Service  |  ContentProvider  |  Broadcast  |

这4个组件分工明确,共同构成了 可重用、灵活、低耦合的Android系统。

Activity负责 UI元素的加载与页面之间的跳转,代表了一个页面单元。

Service负责 与UI无关的工作,如在后台执行耗时操作等。

ContentProvider负责 存储、共享数据,使得数据可以在多个应用之间共享。

Broadcast则是在各个组件、应用之间进行通信,简化了Android开发中通信问题。

Activity

Activity在应用中的表现就是一个用户界面。它会加载指定的布局文件来显示各种UI元素,例如:TextView,Button,ImageView,ListView等,并且为这些UI元素设置事件处理函数,使得用户可以与这些UI进行交互。同时,Activity还可以在不同的Activity之间跳转,将不同的页面串连在一起,共同完成特定的操作流程。每个应用都是由一个或多个Activity组成,它是Android应用程序中不可缺少的部分。

启动应用时会加载一个默认的Activity,这个Activity在AndroidManifest.xml中会被设置为如下intent-filter:



每个Activity都有生命周期,在不同的阶段回调不同生命周期函数,Activity的生命周期函数有如下几个:

1.onCreate()

相信这是开发者见过的次数最多的函数,我们在创建继承者自Activity的类时都会默认生成这个函数。

它会在Activity第一次被创建时调用,通常会在这个函数中完成Activity的初始化操作,如设置布局、初始化视图、绑定事件等。

2.onStart()

这个函数在Activity的onCreate函数调用之后被调用,此时的Activity还处在不可见状态,它的下一个状态就是Activity变得可见的时候。也就是这个函数在Activity可见之前被调用。

3.onResume()

这个函数在Activity变为可见时被调用,执行完onResume之后,Activity就会请求AMS渲染它所管理的视图。

此时的Activity一定位于返回栈的栈顶,并且处于运行状态。

4.onPause()

这个函数在系统准备去启动或者恢复另一个Activity时调用,也就是在Activity即将从可见状态变为不可见时,我们通常会在这个函数中将一些消耗CPU的资源释放掉,以及保存一些关键数据。

5.onStop()

这个函数在Activity完全不可见时调用,它和onPause()函数的主要区别是,如果新启动的Activity是一个对话框式的Activity,那么onPause()函数会得到执行,而onStop()函数并不会执行。

6.onDestroy()

这个函数在Activity被销毁之前调用,之后Activity的状态将变为销毁状态。

7.onRestart()

这个函数在Activity由停止状态重新变为运行状态之前调用,也就是Activity被重新启动了。


从onCreate()函数到onDestroy()函数运行的时期就是一个完整的Activity生命周期。

一般情况下,我们会在一个Activity的onCreate()函数中完成各种初始化操作;

而在onDestroy()函数中完成释放内存的操作。

然而并不是各个时期Activity都是可见的 ,只有 onResume()函数和 onStop()函数之间的Activity是可见的,在Activity可见期内,用户可以与Activity进行交互,完成所需的功能。


Activity 的构成

Activity的构成并不是一个Activity对象再加上一个布局文件那么简单哦。

在Activity和开发人员设置的视图之间还隔着两层。

实际上视图会被设置给一个Window类,这个Window中含有一个DecorView,这个DecorView才是整个窗口的顶级视图。

开发人员设置的布局会被设置到这个DecorView 的 mContentParent 布局中。

也就是所Android中实际上内置了一些系统布局文件xml,我们在xml中定义的视图最终被设置到这些系统布局的特定节点之下,这样就形成了整个DecorView。

【这是简易结构图】


下面是一个名为screen_title 的系统布局xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:fitsSystemWindow="true">
    <!-- Popout bar for action modes -->
    <ViewStub android:id="@+id/action_mode_bar_stub"
                android:inflatedId="@+id/action_mode_bar"
                android:layout="@layout/action_mode_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="?attr/actionBarTheme"/>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="?android:attr/windowTitleSize"
        style="?android:attr/windowTitleBackgroundStyle">
        <TextView android:id="@android:id/title"
            style="?android:attr/windowTitleStyle"
            android:background="@null"
            android:fadingEdge="horizontal"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </FrameLayout>
    <!-这里就是开发人员设置的布局所填充的位置-->
    <FrameLayout android:id="@android:id/content"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:foregroundGravity="fill_horizontal|top"
        android:foreground="?android:attr/windowContentOverlay"></FrameLayout>
</LinearLayout>

文件总包含了actionbar和标题栏区域,下面就是开发人员设置给Activity的布局区域,这个区域被添加到名为content 的布局中,而这整个screen_title.xml又是DecorView的子视图,因此,最终用户界面会显示为标题栏、开发人员设置的界面。

Activity的4种启动模式

每个应用程序都是由一个或者多个Activity组成。

因此,Android内部使用通过回退栈来管理Activity实例。

栈是一种后进先出的集合。

对于Android来说,当期显示的Activity就在栈顶,当用户点击后退键或者点击应用上的返回按钮,系统就会将栈顶的Activity出栈。

此时,原来栈顶下的Activity就会变为栈顶显示到设备上。


然而,事情可能并不是那么简单,在一些特殊情况下我们可能需要对Activity实例做一些特殊的处理,

例如,为避免重复创建Activity,我们要求一个Activity只有一个实例。

好在Android系统为我们提供了这些功能,也就是我们本节要说的Activity的4 个启动模式。

用户可以在AndroidMainfext.xml注册Activity时设置它的启动模式。

例如:

<activity 
            android:name=".MyActivity"
            android:launchMode="singleTask"
            android:label="@string/app_name">
        </activity>
Activity启动模式有四个:


singleTask

singleInstance

singleTop

standard

虾米卓哥介绍:

1)standard(标准启动)

其实就是默认的启动模式。

这种模式下启动的Activity可以被多次实例化,即在同一个任务栈中可以存在多个Activity实例。每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并已有一个Activity A被启动,在该Activity A中调用startActivity 时会启动一个新的 Activity A实例。

栈的变化如下:


如果Activity A是一个非常耗资源的类。那么将会使它所依附的应用消耗更多的系统资源。

2)singleTop(如果此Activity实例已在栈顶)

如果一个以singleTop模式启动Activity的实例已经存在于任务栈的栈顶。那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()函数将Intent对象传递到这个实例中。

例如:Activity的启动模式为singleTop,并且Activity A的一个实例已经存在于栈顶中。那么再调用startActivity启动另一个Activity A 时,不会再次创建 Activity A的实例,而是重用原来的实例,并且调用原来实例 的 onNewIntent()函数。此时任务栈中还是这一个Activity A 的实例。


如果以singleTop模式启动的Activity的一个实例已经存在于任务栈中,但是不在栈顶,那么它的行为和standard模式相同也会创建一个新的实例。


3)singleTask(常用启动模式)

singleTask 模式是常用的启动模式,如果一个Activity 设置了该启动模式,那么在一个任务栈中只能有一个该 Activity的实例。

如果任务栈中还没有改Activity,会新创建一个实例并放在栈顶。但是,如果已经存在 Activity ,系统会销毁处在该 Activity 实例处于栈顶,同时回调该Activity的onNewIntent()方法。

栈内变化如图:

4)singleInstance

设置了singleInstance模式的Activity会在一个独立的任务中开启,并且这个新的任务中有且只有这一个实例。

即就是说,被该实例启动的其它Activity会自动运行于另一个任务中。

当再次启动该Activity实例时,会重用已存在的任务和实例,并调用该实例的onNewIntent()函数,将Intent实例传递到该实例。


就是说,singleInstance能够保证Activity在系统中只有一个实例,不管多少应用要启动该Activity,这个Activity有且只有一个。而不是在不同的任务栈中可以同时存在同一个Activity(比如singleTask启动的Activity)。

FragmentActivity与Fragment

为了更好地运用越来越大屏幕空间,Android在3.0版本引入了Fragment,它可以像Activity一样包含布局。

不同的是Fragment是被嵌套在Activity中使用,它作为一个更大粒度的UI单元。如果需要兼容低于Android3.0的系统,那么开发人员需要引用android-support-v4 的jar包才能使用Fragment功能。

假如这样的场景:

wo们的新闻应用含有两个Activity,第一个Activity是显示新闻标题、概要信息的列表,当用户点击这些标题时进入该新闻的详细页面进行阅读。

Fragment为了应对这种情况出现,我们可以使用两个Fragment。


每个Activity包含一个Fragment


横屏模式下包含两个Fragment的Activity


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值