android四大组件之Activity的学习(四大组件之路:一)

以下是自己在学习中对于Activity理解

Activity的生命周期

一:正常情况下的activity生命周期

Android里所有程序的流程都运行在Activity之中,Activity有自己的生命周期。程序无法改变Activity的生命周期,Activity的生命周期由系统控制。

下图基本说明了Activity在正常和异常情况下的生命周期

android四大组件之Activity的学习(四大组件之路:一)_第1张图片

Activity中常用的函数有SetContentView()  findViewById()    finish()   startActivity(),其生命周期涉及的函数有:

void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()

void onDestroy()

一个个分析这些函数

(1)onCreate方法,Activity被启动时的第一个方法,在这个方法中一般做一些初始化的工作,比如调用setContentView方法加载界面布局,并且可以做一些初始化数据的工作:声明UI元素,定义成员变量,配置UI等。

(2)onStart方法,表示Activity正在被启动,其实这时Activity已经可见了,正如上图所表示的Visible,但并不能被用户所见,我们可以这样理解,Activity现在运行到了后台,还没有准备好到前台和用户交互。

(3)onResume方法,此时Activity来到前台和用户进行交互,用户真正的看到了Activity,Activity可以执行操作,比如说一个Activity上的按钮可以被点击了.  

(4)onPause方法,表示Activity正在停止,该状态下,activity的部分被另外一个activity所遮盖:比如说弹出了一个新的activity页面,导致之前的activity中的按钮不能被点击。被暂停的activity不再接受用户的输入且不再执行任何代码。

(5)onStop方法,该状态下, activity完全被隐藏,对用户不可见。可以认为是在后台。当stopped, activity实例与它的所有状态信息(如成员变量等)都会被保留,但activity不能执行任何代码,这时这个Activity只是不可见并没有被完全销毁。 

(6)onRestart方法,Activity从不可见又变为可见时会调用。此时调用顺序为:onRestart -> onStart -> onResume

(7)onDestroy方法:表示Activity即将被销毁,当收到需要将该activity彻底移除的信号时,系统会调用这个方法。 

接下来用代码和运行结果应证以上几个函数在Actvity生命周期中何时被调用。


两个布局页面

第一个就是普通的Activity 添加一个按钮跳转到另一个activity





    
    


在MainAcitivity中重写我们需要用到的函数

void onCreate(Bundle savedInstanceState)void onStart()void onRestart()void onResume()void onPause()void onStop()

void onDestroy()

package com.example.word.class1;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.view.ViewGroup.FOCUS_BEFORE_DESCENDANTS;

public class MainActivity extends AppCompatActivity {




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("OnCreate 被调用了");

            }
    protected void onStart() {

        super.onStart();
        System.out.println("OnStart 被调用了");

    }
    protected void onResume() {

        super.onResume();
        System.out.println("OnResume 被调用了");

    }
    protected void onPause() {


        super.onPause();
        System.out.println("OnPause 被调用了");

    }
    protected void onRestart() {

        super.onRestart();
        System.out.println("OnRestart 被调用了");

    }
    protected void onStop() {


        super.onStop();
        System.out.println("OnDestroy 被调用了");

    }
    protected void onDestroy() {


        super.onDestroy();
        System.out.println("OnDestroy 被调用了");

    }
    public void Onclick1(View v){
        Intent intent = new Intent(this,second_activity.class);
        startActivity(intent);
    }





}


第二个activity



    
    

运行结果截图

当页面被启动时

android四大组件之Activity的学习(四大组件之路:一)_第2张图片

android四大组件之Activity的学习(四大组件之路:一)_第3张图片

可以看到Oncreate函数最先被调用

应证了Oncreat函数是Activity被启动第一个被调用的函数

接着Onstart被调用 这时候Activity已经运行但是没有与用户交互  设置的按钮不能被点击

再然后OnResume被调用这时候页面已经可见而且按钮已经可以被点击即页面可以与用户发生交互

点击按钮跳转到第二个activity

android四大组件之Activity的学习(四大组件之路:一)_第4张图片

这时我们来看看log是怎么显示的

android四大组件之Activity的学习(四大组件之路:一)_第5张图片

在刚刚的三条语句之后 首先打印出了OnPause 

因为这时候弹出了一个新的activity页面 之前的activity被新的覆盖 之前页面按钮已经无法被点击

然后打印出OnStop

因为这时候界面以及不可见 处于后台运行状态

但是这时程序并没有被销毁 所以没有调用OnDestroy

可以预测的是 如果有一个新的半透明的页面覆盖了当前activity 

导致当前activity可见 但是按钮不可以被点击

(不知道大家有没有玩过早期的腾讯游戏,当你在一个网页中领取奖励的时候会弹出一个页面 让你选择大区和对应的角色

这时候之前的页面变为半透明,你只能在新的页面选择大区角色 但是不能对之前的页面进行任何操作)

类似这样的条件下也就是activity被一个半透明的activity覆盖 我们可以预测 只有OnPause 被调用 而Onstop不会被调用

如果大家有兴趣可以新建一个工程 在AndroidManifest.xml中applica下添加一条属性android:theme="@android:style/Theme.Translucent" 

用这样的新activityty覆盖我们的activity就会出现上述所说的情况

这也应证了OnPause被调用时仅仅是不能点击按钮完成与用户的交互 但是activity是可见的

现在我们按一下返回键 返回到之前的Activity 看看log又会怎么变化

当Activity重新出现的时候首先调用函数OnRestart

由于页面被重新运行

调用OnStart把Activity运行到后台 然后调用OnResume

这时候页面的按钮又可以被点击 即又可以与用户发生交互

我们将程序退出到主界面

android四大组件之Activity的学习(四大组件之路:一)_第6张图片

log打印出和刚刚被activity覆盖一样的结果

因为android中任何界面都可以看成是一个activity 主界面也不例外

这时候相当于主界面的activity覆盖了我们原本的activity

这时候如果再返回我们的程序 结果会像之前返回activity一样

那么什么时候OnDestroy会被调用呢 

刚刚第七条写过

(7)onDestroy方法:表示Activity即将被销毁,当收到需要将该activity彻底移除的信号时,系统会调用这个方法。 

我们这次不返回应用而是从任务管理器结束掉我们程序的进程

看看log怎么显示

android四大组件之Activity的学习(四大组件之路:一)_第7张图片

可以看见这时候OnDestroy已经被调用了

到这里 一个正常的activity生命周期已经完成了

二:异常情况下的activity生命周期

activity会在特定的操作或者异常情况下结束生命周期

1.当与资源相关的系统配置改变时(如横竖屏切换)导致activity被杀死并重新创建

当横竖屏幕切换时 activity会被杀死 经过上文分析 这时候将依次调用onPause,onStop,onDestroy。

因为activity是在异常情况下被关闭的系统还将调用onSavedInstanceState来保存当前Activity的状态(正常情况下不会调用此方法),这个方法的调用时机是在onStop之前,当Activity重新被创建后,系统调用会调用OnrestoreInstanceState并且把Activity销毁时onSavedInstanceState方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法,onRestoreInstanceState是在onStart之后调用。

2.资源内存不足导致低优先级的Activity被杀死 
Activity按照优先级我们可以分为以下的三种: 
a.前台Activity—正在和用户交互的Activity,优先级最高。 
b.可见但非前台Activity,如处于onPause状态的Activity,Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和用户直接交互。 
c.后台Activity—已经被暂停的Activity,比如执行了onStop方法,优先级最低。 

当系统内存不足时,系统就会按照上述的优先级顺序选择杀死Activity所在的进程,并在后续通过onSaveInstanceState缓存数据和onRestoreInstanceState恢复数据。

Activity的四种启动模式

谈到activity的四种启动方式首先要了解任务栈的概念

大家学习过数据结构都知道 栈是一种先进后出的数据结构

在一个安卓应用中通常都会有很多个activity,系统通过任务栈的方式管理这些activity

程序打开时就创建了一个任务栈, 用于存储当前程序的activity,所有的activity属于一个任务栈。 
一个任务栈包含了一个activity的集合, 去有序的选择哪一个activity和用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。 
任务栈可以移动到后台, 并且保留了每一个activity的状态. 并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息。 
退出应用程序时:当把所有的任务栈中所有的activity清除出栈时,任务栈会被销毁,程序退出。

activity的启动模式

1.可以在AndroidMenifest中设置

    <activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/>

2.

通过Intent的addFlags方法设置。

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

第二种方式的优先级比第一种方式高

但第二种方式无法设置singleInstance启动模式。

而activity的四种启动模式分别为

standard(标准模式) 

singleTop(栈顶复用模式)

singleTask(栈内复用模式)

singleInstance(单实例模式)

下面说一下我对这四种模式的理解

1.standard(标准模式) 

如果没有在清单文件中设置启动模式,那么就会以这种模式启动activity,大部分情况都是使用这种模式启动一个activity。这种模式下打开一个activity(不管这个activity是否已经被打开)这个activity就会被加入到任务栈中,作为任务栈的栈顶元素。

例如:一个activity中有一个按钮,点击按钮将启动这个activity本身,如果点击四次,那么任务栈中就会有四个activity。这时如果想退出到主界面。就要按四次回退才能回到主界面。也就是每次回退操作对应任务栈中的一次出栈。

应用

2.singleTop(栈顶复用模式)

singleTop的启动方式和standard非常相似。由名称可以看出来如果下一次打开的activity与当前栈顶的activity相同。那么任务栈中的元素不会增加,而是复用栈顶的activity。

例如:一个activity中有两个按钮,点击按钮1将启动这个activity本,点击按钮2将启动activity2。这时点击按钮1,在新页面中点击按钮1。再在新页面中点击按钮2。按照standard模式中任务栈中自顶向下应该是activity2,activity1,activity1。但在singleTop启动模式中,任务栈中自顶向下应该是activity2,activity1。因为第二次点击按钮1时栈顶元素就是activity本身,所以直接复用。不在将activity1加入任务栈。


3.singletask(栈内复用模式)

singleTask模式的activity在同一个任务栈内只有一个实例。如果activity已经位于栈顶,系统不会创建新的activity实例,和singleTop模式一样。但activity已经存在但不位于栈顶时,系统就会把把它上面的activity出栈,这样这个activity就成为了新的栈顶。

4.singleInstance(单实例模式)

这是一种加强的singleTask模式,除了具有singleTask的特点外还加了一点,具体此模式的Activity会单独位于一个独立的任务栈,如ActivityA为singleInstance启动模式,当A启动后,系统会单独为其建一个任务栈,A将独自位于这个任务栈中,以后的请求均不会创建新的Activity直至这个任务栈被销毁.






你可能感兴趣的:(android学习)