Android之Activity

Activity

  1. Activity的启动和结束
  2. Activity的生命周期
  3. Activity的启动模式
  4. Intent(意图)
  5. Activity的数据发送和返回

Activity的启动和结束

  • 从当前页面跳转到新页面,要用到startActivity方法
    方法里要传入意图(Intent)对象, 代码如下
startActivity(new Intent(源页面.this, 目标页面.class));
  • 从当前页面回到上一页面,相当于关闭当前页面,代码如下
finish();

Activity 生命周期

  • Activity 类提供六个核心回调:
    onCreate()、onStart()、onResume()、onPause()、onStop() 和 onDestroy()

安卓官网生命周期简化图
在这里插入图片描述

简化图的简单说明

1.一个Activity被启动时,顺次执行 onCreate() 、onStart() 、onResume(),这个Activity从创建,到可见状态,最后到启动状态
2.当跳转到另一个Activity时,进入onPause()状态,此时已经是不可见状态,之后执行onStop()
3.当点按返回,会执行onRestart(),onStart() 、onResume(),再度变成可见状态
4.当从这个Activity退出,回到系统主页面时,会执行onPause() 、onStop() 、onDestroy() 、整个Activity被销毁
5.如果点跳转之后又立刻点击返回,那么就会出现上面的现象,onPause() 之后没有执行onStop() 、直接回到onResume(),我们说onStop() 是在页面完全消失后执行,那也就是说,因为快速的切换点击,页面还没有完全消失,就从onPause() 立刻回到了onResume()
6.当前应用已经退到后台,也就是执行完了onStop(),但还没有执行onDestroy() ,手机在运行着其他占用内存的应用,此时系统会为了有更大的内从空间,系统会杀掉onPause() ,onStop()状态的Activity

方法状态说明
onCreate创建活动把页面布局加载进内存,进入初始状态
onStart开始活动把活动页面显示在屏幕上,进入了就绪状态
onResume恢复活动活动页面进入活跃状态,能够与用户正常交互,例如允许响应用户的点击动作,允许用户输入文字等等
onPause暂停活动页面进入暂停状态,无法与用户正常交互
onStop停止活动页面将不在屏幕上显示
onDestroy毁灭活动回收活动占用的系统资源,把页面从内存中清除
onRestart重启活动重新加载内存中的页面数据

当一个Activity启动时,顺次执行 onCreate() 、onStart() 、onResume()
当一个Activity关闭时,顺次执行 onPasue() 、onStop() 、onDestroy()

  • 状态切换
onCreate
onStart
onResume
onPause
onStop
onDestroy
不存在
初始状态
就绪状态
活跃状态
约定俗称的操作

在onCreate() 里做findViewById
在onDestroy() 里关闭网络连接,释放资源
在onResume() 里开启画面
在onPasue() 里关闭画面

Activity的启动模式

如果Activity已经启动过,并且在当前应用的Activity任务栈中,

  • 默认启动模式 standard
  • 栈顶复用模式 singleTask
  • 栈顶复用模式 singleTop
  • 全局唯一模式 singleInstance

1.在配置文件中指定启动模式
打开AndroidMainfest.xml, 给activity节点添加属性 android:launchMode,属性值填入standard表示采取标准模式,当然不添加属性的话默认就是标准模式。具体的activity节点配置内容如下:

<activity android:name=".MainActivity" android:launchMode="standard"/>

其中launchMode属性的几种取值说明

Intent类的启动标志说明
Intent.FLAG_ACTIVITY_NEW_TASK开辟一个新的任务栈,该值类似于 launchMode=“standard” ,不同之处在于,如果原来不存在活动栈,则FLAG_ACTIVITY_NEW_TASK会创建一个新栈
Intent.FLAG_ACTIVITY_SINGLE_TOP当栈顶为待跳转的活动实例时,则重用栈顶的实例,该值等同于launchMode=“singleTop”
Intent.FLAG_ACTIVITY_CLEAR_TOP当栈中存在待跳转的活动实例时,则重新创建一个新的实例,并清除原实例上方的所有实例,该值与launchMode="singleTask"类似,但singleTask采取onNewIntent方法启动原任务,而FLAG_ACTIVITY_CLEAR_TOP采用先调用onDestroy在调用onCreate来创建新任务
Intent.FLAG_ACTIVITY_NO_HISTORY该标志于 launchMode=“standard” 情况类似,但栈中不保存新启动的活动实例,这样下次无论以何种方式在启动该实例,也要走standard模式的完整流程
Intent.FLAG_ACTIVITY_CLEAR_TASK该标志非常暴力,跳转到新页面时,栈中的原有实例都被清空,并要注意,该标志需要结合FLAG_ACTIVITY_NEW_TASK 使用,即setFlags方法的参数为"FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK"
默认启动模式 standard

最常规的模式,先进后出,后进先出

栈顶复用模式 singleTask

与singleTop模式相似,只不过singleTop模式是只针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则将task内的对应Activity实例之上的所有Activity弹出栈,并将对应Activity置于栈顶,获得焦点。

应用场景

程序的主界面:通常主界面不需要被创建多次
耗费系统资源的Activity:对于一些会很耗费资源的Activity,可以考虑设置成singleTask

栈顶复用模式 singleTop
全局唯一模式 singleInstance

在该模式下,会为目标Activity创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点,新的Task有且只有这一个Activity实例,如果已经创建过目标Activity实例,则不会创建新的Task,而是将之前创建过的Activity唤醒。


Intent(意图)

Intent是Android各个组件之间信息通信的桥梁,主要完成下面工作

  • 标明本次通信请求从哪里来,到哪里去,要怎么走
  • 发起方携带本次通信需要的数据内容,接收方从收到的意图里解析数据
  • 发起方若想判断接收方的处理结果,意图就要负责让接收方返回结果数据

Intent的组成部分

元素名称设置方法说明与用途
ComponentsetComponent组件,它指定意图的来源和目标
ActionsetAction动作,它指定意图的动作行为
DatasetData即Uri,它指定动作要操纵的数据路径
CategoryaddCategory类别,它指定意图的操作类别
TypesetType数据类型,它指定消息的数据类型
ExtrasputExtras扩展信息,它指定装载的包裹信息
FlagssetFlags标志位,它指定活动的启动标志
1.显式Intent,直接指定来源活动与目标活动,属于精确匹配。它有三种构建方式:
  • 在Intent的构造函数中指定
  • 调用意图对象的setClass方法指定
  • 调用意图对象的setComponent方法指定

在构建一个意图对象时,需要指定两个参数,第一个参数表示跳转的源页面 源Activity.this
第二个参数表示待跳转的页面 目标Activity.class,具体的意图构建方式有如下3种:

(1) 在Intent的构造函数中指定

Intent intent = new Intent(this, nextActivity.class);

(2) 调用意图对象的setClass方法指定

Intent intent = new Intent();
intent.setClass(this, nextActivity.class);

(3) 调用意图对象的setComponent方法指定

Intent intent = new Intent();
ComponentName component = new ComponentName(this, nextActivity.class);
intent.setComponent(component);
2.隐式Intent,没有明确指定要跳转的目标活动,只给出一个动作字符串让系统自动匹配,属于模糊匹配

通常App不希望向外部暴露活动名称,只给出一个事先定义好的标记字符串,约定俗成的按图索骥,隐式Intent便起到了标记过滤作用,这个动词名称字符串可以是自己定义的动作,也可以是已有的系统动作,常见系统动作的取值说明表

Intent类的系统动作常量名系统动作常量值说明
ACTION_MAINandroid.intent.action.MAINAPP启动时的入口
ACTION_VIEWandroid.intent.action.VIEW向用户显示数据
ACTION_SENDandroid.intent.action.SEND分享内容
ACTION_CALLandroid.intent.action.CALL直接拨号
ACTION_DIALandroid.intent.action.DIAL准备拨号
ACTION_SENDTOandroid.intent.action.SENDTO发送短信
ACTION_ANSWERandroid.intent.action.ANSWER接听电话

动作名称即可以通过setAction方法指定,也可以通过构造函数Intent(String action)直接生成意图对象,但由于是模糊匹配有局限,当想指定更详细的信息时,可以用Uri和Category来制定,
Uri数据可通过构造函数Intent(String action, Uri uri)在生成对象时一起指定,也可以通过setData方法指定(setData这个名字有歧义,实际相当于setUri),Category可通过addCategory方法指定,之所以用add而不用set方法,是因为一个意图允许同时设置多个Category,方便一起过滤


Activity的数据发送和返回

给下一个Activity发送数据

Intent使用Bundle对象存放待传递的数据信息
Bundle对象操作各类型数据的读写方法

数据类型读方法写方法
整型getIntputInt
浮点型getFloatputFloat
双精度型getDoubleputDouble
布尔型getBooleanputBoolean
字符串getStringputString
字符串数组getStringArrayputStringArray
字符串列表getStringArrayListputStringArrayList
可序列化结构getSerializableputSerializable
public class MainActivity2 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        TextView textView = findViewById(androidx.core.R.id.text);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建意图
                Intent intent = new Intent(MainActivity2.this, MainActivity.class);
                //创建Bundle用于绑定要传递的数据
                Bundle bundle = new Bundle();
                bundle.putString("name","Tom");
                bundle.putString("age","10");
                //把绑定好数据的Bundle传递给意图
                intent.putExtras(bundle);
                //调转画面
                startActivities(intent);
            }
        });
    }
}

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        TextView textView = findViewById(androidx.core.R.id.text);
        //接收上个画面传过来的数据
        Bundle bundle = getIntent().getExtras();
        String name = bundle.getString("name");
        String age = bundle.getString("age");
        textView.setText(name + age);
    }
}
给上一个Activity返回数据
  • 上一个页面打包好请求数据,调用startActivityForResult方法执行跳转动作
  • 下一个页面接收并解析请求数据,进行相应处理
  • 下一个页面在返回上一个页面时,打包应答数据并调用setResult方法返回数据包裹
  • 上一个页面重写方法onActivityResult,解析获得下一个页面的返回数据
public class ResActivity extends AppCompatActivity implements View.OnClickListener {

    private ActivityResultLauncher<Intent> register;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_res);
        TextView textView = findViewById(R.id.t_request);
        textView.setText("ABCDE");
        findViewById(R.id.btn_res).setOnClickListener(this);
        TextView textView1 = findViewById(R.id.t_response);
        textView1.setText("1234");

        register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {

                if (result != null){
                    Intent intent = result.getData();
                    if (intent != null && result.getResultCode() == Activity.RESULT_OK){
                        Bundle bundle = intent.getExtras();
                        String msg = bundle.getString("Message");
                        textView1.setText(msg);
                    }
                }
            }
        });
    }

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, ResponseActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("name", "Tom");
        bundle.putString("age", "int");
        intent.putExtras(bundle);
        //已过时的方法
        //startActivityForResult();
        register.launch(intent);
    }
}
public class ResponseActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_response);
        TextView textView = findViewById(R.id.t_request);
        Bundle bundle = getIntent().getExtras();
        String name = bundle.getString("name");
        String age = bundle.getString("age");
        textView.setText("" + name + age);
        findViewById(R.id.btn_response).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        Intent intent = new Intent();
        Bundle bundle = new Bundle();
        bundle.putString("Message", "this is test");
        intent.putExtras(bundle);
        //结果返回
        setResult(Activity.RESULT_OK, intent);
        finish();
    }
}
如何在在Activity里利用strings.xml的字符串

利用上文对象Context里的getString方法,因为Activity本身已经继承了Context类,
所以可以直接用他的getString方法

String name = getString(R.string.name);
代码中获取元数据

获取元数据信息有三步

  • 调用getPackageManager方法获得当前应用的包管理器
  • 调用包管理器的getActivityInfo方法获得当前Activity的信息对象
  • 活动信息对象的metaData是Bundle包裹类型,调用包裹对象的getString方法,获取指定的值

AndroidManifest.xml

<activity
   android:name=".ResActivity"
   android:exported="true"
   android:theme="@style/Theme.MyApplication.NoActionBar">
   <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
   <meta-data android:name="name" android:value="tom"/>  
</activity>

Activity.java

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_res);
        TextView textView = findViewById(R.id.t_request);
        //获取应用包管理器
        PackageManager packageManager = getPackageManager();
        try {
            //从应用包管理器中获取当前活动信息
            ActivityInfo activityInfo = packageManager.getActivityInfo(getComponentName(), packageManager.GET_META_DATA);
            //从活动信息里取得metaData
            Bundle metaData = activityInfo.metaData;
            //从Bundle获取内部信息
            String name = metaData.getString("name");
            textView.setText(name);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值