初识Activity

此刻,你应该静下心来,在阅读中思考,在思考中进步,读完本篇文章的你一定会有不一样的收获,请让我们共同进步,如有任何疑问请留言!

核心内容

  1. Activity本质是什么
  2. Activity生命周期
  3. Activity启动模式
  4. Activity直接的数据交互
  5. 如何启动系统的Activity
  6. Activity启动模式

Activity简介

  1. Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,ContentProvider内容提供者,BroadcastReceiver广播接收器)之一。
  2. Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务。
  3. Activity中所有操作都与用户密切相关,是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件,Activity本质可以理解为界面的载体
  4. 在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。
    注:关于Activity的更多介绍可查看官方文档其他文章详细了解…

Activity生命周期

下面的图显示了Activity 的状态转换的方法和实现,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。(简单了解)
这里写图片描述
在上图中,Activity有三个关键的循环:

  1. 整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。(例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。)

  2. 可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,(例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。)

  3. 前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,(例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。)

单个Activity生命周期

从运行到按back键退出可分为三个状态(显示状态、隐藏状态、销毁状态

1、oncreate  ——》onstart ——》onResume      显示状态

2、onPause ——》onStop     处于完全隐藏状态

3、onDestory     销毁状态

多个Activity交互时的生命周期

A Activity 打开 B Activity 时可编写两个具体的Activity实现其中的各个生命周期方法进行测试

A Activity              B Activity                

onCreate
onStart
onResume
onPause
                        onCreate
                        onStart
                        onResume
onStop

B Activity点击Back键时按back键时对当前Activity执行一个销毁操作

A Activity              B Activity                

                        onPause
onRestart
onStart
onResume
                        onStop
                        onDestroy

思考:Activity的生命周期为什么是这样的呢?在打开B Activity时为什么不可以先不执行A Activity的onPause方法而在B Activity执行完onCreate、onStart、onResume方法后在执行A Activity的onPause方法呢等等。要分析这些具体问题,就要分析整个Activity的生命周期的设计具体思路。假设我们自己是开发sdk的,那么我们在处理这种生命周期的时候需要考虑那些具体问题呢?

解答一:为什么要先暂停当前显示的Activity

假设打开一个应用在观看视频的时候,这时有人给我们打了一个电话进来就显示当前电话的一个Activity界面,这种情况下如果不先执行onPause方法暂停当前的Activity,而是在电话Activity的onResume方法后执行会出现什么问题呢?就有可能当前的电话Activity已经进来的时候视频的声音还是在响等一些问题,这样就给用户感觉很不好,所以才要这样执行当前Activity的onPause()方法。(在开发中需要做的就是在onPause方法中判断当前Activity的音频或视频是否在播放,如果播放我们就让其处于暂停状态,暂停当前Activity的一些状态信息。)

解答二:在打开新Activity的时候,为什么不先执行当前Activity的OnStop方法,而是要先执行新打开Activity的onCreate,onStart,OnResume方法再执行onStop方法

其实这就是google在设计上给我们做的一种安全保护机制,假设在打开新的Activity时出现一些异常信息有可能会crush掉(crush:因为程序或者各种原因而导致的程序意外退出、俗称“闪退”)所以就是为了保证新打开的Activity能正常显示当前的Activity才会调用onStop方法处于隐藏状态。

屏幕切换与应用场景

1、Activity的屏幕切换(横竖屏切换)

Activity的横竖屏切换对activity生命周期的影响,进行横竖屏切换时会将此activity先销毁掉,即经历onPause->onStop->onDestroy方法,然后重新执行此activity的onCreate->onStart->onResume方法,所以在再进行横竖屏切换的时需要保存Activity的相关状态使其保持在屏幕切换前后的内容一致,这里使用到的是系统提供onSaveInstanceState()方法,该方法在整个Activity销毁时用于保存当前的一些状态信息(注:onSaveInstanceState()方法的执行是在onPause()方法后。),信息保存在系统的Bundle对象中,在Activity重新创建时就可以把保存的数据取出来。(具体操作看如下示例:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i("TAG","MainActivity onSaveInstanceState");
        super.onSaveInstanceState(outState);
        outState.putString("name", "nate");
    }

然后在onCreate()方法中判断saveInstanceState值是否为空来取出相应的信息

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(savedInstanceState!=null){
            savedInstanceState.get("name");
        }
    }

对于这种什么周期的切换时都是通过onSaveInstanceState()方法保存相关的状态信息,如果想取出这个信息时就要在onCreate()方法中判断savedInstanceState不等于空根据不同的key值去取出相应的value。在实际的情况下一般的操作都是对整个Activity不让其做横屏的切换的,如果做横屏切换时我们要做的工作就比较多了还要对横屏的界面布局信息做一些适配工作这样开发周期就比较长,目前大多数的应用都是只有竖屏状态。

2、生命周期应用场景

接下来就通过“一个Activity”去播放音乐的例子去讲解整个Activity生命周期在开发中具体应用。

首先在res中新建一个raw文件夹存放响应的音频文件res–>raw–>mm.mp3(文件尽量使用英文名

部分关键代码:

public class MainActivity extends Activity {

    private MediaPlayer mediaPlayer;
    private int position;// 保存当前播放的位置

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("tag", "MainActivity--->onStart()");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("tag", "MainActivity--->onResume()");
        if (position != 0) {
            mediaPlayer.seekTo(position);// 跳到播放的位置
            mediaPlayer.start();// 继续播放
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("tag", "MainActivity--->onPause()");
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();// 暂停
            position = mediaPlayer.getCurrentPosition();// 记录当前播放的位置
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("tag", "MainActivity--->onStop()");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("tag", "MainActivity--->onDestroy()");

        // 释放资源
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
        // ..............
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("tag", "MainAcitvity-->onCreate()");

        mediaPlayer = MediaPlayer.create(this, R.raw.mydream);
        mediaPlayer.start();
    }
}

代码解读:上面是”以一个Activity为载体来播放音乐”的。要播放音乐首先要创建一个MediaPlayer对象,在onCreate()方法中进行播放,此时在该Activity中打开一个新的Activity(假如新的Activity是来电界面)这种情况下应该把音乐处于暂停状态(即在当前Activity生命周期的onPause方法中判断是否在播放,在播放的话就要暂停播放并记录当前播放的位置。)当从电话界面返回到当前音乐播放的Activity时在指定位置开始播放(即在音乐播放Activity的onResume方法中重新播放),最后在onDestory方法中释放一些资源。(上面以给出了关键代码,其他相关的代码可自行完善,如有疑问请在文章最后留言!)

启动Activity(直接启动和匿名启动)

1、直接(显示)启动

//方法1
Intent intent = new intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
//方法2
Intent intent = new Intent();
ComponentName component = new ComponentName(FirstActivity.this, SecondActivity.class);
intent.setComponent(component);
startActivity(intent);

2、匿名(隐式)启动

假设SecondActivity不是在本应用中而是其他应用的Activity,如果这种情况下想在FirstActivity中启动SecondActivity我们是无法拿到SecondActivity对于的class所以不可以用显示意图启动,那要怎样启动SecondActivity呢,前提是需要在SecondActivity所在的应用中的Manifest文件中对SecondActivity指定了一个intent-filter意图过滤器并配置action与category属性(action取一个url作为名称,category属性用于指定当前动作(action)被执行的环境,环境可以设置为default(缺省)) ,然后根据意图过滤器中的action名来启动该Acticity(SecondActivity)。如下示例:

<activity android:name=".SecondActivity">
<intent-filter>
    <action android:name = "www.nf.com"></action>
    <category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
Intent intent=new Intent();
intent.setAction("www.nf.com");
startActivity(intent);

总结:
对于Activity 的启动,应用场景不同启动方式也会不同。我们使用匿名启动的时候,主要的原因是为了启动系统中的Activity(如:联系人界面,相册,浏览器等),显示意图主要是应用于知道Activity的名字的情况下(如:自身应用的Activity)。

启动系统常见的Activity

Intent类已经封装很多的常量信息都是系统Activity的一些标识(查看官方API文档:Develop-Reference-Intent

1、启动系统浏览器

intent.setAction(Intent.ACTION_VIEW);
Uri url=Uri.parse("http://baidu.com")
intent.setData(url);
startActivity(intent);

2、启动相册

Intent intent=new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivity(intent);

3、启动系统短信

Intent intent=new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,"hello world");
startActivity(intent);

4、启动拨号器

Intent intent=new Intent();
intent.setAction(Intent.ACTION_VIEW)
Uri url=Uri.parse("tel:13766257357");
intent.setData(url);
startActivity(intent);

本课程到这里就结束了,如果想更深一步学习可阅读:深入Activity

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值