Activity生命周期及页面跳转(Intent)、数据传递

Activity

用户与程序的交互是通过Activity完成的,Activity负责管理Android应用程序的登陆界面。

1. Activity 的创建

在程序包处单击右键,选择New → Activity → Empty Activity

后会弹出Customize the Activity界面

  • Activity Name :用于输入Activity名称。
  • Layout Name:用输入布局名称。
  • Launcher Activity :复选框用于设置当前Activity是否为默认启动界面,通常情况下不勾选。
  • Package name :表示包名,默认即可。
  • Target Source set 表示目标源集,默认即可。
  • 点击Finish

创建的文件代码如下

package top.codebooks.meizu;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class Activity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_);
    }
}

创建的Activuty 继承自 AppCompatActivity 并重写了该类的 onCreate() 方法,该方法时在Activity创建时调用,因此通常存放一些控件的初始化代码。

在Android中,创建四大组件都需要在manifests/AndroidManifest.xml文件(清单文件)中注册,当Activity在清单文件中注册时,会添加一行<activity android:name="ActivityName"></activity> 代码。Android studio 高级IDE在创建Activity时会自动注册,当然如果在创建时进选择的是java类继承自AppCompatActivity,并需要在manifests/AndroidManifest.xml添加<activity android:name="ActivityName"></activity>

2. Activaty 的生命周期

Activity 的生命周期中包含了5中状态,涉及了7种方法.生命周期指的是一个Activity从创建到销毁的全过程。

(1)生命周期的五个状态:
  • 启动状态:启动状态很短,启动后便会进入运行状态。
  • 运行状态:Activity在运行状态时处于屏幕的最前端,它是可见的有焦点的,可以与用户进行交互。当Activity处于运行状态时,Android会尽可能地保持它的运行,即使出现内存不足时,Android也会先销毁栈底的Activity来确保当前的Activity正常运行。
  • 暂停状态:某些情况下,Activity对用户来说仍然可见,但它无法获得焦点。对用户的操作也没有响应此时它就处于暂停状态。例如当前Activity被覆盖了一个透明或者非全屏的Activity时,被覆盖的Activity就处于暂停状态。
  • 停止状态:Activaty完全不可见时,他就处于停止状态,但仍保留着当前状态的和成员的信息,如果系统内存资源不足,那么这类状态很容易被销毁。
  • 销毁状态:当Activity位于此状态时,Activity会被清理出内存。

Android生命周期模型

在这里插入图片描述

一个Activity 从启动到关闭,会依次执行onCreate() → onStart() → onResume() → onPause() → onStop() → onDestroy() 方法。当Activity执行到 onPause方法时Activity失去焦点后会到前台会执行onTrsume() 方法。如果此时进程被销毁。Activity会重新执行onCreate()方法。当执行到onStop()方法Activity不可见时再次会到前台会执行onRestart() 方法如果此时进程被销毁,会执行onCreate()方法。

(2)生命周期的七个方法
  • onCreate() :在Avtivity创建时调用,通常做一些初始化的工作。
  • onStart():在Avtivity即将可见时调用。
  • onResume():在Actuvity获得焦点开始与用户交互式调用。
  • onPause():当前Avtivity被其他Activity覆盖或锁屏时调用。
  • onStop(): 在Activity对用户不可见时调用。
  • onRestart():在Activity从停止状态再次启动时调用。
  • onDestroy():在Activity销毁时调用。
// 调试时在logcat输出控制信息
package top.codebooks.meizu;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity{
    String TAG = "myTag";

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG,"onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart: ");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart: ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy: ");
    }
}

程序中只有一个Activity时无法进行返回操作,当程序中有多个Activity进行切换时就可以进行切换操作,也就可以看到onRestart() 方法执行。

  • 横竖屏切换时的细节

默认属性下,Avtivity的生命周期会依次调用 onCreate() → onStart() → onResume()方法,而进行横竖屏切换后调用的方法依次是onPause() → onStop() → onDestroy() → onCreate() → onStart() → onResume() ,所以我们可以在此生命周期内进行横竖屏切换时会首先销毁Activity,之后再重建Activity这种模式在开发中会有一定的影响。如果不希望在横竖屏切换时Activity被销毁重建,可以通过configChanges属性进行设置。这样无论怎样切换Ativity都不会被销毁重建。在manifests/AndroidManifest(清单文件)中修改。

<activity android:name=".MainActivity"
          android:configChanges="orientation|keyboardHidden|screenSize">

如果希望某一界面一直处于竖屏或则横屏状态不随手机的晃动而改变同样可以在清单文件中通过设置Activity的参数来完成

竖屏:android:screenOrientation="portrait"
横屏:android:screenOrientation="landscape"

3.Activity的启动模式

Activity是层叠摆放的,每启动一个新的Activity就会覆盖到原Activity之上。如果单击“返回”按钮,最上面的Activity就会被销毁。下面的Activity重新显示,Activity之所以能这样显示,是因为Android系统是通过任务栈方式来管理Activity实例的。

(1)Android中的任务栈

栈是一种先进后出的数据结构,Android任务栈又被称为返回栈,栈中Activity的顺序就是按照他们打开的顺序依次存放的。

通常一个应用程序对应一个任务栈。默认情况下每一个启动的Activity都会入栈并位于栈顶位置。用户操作的永远都是栈顶的Activity在栈中的Activity只有入栈和出栈两种操作。被当前Activity启动时压入,用户单击返回按钮时出栈,而栈中的Activity的位置和循序都不会发生变化。

(2)Activity的四种启动模式

在实际开发中,应根据特定的需求为每个Activity指定适当的启动模式,Activity的启动模式共有4种。分别是standard、singleTop、singleTask、和singleInstance。在清单文件AndroidManifest中通过<activity>标签的android:launchModo 属性可以设置启动模式。

  • standard (标准启动)模式

    Activity的默认启动模式,每启动一个Activity就会在栈顶创建一个新的实例,在实际开发中,闹钟程序通常使用这种模式。

在这里插入图片描述
启动时创建的Aty1_1位于栈底,后创建的实例会堆放到栈顶, 当点返回键的时候,便会从栈顶按顺序将实例移除栈。直至栈为空则退回到桌面。

  • singleTop

    在standard模式下每次启动都会创建一个新的实例,即使当前要创建的Activity已经位于栈顶,不能直接复用,这样并不合理。所以提出了singleTop模式,

    该模式要判断启动的Aativity实例是否位于栈顶,如果位于栈顶则直接复用。否则创建新的实例。

    • 如果此时Aty1的实例在栈顶,此时再创建一个新的Aty1并不会成功。

在这里插入图片描述

  • 如果Aty_1不在栈顶,此时再创建一个Aty1的实例,会产生一个新的Aty1实例到栈顶。

在这里插入图片描述
当点返回键的时候,便会从栈顶按顺序将实例移除栈。直至栈为空则退回到桌面。

  • singleTask

    singleTask很好的解决的重复创建栈顶的问题,但是如果Activity没有处于栈顶的位置,则很有可能会创建多个实例,为了让某个Activity在整个应用程序中只有一个实例,则需要借助singleTask来完成。

    Activity指定singleTask模式后,每次启动该Activity时,系统会先查找栈中是否存在当前的Activity如果存在则直接使用并将该Activity之上的所有实例全部出栈。否则才会创建一个新的实例。实力开发时浏览器主界面通常使用这种模式。

    如果此时Aty1的实例在栈顶,此时再创建一个新的Aty1并不会成功。
    在这里插入图片描述
    如果Aty_1不在栈顶,此时再创建一个Aty1的实例,页面会返回到任务栈中存在的Aty1的实例,并将Aty1上面所有的实例移出栈。
    在这里插入图片描述
    当点返回键的时候,便会从栈顶按顺序将实例移除栈。直至栈为空则退回到桌面

  • singleInstance

    singleInstance模式时四种启动模式中最特殊的一个,指定为singleInstance模式的Activity会启动一个新任务栈来管理Activity实例,无论从哪个任务栈启动该Activity,带实力在整个Android系统中只有一个,这种模式存在的意义,是为了在不同的程序之间共享一个Activity实例。

    Activity采用singleInstance模式启动通常有两种情况

    • 要启动的Activity不存在

      系统会新创建一个任务栈,然后在创建该Activity实例。

      此时Aty2的实例还未被创建,创建的Aty2的实例时被存放到一个新的任务栈中。

在这里插入图片描述

  • 启动的Activity已存在

    无论当前Activity在那个程序那个任务栈,系统都会把Activity所在的任务栈移动到前台,从而使Activity显示。来电界面通常采用这种模式。

    此时Aty1的实例在栈顶,此时再创建一个新的Aty1并不会成功。

在这里插入图片描述
此时Aty1的实例已存在且我们在Aty2的页面中创建新的Aty1实例时,则不会创建新的Aty1实例,而是页面跳转到原来任务栈中存在的Aty1的实例,但存放Aty2实例的任务栈仍然存在
在这里插入图片描述
当点返回键的时候,便会依次销毁相应的任务栈,直至任务栈数为空则退回到系统桌面。

4. Activity之间的跳转

在Android系统里,应用程序通常都是由多个界面组成的,每一个界面就是一个Activity,在这些界面之间进行跳转时,实际上也就是Activity之间的跳转。Activity之间的跳转需要用到Intent(意图)组件,通过Intent可以开启新的Activity实现界面跳转功能。

(1)Intent简介

Intent被称为意图,是程序中各组件进行交互的一种重要方式,它不仅可以指定当前组件要执行的动作,还能再不同的组件之间进行数据的传递。一般用于启动Activity、Service以及发送个广播等。根据开启目标组件的不同,Intent被分为隐式意图和显式意图两种。

  • 显式意图

    ​显示意图可以直接通过名称来开启指定的目标组件,通过其构造方法Intent(ContextpackgeContext,Class<?>cls)来实现,其中第一个参数表示但分分钱的Activity对象,这里使用this即可。第二个参数Class表示要启动的目标Activity。通过这个方法创建一个Intent对象,然后将该对象传递给Activity的startActivity
    (Intent intent)方法即可启动目标组件。

    Intent intent = new Intent(this,Activity.class);		// 创建Intent对象
    startActivity(intent);								// 开启Activity
    
  • 隐式意图

    隐式意图比显式意图来说更为抽象。他并没有明确指明要开启那个目标组件,而是通过指定action和category等属性信息,系统根据这些信息进行分析,然后寻找目标Activity。

    Intent intent = new Intent();
    // 设置action动作,该动作要和清单文件中设置的一样。
    intent.setAction("cn.itcast.START_ACTIVITY");
    startActivity(intent);
    

    上面只是指定了action,并没有指定category,这是因为在目标Activity的清单文件中配置的category是一个默认值,在调用startActivity() 方法时自动将这个categroy添加到Intent中。

    但是,上述代码还不能开启指定的Activity还需在目标Activity的清单文件中配置<intent-filter>指定当前Activity能够响应action和category。

            <activity android:name="cn.itcast.Activity">
                <intent-filter>
                <!--设置action属性,需要在代码中所设置的name打开指定的组件-->
                    <action android:name="cn.itcast.START_ACTIVITY"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                </intent-filter>
            </activity>
    

    在清单文件中,目标组件Activity指定了可以响应的<action><categoty> 信息,只有当action 和 categoty属性与目标组件设置的内容相同时,目标组件才会被开启,注意:每个intent只能指定一个action,却能指定多个categoty。

5.Activity 中的数据传递

Intent 不仅可以来气Activity、Service、BroadcastReceiver 组件。还可以在这些组件之间传递数据。

(1)数据传递

Intent提供了一系列重载的 putExtra(String name,String values)方法。通过该方法可以将要传递的数据暂存在Intent中。当启动另一个Activity之后,只需要将这些数据从Intent取出即可。

在Activity01中的字符串数据传递到Activity02中

  • 在Activity01 将数据传递到Intent中
Intent intent = new Intentthis,Activity02.class;
intent.putExtra("ectra_data","Hello Activity02");
startActivity(intent);

putExtra();方法中有两个参数,第一个参数是键,用于后面从Intent中取值;第二个参数是传递的数据内容。

  • 在Activity02中取出传递过来的值。
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");

通过getIntent方法获取Intent对象,然后调用getStringExtra(String name)根据传入的名称获取值,若要获取其他类型的值,如数字可以用getIntExtra(String name) 方法。

(2)数据回传

Intent除了可以将数据传递给下一个Activity,还可以将数据传递给上一个Activity。例如:在微信发朋友圈时,进入图库选择好照片后,会返回到发表状态的页面并带回所选的图片信息。

Activity中有一个方法startActivityForResult(Intent intent,int requestCode)方法。该方法可以用于启动Activity,并且可以在当前Avtivity销毁时返回一个结果给上一个Activity。

  • startActivityForResult(Intent intent,int requestCode)

    参数(2个):第一个参数接收一个 Intent 对象,第二个参数时请求吗,用于判断数据的来源,输入一个唯一值即可。

在Activity01中开启Activity02

Intent intent = new Intent(this,Activity02.class);
startActivityForResult(intent,1);

在Activity02中添加返回数据的实例代码

Intent intent = new Intent();
intent.putExtra("extra_data","Hello Acyivity01");
setResult(1,intent);

在上面的代码里仍然构建了一个对象,然后调用setResult(int resultCode,Intent data)方法向上一个Activity回传数据,其中第一个参数用于处理回传的结果,一般使用0或者1,第二个参数是把带有数据的Intent传递回去。

由于在Activity01中使用了startActivityForResult(Intent intent,int requestCode)方法启动了Activity02,在Activity02被销毁后会调用Activity01的onActivityResult()方法,因此要在Activity01中重写该方法来得到返回的数据。

    protected void onActivityResule(int requestCode, int resultCode, Intent data){
        super.onActivityResult(requestCode,resultCode,data);
        if(requestCode == 1){
            if(resultCode == 1){
                String string = data.getStringExtra("extra_data");
            }
        }
    }

在Activity01中,通过onActivityResule(int requestCode, int resultCode, Intent data)方法来获取数据,该方法有三个参数。

  • int requestCode:当前Activity01启动Activity02时的请求码。
  • int resultCode:在ACtivity返回数据时的传入结果码。
  • Intent data:携带返回数据的 Intent。

注意:在一个Activity中可能会调用startActivityForResult(Intent intent,int requestCode)方法启动多个不同的Activity,每一个Activity返回的数据都会回调到onActivityResule(int requestCode, int resultCode, Intent data)这个方法中,因此首先要做的事通过检查requstCode来判断数据的来源,确定是从那个Activity返回的,然后通过resultCode的值来判断数据处理结果是否成功。最后才能从data中取出数据。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值