Activity基础知识

1.Activity的创建

Activity 是Android 四大组件之一,用于展示界面
  • Activity 中所有操作都与用户密切相关,是一个负责与用户交互的组件,它上面可以显示一些控件也可以监听并处理用户的事件。
  • 一个Activity 通常就是一个单独的屏幕,Activity 之间通过Intent 进行通信。

1.自定义类继承Activity

新建一个Android 工程,在src 目录下新建一个类,不妨起名MyActivity,让该类继承Android SDK提供的Activity。

2.MyActivity 中覆写onCreate()方法

onCreate() 方法在当前Activity 被系统创建的时候调用
  • 在该方法中一般要通过setContentView(R.layout.myactivity)方法给当前Activity 绑定布局文件或视图。
  • 因此为了让我们的MyActivity能够展示界面,需要在工程目录的res/layout/目录下创建一个布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是MyActivity的界面"/>
</LinearLayout>

3.AndroidManifest.xml 中进行Activity 的注册

Android 中共有四大组件,除了BroadCastReceiver 之外,其他三个组件如果要使用那么必须在AndroidManifest.xml 中进行注册(也叫声明)
activity/android:name:要注册的Activity 的全限定类名
activity/android:label:Activity 左上角显示的名称

intent-filter:叫意图过滤器,一般用于隐式启动该Activity
action/android:name:意图过滤器的Action 名称,可以自定义也可以使用系统提供的。
category/android:name:意图过滤器的category 名称,只能使用系统提供的常量值。
  • 对于MainActivity来说正是配置了特定(action为android:name="android.intent.action.MAIN",category为android:name="android.intent.category.LAUNCHER")的intent-filter,那么当应用安装好以后,才会在桌面创建一个图标,点击该图标打开MainActivity。

  • 自定义的MyActivity如果也配置了一模一样的intent-filter,那么系统也会为我的MyActivity 创建一个图标,如果用户点击了该图标,那么也可以直接打开我的MyActivity 界面。

  • 也就是说一个Android 工程可以创建多个图标,不过通常情况下一个Android 应用只要给一个入口的Activity 配置为入口Activity 即可。

2.Activity的跳转

显式跳转:在可以引用到另外一个Activity 的字节码,或者包名和类名的时候,通过字节码,或者包名+类名的方法实现的跳转叫做显示跳转。
显示跳转多用于自己工程内部多个Activity 之间的跳转,因为在自己工程内部可以很方便地获取到另外一个Activity 的字节码。

隐式跳转:隐式跳转不需要引用到另外一个Activity 的字节码,或者包名+类名,只需要知道另外一个Activity 在AndroidManifest.xml 中配置的intent-filter 中的action 和category 即可。
言外之意,如果你想让你的Activity 可以被隐式意图的形式启动起来,那么就必须为该Activity 配置intent-filter。
  • Activity 之间的跳转都是通过Intent 进行的。

  • Intent 即意图,不仅用于描述一个Activity的信息,同时也是一个数据的载体。

  • 显示意图

//通过Intent 的带参构造函数
Intent intent = new Intent();
//通过Intent 的setClass 方法
intent.setClass(this, SecondActivity.class);
//Intent 可以携带的数据类型
1.八种基本数据类型boolean、byte、char、short、int、float、double、long 和String 以及这9 种数据类型的数组形式
2.实现了Serializable 接口的对象
3.实现了Android 的Parcelable 接口的对象以及其数组对象
  • 隐式意图
//要跳转的activity在清单文件里增在intent-filter
<intent-filter >
        <action android:name="自己定义,习惯用包名后加功能名"/>
        <category android:name="android.intent.category.DEFAULT"/> //默认
</intent-filter>

//谁要跳转到这个activity,谁的方法里面调用
Intent intent = new Intent();
intent.setAction("要跳转的activity在清单文件里配置的action");
intent.addCategory("android.intent.category.DEFAULT");-->默认
startActivity(intent);
  • 隐示意图需要注意的地方
在清单文件的 intent-filter 里面还可以配置 data标签,data标签可以配置多个不同种类型的
例如:
<data android:scheme="自己定义"/> -->设置前缀,与电话播放器调用很像
<data android:mimeType="text/plain"/> -->定义类型,这里不能随意定义

在java代码里,如果同时配置了scheme和mineType:
intent.setDataAndType(scheme,mimeType);

如果只配置scheme:
intent.setData();

如果只配置了mimeType:
intent.setType();

3.示例代码

  • 闪屏页面
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(){
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Intent intent = new Intent();
                intent.setClass(MainActivity.this, CalcActivity.class);
                startActivity(intent);
                finish();//把mainActivity关闭
            }
        }.start();
    }
}
  • 主页面
public class ResultActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_result);
        // 获取传递过来的Intent
        Intent intent = getIntent();
        // 取出对应的数据
        String name = intent.getStringExtra("name");
        Bitmap bitmap = intent.getParcelableExtra("bitmap");
    }
}

3.Activity 的生命周期

Activity 从创建到销毁,整个生命周期是一个非常复杂的过程,该过程由Android 系统负责维护

1.Activity 的3种状态

Resumed、Paused、Stopped可以理解为:激活或运行状态、暂停状态、停止状态
  • Resumed 状态
    Activity 位于前端位置,并且获取到了用户的焦点。也就是当前Activity 完全可见也可用。
    注意:在Android 中目前只允许同时只能有一个Activity 位于前端位置。

  • 2.Paused 状态
    如果另外一个Activity 位于前端位置并且获取了焦点,但是该Activity 还依然可见,那么该Activity 就处于了Paused 状态。
    比如另外一个Activity 虽然位于前端,但是是透明的或者没有占满整个屏幕,那么就会出现上面的这种情况。
    位于Paused 状态的Activity 依然是“存活”着的,但是如果系统内存极端的不足,那么就有可能被系统“杀死”以便释放内存。

  • 3.Stopped 状态
    当另外一个Activity 完全将该Activity 遮盖住的情况下,那么该Activity 就处于停止状态了。
    位于停止状态的Activity 依然“活着”,但是它已经对用户完全不可见了,因此只要系统需要释放内存就会将该Activity“杀死”。

我们编写的代码要根据Activity 的不同状态让其做不同的工作。
如果我们的Activity 是用于播放视频的:
当其位于Resumed 状态时我们可以让视频正常的播放。
当Activity 位于Paused 状态的时候,我们也应该让我们的视频暂停播放。
当Activity 位于Stopped 状态时我们应该停止播放视频并释放资源。

2.Activity 生命周期的回调方法

OnCreate    
当Activity 第一次创建时被调用,在该方法中我们应该执行创建视图、初始化数据等工作。
该方法被调用之后紧接着就是调用onStart 方法。

onStart 
当Activity 对用户可见前被系统调用。

onResume    
当Activity 可以跟用户交互前被调用,该方法被调用后Activity 就处于Resumed 状态。

onPause 
当另外一个Activity 即将成为Resumed 状态前调用,在该方法中应该保存临时数据、停止动画、暂停视频播放器等。
必须要注意的就是该方法执行必须要快,因为只有当该方法执行过之后,另外一个Activity 才会成为Resumed 状态,不然会造成Activity 直接切换的“卡顿”现象。

onStop  
当Activity 对用户已经完全不可见的时候就会调用该方法。
当另外一个Activity 已经成为Resumed 状态或者当前Activity 被销毁的情况下会导致当前Activity 不可见。

onDestory   
当Activity 被销毁前调用。
当前Activity 调用finish()方法或者系统为了释放内存而将其销毁都会调用该方法。

onRestart   
当Activity 处于onStop 状态之后,如果重新启动则会调用该方法。
比如如果当前Activity位于Resumed 状态,此时我们按了Home 键,那么Activity 就完全不可见了,onStop 方法就会被执行,然后再长按Home 键再将该Activity 重新启动起来就会调用onRestart 方法。

3.横竖屏切换时Activity 的生命周期

Android 手机在横竖屏切换时,默认情况下会把Activity 先销毁再创建。

在类似手机游戏、手机影音这一类的应用中,这个体验是非常差的。不让Activity 在横竖屏切换时销毁,只需要在清单文件声明Activity 时配置<activity>节点的几个属性即可,其方式如下:

//参数配置到Activity,就不会再销毁和重新创建了
android:configChanges="orientation|keyboardHidden|screenSize"

//固定Activity 的方向
//有两种方法:
    //通过配置文件
    在AndroidManifest.xml 中的activity 节点中添加如下属性。
    android:screenOrientation="portrait"
    该属性通常有两个常量值,portrait:垂直方向,landscape:水平方向。
    
    //通过代码
    在Activity 的onCreate 方法中执行如下方法。
    //垂直方向
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    //水平方向
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

4.Activity 的启动模式

1.Activity 的任务栈

Task Stack(任务栈)是一个具有栈结构的容器,可以放置多个Activity 实例
  • 数据结构:先进后出

2.优缺点

  • 优点:提高了用户体验
  • 缺点:
    每开启一次页面都会在任务栈中添加一个Activity,而只有任务栈中的Activity 全部清除出栈时,任务栈被销毁,程序才会退出,这样的设计在某种程度上可能造成了用户体验差,需要点击多次返回才可以把程序退出了。
    每开启一次页面都会在任务栈中添加一个Activity 还会造成数据冗余, 重复数据太多, 会导致内存溢出的问题(OOM)。

3.启动模式

Activity 的启动模式
启动模式(launchMode)在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity 实例,是否重用已存在的Activity 实例,是否和其他Activity 实例共用一个task。

Activity 一共有以下四种启动模式:standard、singleTop、singleTask、singleInstance。

我们可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可。

  • standard: 标准启动模式
    特点:默认启动模式, 每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈

  • singleTop:单一顶部模式
    特点:如果activity已经被开启,而且是在栈顶,就不会在创建当前这个activity的实例,而是复用这个已经开启的activity,但是如果不是在栈顶,就会初始化一个新的实例,在整个栈里允许有多个实例

  • singleTask:单一任务栈
    特点:当前栈里只允许有一个当前activity的实例,如果要开启的activity在栈里存在,并且在底部,就会移除这个activity上面所有的activity
    应用场景:如果这个activity非常消耗cpu和内存,建议把这个activity的启动模式设置为singleTask,浏览器的browserActivity 设置的就是

  • singleinstance:单一实例
    特点:整个手机操作系统只有一个实例,并且是单独运行在自己的任务栈里
    应用场景:通话界面的activity

Activity的启动模式是很重要的一个知识点,在项目开发中经常会用到启动模式来帮助我们解决一些比较难解决的bug,也可以帮助我们去优化一个项目的任务栈,防止界面太多导致卡顿和OOM。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 跳绳,跳房子。那个穿着黑衣服、挨着我坐在我的长椅上,坐在我的欢乐之枷上(有个性感少女正在我脚下寻找一个失落了的弹子...
    Molly_zhang阅读 248评论 0 0
  • 常言道:"茶亦醉人何必酒,书能香我不需花。"昨日我刚欣赏到茶香之韵,花姿之美,今天又迎来了世界读书日。近几年,随着...
    莞笔轻轻阅读 872评论 2 14
  • 所有深爱,都是秘密。
    分心成瘾阅读 173评论 0 0
  • 北京时间9月15日凌晨,欧联杯小组赛首轮,葡超队吉马良斯创造了一个新纪录,他们在与萨尔茨堡红牛的比赛中排出全部由非...
    爱体育阅读 214评论 0 0