《第一行代码》——活动
写活动之前,初步认识一下安卓中另一个比较重要的概念:context。
context可以理解为上下文环境,也可以理解为运行环境,提供系统运行必须的信息,资源等等,或者是用户操作与系统交互的场景,比如Activity之间的切换,启动服务等。
安卓中,context是关于应用环境全局信息的接口,能够获取系统资源和类型。
context与四大组件的关系为:
context本身是一个抽象类,ContextWrapper类和ContextImpl类实现了Context类。其中运用了装饰模式,使得代码更为灵活。看ContextWrapper源码,可以发现没有功能的具体实现,而具体功能是通过传入ContextImpl对象实现的(ContextImpl具体路径:/sdk/sources/android-28/android/app/ContextImpl.java,通过source insight软件查看源码)。ContextThemeWrapper类,内部包含了与主题(Theme)相关的接口,这里所说的主题就是指在AndroidManifest.xml中通过android:theme为Application元素或者Activity元素指定的主题。只有Activity才需要主题,Service是不需要主题的,因为Service是没有界面的后台场景,所以Service直接继承于ContextWrapper,Application同理。而ContextImpl类则真正实现了Context中的函数,应用程序中所调用的各种Context类的方法,其实现均来自于该类。一句话总结:Context的两个子类分工明确,其中ContextImpl是Context的具体实现类,ContextWrapper是Context的包装类。Activity,Application,Service虽都继承自ContextWrapper(Activity继承自ContextWrapper的子类ContextThemeWrapper),但它们初始化的过程中都会创建ContextImpl对象,由ContextImpl实现Context中的方法。
关于context先大致介绍到这儿,关于详情可以结合下面文章:
https://blog.csdn.net/chishi199433/article/details/80096350 (这篇是几篇整合,但是排版比较乱,优点是源码清晰)
https://www.jianshu.com/p/b36b70521b79(关于装饰模式讲的比较通俗易懂)
再查一下对context就会有大致了解。
再谈一下活动。从几个方面来讲。
-
是什么?
Activity是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。
-
有什么特点?
任务和返回栈:
应用通常有多个Activity,任务是执行特定作业时与用户交互的一系列Activity,Activity按照打开顺序排列在堆栈中,即返回栈中。 (来源:https://developer.android.google.cn/guide/components/tasks-and-back-stack.html?hl=zh_cn)当 Activity A 启动 Activity B 时,Activity A 将会停止,但系统会保留其状态(例如,滚动位置和已输入表单中的文本)。如果用户在处于 Activity B 时按“返回”按钮,则 Activity A 将恢复其状态,继续执行。
用户通过按主页按钮离开任务时,当前 Activity 将停止且其任务会进入后台。 系统将保留任务中每个 Activity 的状态。如果用户稍后通过选择开始任务的启动器图标来恢复任务,则任务将出现在前台并恢复执行堆栈顶部的 Activity。
如果用户按返回按钮,则当前 Activity 会从堆栈弹出并被销毁。 堆栈中的前一个 Activity 恢复执行。销毁 Activity 时,系统不会保留该 Activity 的状态。
即使来自其他任务,Activity 也可以多次实例化。
生命周期:
Activity基本以三种状态存在
继续 Activity位于屏幕前台并具有用户焦点,位于栈顶
暂停 Activity失去焦点但仍可见,位于栈顶
停止 Activity被另一个Activity遮盖,位于后台,不再栈顶,但仍处于活动状态。
adroid中定义了回调方法来定义Activity的整个生命周期。
onCreate():首次创建时调用。完成活动的初始化。执行所有正常的静态设置(视图,数据绑定到列表等)。
onStart():活动即将对用户可见时调用。如果活动转前台,则接onResume,转隐藏,则接onStop()。
onResume():即将与用户交互的时候调用。此时Activity一定位于栈顶并具有用户输入焦点。
onPuase():系统即将去调用另一个Activity时调用。通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗CPU的内容。应迅速执行所需操作。
onStop():Activity完全不可见的时候调用。
onDestory():Activity被销毁前调用。
onRestart():活动已停止并将再次启动之前调用。
注意不同生命周期不同的代码,比如广播的取消等。
保存Activity状态
当系统为了恢复内存而销毁某项 Activity 时,Activity对象也会被销毁,因此系统在继续 Activity 时根本无法让其状态保持完好,而是必须在用户返回 Activity 时重建Activity
对象。但用户并不知道系统销毁 Activity 后又对其进行了重建,因此他们很可能认为 Activity 状态毫无变化。 在这种情况下,实现另一个回调方法对有关 Activity 状态的信息进行保存,以确保有关 Activity 状态的重要信息得到保留:onSaveInstanceState()
。
系统调用onSaveInstanceState(),使用putString和putInt等方法以名称-值对的形式保存信息。重建时会将Bundle传递给onCreate和onRestoreInstanceState(),任意选用其中一个提取保存的状态并恢复该Activity。
启动模式
1.清单文件中通过launchMode属性声明。
2.使用Intent标志 调用startActivity时,在Intent中加入标志。
四种启动模式:
standard 默认。Activity多次实例化,每个实例可属于不同任务,一个任务可以拥有多个实例。
singleTop 顶部存在,则调用该实例,否则创建新的。
singleTask 有实例,则直接使用并将此实例之上的全部出栈。
singleInstance 启用一个新的返回栈来管理这个活动(其实如果 singleTask 模式指定了不同的 taskAffinity,也会启动一个新的返回栈)。
-
怎么用
Intent-filter可以声明其他应用组件**它的方法。
显式IntentIntent intent = new Intent(this, SignInActivity.class); startActivity(intent);
隐式Intent
在Manifest.xml文件中添加Intent-filter
<activity android:name=".inquiry_activity.SecondActivity"> <intent-filter> <!-- 指定活动能响应的action和category --> <action android:name="com.wonderful.ACTION_START"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> // 隐式Intent Intent intent = new Intent("com.wonderful.ACTION_START"); startActivity(intent);
隐式Intent好处是松耦合。
更多用途:
Intent intent = new intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("tel:10086)); startActivity(intent);
传递数据:
String data = "sss"; Intent intent = new Intent(firActivity.this, secActivity.class); intent.putExtra("extraData",data); startActivity(intent); //another activity Intent intent = getIntent(); String data = intent.getStringExtra("extraData");
返回数据给上一个Activity:
//fir Intent intent = new Intent(FirstActivity.this,SecondActivity.class); startActivityForResult(intent,1);//请求码只要是唯一值就行了,这里传入1 //second Intent intent = new Intent(); intent.putExtra("data_return","hello FirstActivity"); setResult(RESULT_OK,intent); finish();//销毁当前活动 //fir /** * 处理得到的返回数据 * @param requestCode 启动活动时传入的请求码 * @param resultCode 返回数据时传入的处理结果 * @param data 携带返回数据的Intent */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ case 1: if (resultCode == RESULT_OK){ String returnedData = data.getStringExtra("data_return"); Log.d(TAG, returnedData); } break; default: break; } }
https://www.jianshu.com/p/633588694a34(第一行代码第一章内容)
https://developer.android.google.cn/guide/components/tasks-and-back-stack.html?hl=zh_cn(任务和返回栈)
https://developer.android.google.cn/guide/components/activities?hl=zh_cn#Lifecycle(Activity)
https://blog.csdn.net/hystudio_lzu/article/details/80629571(更深入一点讲Activity的文章,包含了异常情况,各种匹配规则)
最后马克两个博主的博客,方便以后更深入学习。
https://blog.csdn.net/Luoshengyang/article/details/8923485(偏向更底层的源码解析)
https://blog.csdn.net/qq_26787115/article/details/81068136(Android开发艺术探索笔记)
上一篇: 第一行代码中的下载服务最佳实践