20220423-安卓基础学习(2)

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);
        //加载一个布局,传入布局文件的ID
        setContentView(R.layout.first_layout)
        Log.d("FirstActivity", "OnCreate execute")
        //val button1:Button = findViewById(R.id.button_1)
        button_1.setOnClickListener{
            //三个参数,第一个是要求的上下文即activity本身,第二个是内容,第三个是显式时长
            Toast.makeText(this, "You clicked Button1", Toast.LENGTH_SHORT).show()
            //val intent = Intent(this, ThirdActivity::class.java)
            val intent = Intent(Intent.ACTION_VIEW)
            intent.data = Uri.parse("https://www.baidu.com")
            startActivity(intent)
        }
    }
//直接使用在布局中的button1变量

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
    //ture表示显示菜单,false表示不显示
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    //通过itemId判断点击的是哪一个菜单项
    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")
    //intent.addCategory("com.example.activitytest.MY_CATEGORY")
    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()
    }
}

参考文献

郭霖-第一行代码第三版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值