Activity
创建一个Activity
? 当我们创建一个Activity后,都需要在AndroidManifest中进行注册才能生效
? Activity的注册声明式放在标签中的。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.uibestpractice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.UIBestPractice">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
? 在中加入标签表示将此Activity作为启动的Activity。
? label:指定Activity中标题栏的内容,将显示在Activity的最顶部
Activity中使用Toast
? Toast式Android提供的一种提醒方式,在程序中可以使用它将一些短小的消息通知给用户,这些消息会在一段时间后消失,并且不占用任何屏幕空间
Toast.makeText(this, "You clicked Button1", Toast.LENGTH_SHORT).show()
? Toast有三个参数:
- Context:Toast要求的上下文,由于Activity本身就是一个Context对象,所以可以直接传入this
- String: Toast需要显示的文本内容
- Toast显示的时长,有两个可选参数:Toast.LENGTH_SHORT和Toast.LENGTH_LONG
简化findViewById()
? 在kotlin中,可以在app/build.gradle文件中加入kotlin-android-extensions,就可以直接使用控件的id进行调用,而不需要使用findViewById()方法了
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android-extensions'
}
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.first_layout)
Log.d("FirstActivity", "OnCreate execute")
button_1.setOnClickListener{
Toast.makeText(this, "You clicked Button1", Toast.LENGTH_SHORT).show()
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("https://www.baidu.com")
startActivity(intent)
}
}
Menu的使用
? 通过New->Menu resource file创建一个menu文件.
? 标签用于创建具体的菜单项,然后通过id表示唯一的标识符
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
? 然后在Activity中重写onCreateOptionsMenu()方法,可以使用Ctrl + O快捷键。inflate接收两个参数,第一个参数用于指定我们通过哪一个资源文件来创建菜单,第二个用于指定我们的菜单添加到哪一个Menu对象中。然后可以通过重写onOptionsItemSelected()方法来对菜单定义响应事件
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.add_item->Toast.makeText(this, "you clicked add", Toast.LENGTH_SHORT).show()
R.id.remove_item->Toast.makeText(this, "you clicked remove", Toast.LENGTH_SHORT).show()
}
return true
}
销毁一个Activity
? 可以通过back键来销毁,也可以调用finish()方法对activity进行销毁。
button_1.setOnClickListener{
finish()
}
使用Intent对Activity进行切换
显式Intent切换
? Intent()方法接收两个参数,第一个Context要求提供Activity的上下文,第二个用于指定想要启动的目标Activity。
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.First_layout)
button_2.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
隐式Intent切换
? 隐式切换不会指明想要启动的Activity,而是通过抽象的action和category等信息,然后通过系统分析Intent找到合适的Activity来启动。
? 首先在AndroidManifest文件中指明和信息。default表示一种默认的category,在调用startActivity时会自动将其添加到intent中
<activity android:name=".SecondActivity"
android:exported="true">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example.activitytest_MY_CATEGORY"/>
</intent-filter>
</activity>
? 然后就可以通过隐式intent来切换Activity
button_2.setOnClickListener{
val intent = Intent("com.example.activitytest.ACTOPM_START")
startActivity(intent)
}
? 除此之外,隐式Intent还可以启动其他程序的Activity。
button_1.setOnClickListener{
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.prase("https://www.baidu.com")
startActivity(intent)
}
传递数据到下一个Activity
? Intent提供了一系列putExtra()方法的重载,可以将想要的数据暂存在Intent中。
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.First_layout)
button_2.setOnClickListener{
val data : String = "Hello SecondActivity"
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("extra_data", data)
startActivity(intent)
}
}
class SecondActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.second_layout)
val extraData = intent.getStringExtra("extra_data")
Log.d("SecondActivity", "extra data is $extraData")
}
}
返回给上一个Activity
? Activity类中提供了一个用于启动Activity的startActivityForResult()方法,它期望在Activity销毁的时候能够返回给上一个Activity。
startActivityForResult()方法接收两个参数:第一个参数是Intent,第二个参数是请求吗,用于判断数据的来源。
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?){
...
button1.setOnClickListener{
val intent = Intent(this, secondActivity::class.java)
startActivityForResult(intent, 1)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data:Intent?){
super.onActivityResult(requestCode, resultCode, data)
when(requestCode){
1-> if(resultCode == RESULT_OK){
val returnData = data?.getStringExtra("data_return")
}
}
}
}
class SecondActivity:AppCompatActivity{
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.second_layout)
button2.setOnClickListener{
val intent = Intent()
intent.putExtra("data_return", "Hello FirstActivity")
setResult(RESULT_OK, intent)
finish()
}
}
}
Activity的生命周期
返回栈
? Android使用任务(task)来管理Activity,一个任务就是一组存放在返回栈中的Activity集合。每当我们启动一个Activity时,它就会在返回栈中入栈,并处于栈顶位置。每当我们按下Back或者调用finish方法销毁Activity时,处于栈顶的Activity就会出栈。系统总是显式处于栈顶的Activity给用户
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvweZqEL-1650718347510)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220423164022217.png)]
Activity状态
? 每个Activity在其生命周期中最多可能有四种状态
- 运行状态:当Activity处于栈顶时,Activity就处于运行状态
- 暂停状态:当Activity不再处于栈顶,但仍然可见时就处于暂停状态
- 停止状态:当Activity不再处于栈顶,且完全不可见时,处于停止状态
- 销毁状态:当Activity从栈中一出时处于销毁状态
Activity的生存期
? Activity定义了7个回调方法,覆盖了Activity生命周期的每一个环节。
- onCreate():当Activity第一次被创建时调用
- onStart():当Activity由不可见到可见时调用
- onResume():当Activity准备好和用户进行交互的时候调用。此时Activity处于栈顶并处于运行态
- onPause():当系统准备启动或恢复另一个Activity时调用
- onStop():当Activity完全不可用时调用
- onDestory():在Activity被销毁之前调用
- onRestart():当Activity由停止变为运行之前调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lu6W121v-1650718347511)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220423165533274.png)]
package com.example.activitylifecycletest
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val tag = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startNormalActivity.setOnClickListener{
val intent = Intent(this, NormalActivity::class.java)
startActivity(intent)
}
startDialogActivity.setOnClickListener{
val intent = Intent(this, DialogActivity::class.java)
startActivity(intent)
}
}
override fun onStart() {
super.onStart()
Log.d(tag, "onStart")
}
override fun onResume(){
super.onResume()
Log.d(tag, "onResume")
}
override fun onPause() {
super.onPause()
Log.d(tag, "onPause")
}
override fun onStop() {
super.onStop()
Log.d(tag, "onStop")
}
override fun onDestroy() {
super.onDestroy()
Log.d(tag, "onDestroy")
}
override fun onRestart() {
super.onRestart()
Log.d(tag, "onRestart")
}
}
Activity被回收了的处理办法
? 当Activity进入停止状态时,有可能会被系统回收,但此时Activity中可能保存有临时数据和状态。如果丢失这些数据和状态是非常影响用户体验的。为了解决这一问题,Activity中提供了一个onSaveInstanceState()方法,它保证了Activity被回收之前一定会调用。
? onSaveInstanceState()方法会携带一个Bundle类型的参数,它提供了一系列的方法用于保存数据,如putString()、putInt()等。每个保存方法提供了两个参数,第一个是键,第二个是值
override fun onsaveInstanceState(outState:Bundle){
super.onSaveInstanceState(outState)
val tmpData = "Something you just typed"
outState.putString("data_key", tmpData)
}
override fun onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(saveInstanceState != null){
val tmpData = savedInstanceState.getString("data_key")
}
...
}
Activity 启动模式
? 启动模式一共有四种,分别是standerd、singleTop、singleTask和singleInstance,可以在AndroidManifest中通过标签指定android:launchMode属性来选择启动模式。
- standerd:默认启动模式,在此模式下,每当启动一个新的Activity,它就会在返回栈中入栈,并处于栈顶位置。系统不会在乎此Activity是否已经在返回栈中存在,每次启动都会创建一个新的Activity实例
- singleTop:在启动Activity时,如果发现返回栈的栈顶已经是该Activity时,则可以直接使用它,不再创建新的Activity实例
- singleTask:每次启动Activity时,系统首先会检查返回栈中是否存在该Activity实例,如果发现已经存在则直接使用该实例,并将该Activity之上的所有Activity都出栈,如果没有咋创建一个新的Activity
- singleInstance:系统会启用一个新的返回栈来管理这个Activity。
Activity实践
如何知道当前是哪一个Activity
? 先创建一个BaseActivity,然后让此类成为其他Activity类的父类,然后就会打印出当前所在类的类名
open class BaseActivity: AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
Log.d("BaseActivity", javaClass.simpleName)
}
}
随时退出Activity
? 新建一个单例类ActivityCollector作为Activity的集合,在创建时将Activity加入到集合中,然后在退出键中调用finishAll函数
object ActivityCollector{
private val activities = ArrayList<Activity>()
fun addActivity(activity:Activity){
activities.add(activity)
}
fun removeActivity(activity:Activity){
activities.add(activity)
}
fun finishAll(){
for(activity in activities){
if(!activity.isFinishing){
activity.finish()
}
}
activities.clear()
}
}
参考文献
郭霖-第一行代码第三版
|