前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android必知必会的四大组件--Activity

Android必知必会的四大组件--Activity

作者头像
ClericYi
发布2020-06-23 15:17:09
7290
发布2020-06-23 15:17:09
举报
文章被收录于专栏:ClericYi's Blog

生命周期&方法解释

这儿重点要知道的是下面这两对各自之间的区别。

(1)onPause() 和 onStop()

(2)onStart() 和 onResume()

onPause()说明当前的Activity已经暂停,但你并不是说暂停的意思只是没有了动作,而调用了onStop()才让Acivity不可见。

onStart()也是一样,只是说Activity已经可以启动了,但这个时候页面还是不可见的,只有调用了onResume()页面才能够可见,页面跳转也是如此。

现在在回答一下之前的问题,Activity A 跳转Activity B,再从Activity B按back键回退,两个过程各自的生命周期?

  1. Activity A 跳转Activity B: Apause -> Bcreate -> Bstart -> Bresume -> Astop
  2. Activity B再按back键回退: Bpause -> Arestart -> Astart -> Aresume -> Bstop -> Bdestroy

想来你会有这样的一个问题,为什么要先进行OnPause呢?

Activity的启动过程:由AMS对栈内的Activity状态进行同步管理 & 规定:新Activity启动前,栈顶的Activity必须先onPause(),才能启动新的Activity(执行onResume())

所以为了让新的Activity能够进行快速的切换,在OnPause()中尽量不要做耗时的操作。

四大启动模式

standard — 标准模式

  • 特征:每次启动一个Activity都会创建一个实例。
  • 应用场景:Activity的默认启动方式。

singleTop — 栈顶复用

  • 特征:如果在栈顶,就不在创建实例。反之则创建。
  • 应用场景:当前要跳转的页面已经在栈顶时,比如说消息通知跳转

singleTask — 栈内复用

  • 特征:如果栈内存在,就将后入栈的实例全部弹出
  • 应用场景:有一个专用主页面作为基础的app,这样的app现在市面上也非常普遍存在,就比如一个Activity中嵌入ViewPager+BottomNavigationBar制作成的一个主页面一样,ViewPager中嵌入了很多的Fragment,这个时候如果是standard或singleTop的形式,很容易让应用卡顿。

注意点:

  • 如果其他App进程开启了Activity1,这个时候会创建新的任务栈
  • 如果以该启动模式启动的Activity1已经活动在后台的一个任务栈中,那么启动后,后台任务栈会一起切换到前台。

singleInstance — 全局唯一

跟前三种启动模式不同,他的实例存在于一个独立的任务栈中。

  • 特征:系统中只会有一个实例。
  • 应用场景:系统内部的应用,比如电话、短信等功能,通过Intent进行传播时,固定的就会调用这些系统自带的应用,在自己的应用中一般比较少使用。

常见场景的生命周期调用

上文中我们讲到过了两种场景的生命周期调用。这里重新放出用于背诵。Activity A 跳转Activity B,再从Activity B按back键回退,两个过程各自的生命周期?

有什么样的生命周期调用呢?

  1. Activity启动:用户打开Activity onCreate() onStart() onResume 运行状态
  2. Activity部分遮盖,弹窗跳出:Activity从运行状态 onPause() (注意,没有onStop())
  3. Activity完全遮盖,也就是Activity A跳转到Activity B的场景。
  4. Activity从部分覆盖 -> 运行状态:OnPause() OnResume()
  5. Activity从完全覆盖 -> 运行状态:从Activity B按back键回退
  6. Activity退出:运行状态 -> onPause() -> onStop() -> onDestroy()

注意注意!!!这些都是正常情况,但是如果出现闪退之类的情况呢???那我们就要好好谈谈异常情况了。

  • 因为系统内存不足,等待被杀。如果要返回,但前面的Activity已经被杀,那么这个Activity会重新经过Activity启动的生命周期。

存在一个杀死进程的优先级:

  1. 后台Activity,即不可见的,且不位于前台的Activity
  2. 可见但是不位于前台的Activity,即弹窗背后的Activity
  3. 前台Activity

  • 配置变化,例如 横竖屏切换。会将数据保存,也就是onSaveInstanceState(),销毁掉当前的Activity,重建之后,从onRestoreInstanceState()中拿到已经保存的数据。

Activity之间的数据传输

在Activity的跳转之间,其实存在很多需要带上数据的情况。举个例子来说,就像是从Activity A一个新闻列表中选取了一条新闻,那这个时候就需要跳转进入Activity B,而查询新闻的方式我们就假设是他的id那这个时候,就需要将这个id从Activity A送到Activity B中。

其实这种方式有很多,但是最普遍进行使用的莫过于putExtra(key, value)了。

使用方法

代码语言:javascript
复制
// 1. 定义跳转页面
Intent intent = new Intent(this, SecActivity.class);

// 2. 将数据放到Intent中
intent.putExtra("parameter key", "parameter value");

// 3. 启动页面
//      |-- 不带回传方法
startActivity(intent);
//      |-- 带回传方法
startActivityForResult(intent, REQUEST_CODE);

这里要注意的一个问题就是,如果想要接受到返回的数据,那我们就存在必须重写的方法,通过下方模版即可完成。

代码语言:javascript
复制
@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  if(requestCode == REQUEST_CODE){
    // 进行相应的处理
  }
  super.onActivityResult(requestCode, resultCode, data);
}

完成了页面跳转和参数传递,那我们接下来要干啥?当然是拿到这些参数了!!!

代码语言:javascript
复制
getIntent().getStringExtra(key);
getIntent().getBooleanExtra(key);
// 。。。。。。

实在太多了,我就不一一列举了。那我们就出现问题了getIntent()哪儿来的,传递靠的是什么机制??,因为我们的接收还没讲完,所以我们这个问题先保留。

因为我们说过一个事情存在回调,我们应该要怎么做的问题。

代码语言:javascript
复制
// 通过setRsult()方法,来进行一个数据的回传
setResult(resultCode);
setResult(resultCode, intent);

// 模版,setResult()方法二选一
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
  // 说明是一个返回事件
  if (keyCode == KeyEvent.ACTION_DOWN && event.getAction() == KeyEvent.ACTION_DOWN) {
    Intent intent = new Intent();
    intent.putExtra("parameter key", "parameter value");
    // setResult(resultCode);
    setResult(resultCode, intent);
  }
  return super.onKeyDown(keyCode, event);
}

Activity之间跳转,Intent的设置

代码语言:javascript
复制
public Intent getIntent() {
  return mIntent;
}

我们去Activity的startActivity(intent)跳转过程中去查询,当然代码太多了,我就直接总结好了。

代码语言:javascript
复制
startActivity() --> startActivityForResult() --
--> Instrumentation.execStartActivity() --> IActivityTaskManager.startActivity() --
--> 进入了一个.aidl文件然后我也不知道了,但是肯定是在这里办正事儿的

探索发现:

(1)我们的数据,也就是Intent中使用putExtra(key, value)放置的数据最后都被封装进了Bundle,所以说Bundle其实就是我们Activity之间数据传递的媒介

(2)而Activity的跳转也是基于一个Binder的机制来完成的。

Fragment的生命周期

整体上来说的话Fragment的生命周期和Activity是差不多的,但是要注意Fragment是存在一个依存关系的,通过与Activity绑定实现。碎片化作为他的专有名词,其实同样的是为了帮助我们抛去过度复杂的Activity的一系列创建操作,这也是为什么我们在开发过程中会经常去使用Fragment的原因。

简单来说就是Activity太重了,如果我们能用轻的Fragment完成就尽量换用。比如一个ViewPager的每个按钮对应的是一个个Activity和对应的是一个个Fragment的区别,一个是页面跳转,一个是布局内的内容切换,如此看来Fragment的使用会更占优势。

总结

其实上面都讲的差不多了,这里说几个实际会碰到的问题把。

就是static、Handler、ServiceConnection这一类可能会引发的内存泄漏问题。他们存在解决方法,其实多种多样,但更多一般也都是基于生命周期来完成的。一般解法都是在onDestroy()进行置空操作、或是解绑这一类方法。

另一种泄漏问题就可能会引起Activity的泄漏了,就是内部存在未运行完子线程,导致Activity不能被及时清理掉。而具有复杂操作的Activity一旦泄漏将会产生灾难性的后果,这也是为什么我们后来会引申出MVP、MVVM框架的一部分原因了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DevGW 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用方法
  • Activity之间跳转,Intent的设置
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档