学习Android之Activity的查缺补漏

在Activity中使用Menu

 菜单是不占用屏幕空间的。

 首先在res目录下新建menu文件夹,再在此文件夹中新建Menu resource file。

 <item>标签用来创建具体的某一个菜单项。id给这个菜单项指定一个唯一的标识符,title给这个菜单项指定一个名称。

 回到Activity中来重写onCreateOptionsMenu()方法,重写方法可以使用Ctrl + O快捷键。

 

 

 menuInflater实际上是调用了父类的getMenuInflater()方法。

 getMenuInflater()方法能够得到一个MenuInflater对象,再调用它的inflate()方法,就可以给当前Activity创建菜单了。

 还需要响应事件,重写onOptionsItemSelected()方法,如下所示:

 

 

使用隐式Intent

通过在<activity>标签下配置<intent-filter>的内容,可以指定当前Activity能够响应的action和category,打开AndroidManifest.xml,添加如下代码:

 

 

 在<action>标签中指明了当前Activity可以响应com.example.activitytest.ACTION_START这个action。

 而<category>标签则包含了一些附加信息,更精确地指明了当前Activity能够响应的Intent中还可能带有的category。

 只有<action>和<category>中的内容同时匹配Intent中指定的action和category时,这个Activity才能响应该Intent。

 此时修改FirstActivity中按钮的点击事件,代码如下所示:

 

 

 因为设置的一种默认的category,所以不用指定。

 每个Intent中只能指定一个action,但能指定多个category。

 可以调用Intent中的addCategory()方法来添加一个category。

 

 

 更多隐式Intent的用法

 使用隐式Intent,不仅可以启动自己程序内的Activity,还可以启动其他程序的Activity,这就使多个应用程序之间的功能共享成为了可能。

 比如需要展示网页时,调用系统的浏览器即可:

 

 

 Intent.ACTION_VIEW是一个Android系统内置的动作,其常量值为android.intent.action.VIEW。

 然后通过Uri.parse()方法将一个网址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传递进去。

 setData()方法接收一个Uri对象,主要用于指定当前Intent正在操作的数据,而这些数据通常是以字符串形式传入Uri.parse()方法中解析产生的。

 

另外,我们可以在<intent-filter>标签中再配置一个<data>标签,用于更精确地指定当前Activity能够响应的数据。

<data>标签中主要可以配置以下内容。

  • android:scheme。用于指定数据的协议部分,如上例中的https部分。
  • android:host。用于指定数据的主机名部分,如上例中的www.baidu.com部分。
  • android:port。用于指定数据的端口部分,一般紧随在主机名之后。
  • android:path。用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
  • android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

 不过,在<data>标签中一般不会指定过多的内容。

 例如在上面的浏览器示例中,其实只需要指定android:scheme为https,就可以响应所有https协议的Intent了。

 除了https协议外,还有geo表示显示地理位置、tel表示拨打电话。

 比如拨号:

 

 

 

Activity之间传递数据

 

 当appcompat库升级到1.3.0或更高的版本时,会发现startActivityForResult()方法已经被废弃了。

 现在更加建议使用Activity Result API,将会在后续文章学习记录。

Activity的生命周期

 Android是使用任务(task)来管理Activity的,一个任务就是一组存放在栈里的Activity的集合,这个栈也被称作返回栈(back stack)。

 Activity状态

 每个Activity最多4种状态。

  •  运行状态:Activity位于返回栈的栈顶时。
  •  暂停状态:一个Activity不再处于栈顶位置,但仍然可见时,比如对话框形式的Activity只会占用屏幕中间的部分区域。
  •  停止状态:一个Activity不再处于栈顶位置,并且完全不可见时。系统仍然会为这种Activity保存相应的状态和成员变量,但是这并不是完全可靠的,当其他地方需要内存时,处于停   止状态的Activity有可能会被系统回收。
  •  销毁状态:一个Activity从返回栈中移除后,系统最倾向于回收处于这种状态的Activity。

 Activity的生存期

  •  onCreate():Activity第一次被创建的时候调用。完成Activity的初始化操作,比如加载布局、绑定事件等。
  •  onStart():在Activity由不可见变为可见的时候调用。
  •  onResume():此时的Activity一定位于返回栈的栈顶,并且处于运行状态。可以与用户交互。
  •  onPause():系统准备去启动或者恢复另一个Activity的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据。但是执行速度要快。
  •  onStop():Activity完全不可见的时候调用。如果启动的新Activity是一个对话框式的Activity,那么onPause()方法会得到执行,而onStop()方法并不会执行。
  •  onDestroy():在Activity被销毁之前调用。
  •  onRestart():在Activity由停止状态变为运行状态之前调用,也就是Activity被重新启动了。

 

 

 

 

 Activity被回收了怎么办

 Activity中提供了一个onSaveInstanceState()回调方法,这个方法可以保证在Activity被回收之前一定会被调用,因此我们可以解决Activity被系统回收后数据的恢复。

 onSaveInstanceState()方法会携带一个Bundle类型的参数:

 

 

 那在哪里恢复呢?

 其实onCreate()方法也有一个Bundle类型的参数,一般情况下都是null。

 如果在Activity被系统回收之前,你通过onSaveInstanceState()方法保存数据,这个参数就会带有之前保存的全部数据。

 

 

 当手机的屏幕发生旋转的时候,Activity也会经历一个重新创建的过程。但是一般不建议通过onSaveInstanceState()方法来解决,对于横竖屏旋转的情况,后面有更好的方案。

 Activity的启动模式

 有4种:分别是standard、singleTop、singleTask和singleInstance。

 在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。

  standard

  Activity默认的启动模式。系统不会在乎这个Activity是否已经在返回栈中存在,每次启动都会创建一个该Activity的新实例,并处于栈顶。

 

 singleTop

 在启动Activity时如果发现返回栈的栈顶已经是该Activity,则认为可以直接使用它,不会再创建新的Activity实例。

 如果该Activity不在栈顶,则会创建新的Activity实例。

 使用场景:登录页面、推送通知栏

 singleTask

 每次启动该Activity时,系统首先会在返回栈中检查是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并把在这个Activity之上的所有其他Activity统统出栈,如果没有发现   就会创建一个新的Activity实例。

 使用场景:WebView页面、扫一扫页面、购物界面、确认订单界面、付款界面

 singleInstance

 最复杂最特殊的一个。

 指定为该模式的Activity会启用一个新的返回栈来管理这个Activity。

 作用:实现其他程序和我们的程序可以共享这个Activity的实例。

 因为每个应用程序都会有自己的返回栈,同一个Activity在不同的返回栈中入栈时必然创建了新的实例。在这种模式下,会有一个单独的返回栈来管理这个Activity,不管是哪个应用程序来访问这个Activity,都共用同一个返回栈,也就解决了共享Activity实例的问题。

 使用场景:系统Launcher、锁屏键、来电显示等系统应用

 

 随时随地退出程序(专门对Activity进行管理)

 新建一个单例类ActivityCollector作为Activity的集合,代码如下所示:

 

 

 

 

 

  新建BaseActivity类继承AppCompatActivity(),实现启动Activity就加入集合,退出就移出集合:

 

 

 再让所有的Activity继承BaseActivity。

 

 

 启动Activity的最佳写法

 为了方便数据传递,在需要接受数据的Activity中编写接收格式,提高可读性。方便他人传递数据时一目了然。

 写法如下:

 

 这里有一个新的语法结构companion object,所有定义在里面的方法都可以使用类似于Java静态方法的形式调用。

 此时启动代码只需一行:

 

posted @ 2022-03-12 18:04  PeacefulGemini  阅读(108)  评论(0)    收藏  举报
回顶部