安卓开发——活动的生命周期_安卓开发活动周期-程序员宅基地

技术标签: android  第二行代码  

只有懂生命周期的程序员才能开发出流畅的应用。

一、返回栈

Android 中的活动是可以层叠的,每启动一个新的活动,就会覆盖在原活动之上。当BACK掉最上层的活动,下面的活动才会显示出来。
Android 用 任务 Task 管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈称为返回栈Back Stack
栈是后进后出的数据结构。

二、活动的状态

一句两句解释不清楚,后面实战时再看

  • 运行态
  • 暂停态
  • 停止态
  • 销毁态

三、活动的生存期

Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节:

  • onCreate()在第一次被创建时调用,通常用于完成初始化操作,比如加载布局和绑定事件
  • onStart()活动在不可见变为可见时调用
  • onResume()在活动准备交互时调用,此时活动一定在返回栈的栈顶,并且处于运行态
  • onPause()在系统准备启动或恢复另一个活动时调用。通常用于将消耗CPU的资源释放掉,以及保存一些关键数据。此方法执行一定要快,不然影响新的栈顶活动的使用
  • onStop()在活动完全不可见时调用。如果启动的活动是一个对话框式的活动,那么onPause()会执行,onStop()不会执行
  • onDestroy()在活动被销毁前调用,之后活动的状态将变为销毁态
  • onRestart()在活动由停止态变为运行态之前调用,也就是活动的重启

以上七个方法,除了onRestart(),其他都是凉凉相对的,从而可以将活动分为3种生存期:

  • 完整生存期:从onCreate()onDestroy()。也就是从初始化到释放内存
  • 可见生存期:从onStart()onStop(),活动对用户来说是可见的,即使无法进行交互。也就是资源加载到资源释放
  • 前台生存期:从onResume()onPause(),此时的或从都是运行态,可以交互的。平时使用和看到的也是这个状态的活动

在这里插入图片描述

四、体验活动的生命周期

1、新建项目

新建一个Android项目,并添加两个子活动NormorActivityDialogActivity及其布局
在这里插入图片描述
在这里插入图片描述

2、修改次活动布局

修改 NormalActivity的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a normal activity"
        />

</LinearLayout>

修改DialogActivity的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a dialog activity"
        />

</LinearLayout>

3、添加次活动主题

修改A-M配置种DialogActivity的配置,添加对话框主题:

<activity android:name=".DialogActivity" 
	android:theme = "@style/Theme.AppCompat.Dialog">
</activity>

4、修改主活动布局

修改activity_main的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/start_normal_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="启动NormalActivity"/>
    
    <Button
        android:id="@+id/start_dialog_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="启动DialogActivity"/>

</LinearLayout>

5、修改主活动运行方案

最后修改Main_activity.java:

public class MainActivity extends AppCompatActivity {
    

    private static final String TAG = "MainActivity";

    @Override
    protected void onRestart() {
    
        super.onRestart();
        Log.d(TAG, "onRestart: 停止态变为运行态");
    }

    @Override
    protected void onDestroy() {
    
        super.onDestroy();
        Log.d(TAG, "onDestroy: 活动销毁前");
    }

    @Override
    protected void onStop() {
    
        super.onStop();
        Log.d(TAG, "onStop: 活动完全不可见");
    }

    @Override
    protected void onPause() {
    
        super.onPause();
        Log.d(TAG, "onPause: 准备启动或恢复另一个活动");
    }

    @Override
    protected void onResume() {
    
        super.onResume();
        Log.d(TAG, "onResume: 准备交互");
    }

    @Override
    protected void onStart() {
    
        super.onStart();
        Log.d(TAG, "onStart: 不可见变为可见");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG, "onCreate: 第一次被创建");
        Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
        Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
        startNormalActivity.setOnClickListener(new View.OnClickListener() {
    
            @Override
            public void onClick(View v) {
    
                Intent intent = new Intent(MainActivity.this, NormalActivity.class);
                startActivity(intent);
            }
        });
        startDialogActivity.setOnClickListener(new View.OnClickListener() {
    
            @Override
            public void onClick(View v) {
    
                Intent intent  = new Intent(MainActivity.this, DialogActivity.class);
                startActivity(intent);
            }
        });
    }
}

6、运行并打印日志

(1)启动app

在这里插入图片描述

  • onCreate:第一次被创建
  • onStart:不可见变为可见
  • onResume:准备交互
(2) 启动NormalActivity

NormalActivity 使得 MainActivity完全不可见:
在这里插入图片描述
发现主活动先暂停(onPause()),然后停止(onStop())

  • onPause:准备启动或恢复另一个活动
  • onStop:活动完全不可见
(3)返回MainActivity

在这里插入图片描述
注意此时onCreate()并未执行,因为这不属于重新创建

  • onRestart: 停止态变为运行态
  • onStart: 不可见变为可见
  • onResume: 准备交互
(4)启动DialogActivity

在这里插入图片描述
这次只输出了一行:
onPause: 准备启动或恢复另一个活动
因为没有完全遮挡,所以onStop()并未执行,同样的:

(5)继续MainActivity

也就只有onResume()执行
在这里插入图片描述
onResume: 准备交互

五、活动被回收了怎么办

当活动进入停止态,即执行了onStop(),是可能被系统回收的。回收了之后,如果BACK到之前的活动,系统就会重新onCreate()->onStart()->onResume(),而不是onRestart()->onStart()->onResume()

如果真的系统真的onCreate()了,那么原活动的临时数据就会丢失!

所以Activity又提供了一个onSaveInstanceState()的回调方法来解决临时数据得不到保存的问题。

onSaveInstanceState()会携带一个Bundle类型的参数,Bundle提供了一系列的方法保存数据,比如putString()putInt()等,其第一个参数是键值,第二个参数是数据。

比如MainActivity要保存数据,可以重写这个:

@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
    
    super.onSaveInstanceState(outState, outPersistentState);
    String tempData = "这里是你刚刚输入的数据";
    outState.putString("key", tempData);
}

取值的之后直接从onCreate()中的Bundle取值

protected void onCreate(Bundle savedInstanceState) {
    
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
  
	if (savedInstanceState!=null){
    
		String tempData = savedInstanceState.getString("key");
		Log.d(TAG, tempData);
	}
	...
}

TIPS:Bundle可以结合Intent传递数据,先将数据放到Bundle,再将Bundle对象放到Intent中,取数据也是一样。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41205771/article/details/103879626

智能推荐

手把手教你安装Eclipse最新版本的详细教程 (非常详细,非常实用)_eclipse安装教程-程序员宅基地

文章浏览阅读4.4k次,点赞2次,收藏16次。写这篇文章的由来是因为后边要用这个工具,但是由于某些原因有部分小伙伴和童鞋们可能不会安装此工具,为了方便小伙伴们和童鞋们的后续学习和不打击他们的积极性,因为80%的人都是死在工具的安装这第一道门槛上,这门槛说高也不高说低也不是太低。所以就抽时间水了这一篇文章。_eclipse安装教程

分享11个web前端开发实战项目案例+源码_前端项目实战案例-程序员宅基地

文章浏览阅读4.1w次,点赞12次,收藏193次。小编为大家收集了11个web前端开发,大企业实战项目案例+5W行源码!拿走玩去吧!1)小米官网项目描述:首先选择小米官网为第一个实战案例,是因为刚开始入门,有个参考点,另外站点比较偏向目前的卡片式设计,实现常见效果。目的为学者练习编写小米官网,熟悉div+css布局。学习资料的话可以加下web前端开发学习裙:600加上610再加上151自己去群里下载下。项目技术:HTML+CSS+Div布局2)迅雷官网项目描述:此站点特效较多,所以通过练习编写次站点,学生可以更多练习CSS3的新特性过渡与动画的实_前端项目实战案例

计算质数-埃里克森筛法(间隔黄金武器)-程序员宅基地

文章浏览阅读73次。素数,不同的质数,各种各样的问题总是遇到的素数。以下我们来说一下求素数的一种比較有效的算法。就是筛法。由于这个要求得1-n区间的素数仅仅须要O(nloglogn)的时间复杂度。以下来说一下它的思路。思路:如今又1-n的数字。素数嘛就是除了1和本身之外没有其它的约数。所以有约数的都不是素数。我们从2開始往后遍历,是2的倍数的都不是素数。所以我们把他们划掉然后如...

探索Keras DCGAN:深度学习中的创新图像生成-程序员宅基地

文章浏览阅读532次,点赞9次,收藏14次。探索Keras DCGAN:深度学习中的创新图像生成项目地址:https://gitcode.com/jacobgil/keras-dcgan在数据驱动的时代,图像生成模型已经成为人工智能的一个重要领域。其中,Keras DCGAN 是一个基于 Keras 的实现,用于构建和训练 Deep Convolutional Generative Adversarial Networks(深度卷积生...

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):_spring-could org.apache.ibatis.binding.bindingexce-程序员宅基地

文章浏览阅读116次。今天在搭建springcloud项目时,发现如上错误,顺便整理一下这个异常:1. mapper.xml的命名空间(namespace)是否跟mapper的接口路径一致<mapper namespace="com.baicun.springcloudprovider.mapper.SysUserMapper">2.mapper.xml接口名是否和mapper.java接..._spring-could org.apache.ibatis.binding.bindingexception: invalid bound state

四种高效数据库设计思想——提高查询效率_数据库为什么能提高效率-程序员宅基地

文章浏览阅读1.1k次。四种高效数据库设计思想——提高查询效率:设计数据库表结构时,我们首先要按照数据库的三大范式进行建立数据。1. 1NF每列不可拆分2. 2NF确保每个表只做一件事情3. 3NF满足2NF,消除表中的依赖传递。三大范式的出现是在上世纪70年代,由于内存资源比较昂贵,所以严格按照三大范式进行数据库设计。而如今内存变得越来越廉价,在考虑效率和内存的基础上我们可以做出最优选择以达到最高效率。_数据库为什么能提高效率

随便推点

什么是配置_基于配置是什么意思-程序员宅基地

文章浏览阅读1.6k次。应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数 据库连接参数、启动参数等。配置主要有以下几个特点:配置是独立于程序的只读变量配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置配置伴随应用的整个生命周期配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。比如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。配置可以有多种加载方式常见的有程序内部_基于配置是什么意思

二、使用GObject——一个简单类的实现-程序员宅基地

文章浏览阅读170次。Glib库实现了一个非常重要的基础类--GObject,这个类中封装了许多我们在定义和实现类时经常用到的机制: 引用计数式的内存管理 对象的构造与析构 通用的属性(Property)机制 Signal的简单使用方式 很多使用GObject..._

golang 定时任务处理-程序员宅基地

文章浏览阅读6.3k次,点赞2次,收藏9次。在 golang 中若写定时脚本,有两种实现。一、基于原生语法组装func DocSyncTaskCronJob() { ticker := time.NewTicker(time.Minute * 5) // 每分钟执行一次 for range ticker.C { ProcTask() }}func ProcTask() { log.Println("hello world")}二、基于 github 中封装的 cron 库实现package taskimport (_golang 定时任务

VC获取精确时间的方法_vc 通过线程和 sleep 获取精准时间-程序员宅基地

文章浏览阅读2.1k次。 来源:http://blog.csdn.net/clever101/archive/2008/10/18/3096049.aspx 声明:本文章是我整合网上的资料而成的,其中的大部分文字不是我所为的,我所起的作用只是归纳整理并添加我的一些看法。非常感谢引用到的文字的作者的辛勤劳动,所参考的文献在文章最后我已一一列出。 对关注性能的程序开发人员而言,一个好的计时部件既是益友,也_vc 通过线程和 sleep 获取精准时间

wml入门-程序员宅基地

文章浏览阅读58次。公司突然说要进行wap开发了,以前从没了解过,但我却异常的兴奋,因为可以学习新东西了,呵呵,我们大家一起努力吧。首先说说环境的搭建。可以把.wml的文件看做是另一种的html进行信息的展示,但并不是所有的浏览器都支持,好用的有Opera,还有WinWap。编写wml文件语法比较严格,不好的是我还没有找到好的提示工具,就先用纯文本吧。我找到了一个很好的学习网站:http://w3sc..._winwap学习

计算机考研怎么给老师发邮件,考研复试前,手把手教你怎么给导师发邮件!4点要注意...-程序员宅基地

文章浏览阅读504次。考研成绩出来后,第一件事是干什么?当然不只是高兴,而是马上给心仪的导师发邮件,先露个“名字熟”。不要以为初试考了高分或者过线了,一切都稳妥了,一时得意忘形,居然没联系导师,等想起时,导师已经属于他人了。对于一些大佬,热门导师一定要趁早发邮件咨询,一是表示尊重;二是这类老师可能已经没有统招名额,所以越早知道,越有利于下一步计划。但是,在给导师发邮件中,要注意以下4点,不求一步成功,但求先留下个好印象..._跨考计算机怎么给导师发邮件