第一行代码 第三版 第三章 活动

第三章 Activity

3.2 Activity的基本用法

3.2.4 Toast

val button1: Button = findViewById(R.id.button1)
        button1.setOnClickListener{
            Toast.makeText(this,"You clicked Button 1",Toast.LENGTH_SHORT).show()
        }
  • 省略 findViewById 的方法
  1. build.gradle中导入
id 'kotlin-android'
id 'kotlin-android-extensions'
  1. 直接使用控件id
   button1.setOnClickListener{
            Toast.makeText(this,"You clicked Button 1",Toast.LENGTH_SHORT).show()
        }

3.2.5 Menu

  1. Res -> menu -> main
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/add_item"
        android:title="Add">
    </item>

    <item android:id="@+id/remove_item"
        android:title="Remove">
    </item>

</menu>
  1. 重写 onCreateOptionsMenu( )
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main,menu)
        return true
    }
  1. 重写 onOptionsItemSelected( )
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_LONG).show()
        }
        return true
    }
  • kotlin 的语法糖
val book = Book()
book.pages = 500 //背后调用了set方法
val bookPages = book.pages //背后调用了get方法

3.2.6 销毁一个活动

button1.setOnClickListener { finish() }

3.3 Intent

3.3.1 使用显示Intent

  1. 创建 SecondActivity.class
  2. 修改activity_second.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".SecondActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:text="Button 2"
        ></Button>

</LinearLayout>
  1. 跳转
button1.setOnClickListener {
            val intent = Intent(this,SecondActivity::class.java)
            startActivity(intent)
        }

3.3.2 隐式 Intent

  1. 指定要跳转的活动的action 和 category
  <activity
            android:name=".SecondActivity"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.example.activitytext.ACTION_START"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>

        </activity>
  1. 跳转
button1.setOnClickListener {
            val intent=  Intent("com.example.activitytext.ACTION_START")
            startActivity(intent)
        }

注:

  • Action 只有一个,category 可以指定多个
  • 这条写了之后才能自己指定其他 category
  1. 指定要跳转的活动的action 和 category
<activity
            android:name=".SecondActivity"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.example.activitytext.ACTION_START"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="com.example.activitytest.MY_CATEGORY"></category>
            </intent-filter>

        </activity>
  1. 跳转
button1.setOnClickListener {
            val intent=  Intent("com.example.activitytext.ACTION_START")
            intent.addCategory("com.example.activitytest.MY_CATEGORY")
            startActivity(intent)
        }

3.3.3 更多隐式 Intent 的用法

1跳转到网页
 button1.setOnClickListener {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.data = Uri.parse("https://www.baidu.com") //data:指定当前 intent 正在操作的动作
            startActivity(intent)
        }

补充:

  1. <intent - filter> 标签中还可以再配置 标签:用于更精确指定当前activity 能够响应的数据
  • android:scheme : 数据的协议部分 https
  • android:host : 数据的主机名部分 www.baidu.com
  • android:port : 数据的端口部分,在主机名后
  • android:path : 主机名和端口后面的部分
  • android:mimeType : 指定处理的数据类型
    • 只有当 data 标签和 Intent 中的 data携带信息完全一致时才会响应
2 响应打开网页的Intent
  1. 指定要跳转的活动的配置信息
<activity android:name=".ThirdActivity"
            android:exported="true">
  					<!--     需要指定为true不然会爆红       -->
            <intent-filter tools:ignore="AppLinkUrlError">
              <!--     将警告忽略       -->
                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:scheme="https"></data>
            </intent-filter>
        </activity>
  1. 跳转
 button1.setOnClickListener {
            val intent = Intent()//需要指定action为空,不然无法跳转
            intent.data = Uri.parse("https://www.baidu.com")
            startActivity(intent)
        }

补充其他协议:

  • geo 显示地理位置
  • tel 表示拨打电话
3 调用系统拨打电话界面
button1.setOnClickListener {
            val intent = Intent(Intent.ACTION_DIAL)
            intent.data = Uri.parse("tel:10086")//指定协议是tel号码是10086
            startActivity(intent)
        }

3.3.4 向下一个活动传递数据

  1. 设置要传递的数据
button1.setOnClickListener {
            val data = "Hello SecondActivity"
            val intent = Intent(this,SecondActivity::class.java)
            intent.putExtra("extra_data",data)
            startActivity(intent)
        }
  1. 获取传递数据
val extraData = intent.getStringExtra("extra_data")
Log.d("SecondActivity", "extra data is $extraData")

补充获取传递来的不同数据:

  • 整型 getIntentExtra
  • 字符串 同上
  • 布尔型 getBooleanExtra

3.3.5 返回传递数据给上一个活动

  1. 打开活动
button1.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            startActivityForResult(intent,1)//利用请求码标记打开的活动
        }
  1. 处理返回数据
button2.setOnClickListener {
            val intent =  Intent()
            intent.putExtra("data_return","Hello FirstActivity")
            setResult(RESULT_OK,intent)//结果码也可以为RESULT_CANCELED,这个方法用于向上个活动返回处理结果
            finish()
        }
  1. 获得返回数据
 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {//过滤是否请求码是否为1的活动
            1 -> {
                if (resultCode == RESULT_OK) {//利用处理结果进行过滤
                    val returnedData = data?.getStringExtra("data_return")//?.后面为空时不操作,不为空时进行
                    Log.d("FirstActivity", "returned data is $returnedData")
                }
            }
        }
    }

补充:按下back时的回调

override fun onBackPressed() {
  			//不需要调用父类的构造方法,否则会不执行
        val intent =  Intent()
        intent.putExtra("data_return","Hello FirstActivity")
        setResult(RESULT_OK,intent)
        finish()
    }

3.4 活动的声明周期

3.4.2 活动状态

  1. 运行状态 活动处于栈顶
  2. 暂停状态 如对话框下
  3. 停止状态 完全不可见,仍然会保存相应的状态和成员变量,但是有可能会被回收
  4. 销毁状态 从返回栈中移除

3.4.3 活动的生存期

  • onCreate 活动第一次创建的时候调用。一般加载布局、绑定实践
  • onStart 活动由不可见到可见的时候调用
  • onResume 活动准备好和用户交互的时候调用。处于栈顶
  • onPause 活动准备启动或恢复另一个活动的时候调用。一般将消耗CPU的资源释放掉,保存一些关键数据
  • onStop 活动完全不可见的时候调用。和上面的区别在于,如果启动的是对话框式的活动,上面的方法会执行,这个不会。
  • onDestroy 活动销毁之前调用,之后被销毁
  • onRestart 这个方法由停止状态到运行状态之前调用,也就是活动重新启动了

上面的方法两两配对,分为三种生存期。

  • 完整生存期。onCreate和onDestroy之间,一般在前者会完成初始化操作,后者会释放内存。
  • 可见生存期。onStart 和 onStop 之间,活动对用户总是可见,虽然可能无法进行交互。一般前者会对资源进行加载,后者对资源进行释放。
  • 前台生存期。onResume和onPause,在这个生存期,活动总是可以和用户进行交互的,接触最多。

3.4.4 体验生命周期

  1. 创建三个活动 主活动,NormalActivity、DialogActivity(主题为Dialog),主活动代码:
 private val TAG = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d(TAG, "onCreate: ")
        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()
    }
  1. 主活动布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/startNormalActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start NormalActivity"
            >
    </Button>

    <Button
        android:id="@+id/startDialogActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity"
        >
    </Button>

</LinearLayout>

当打开项目时 onCreate - onStart - onResume

打开normalActivity时 onPause - onStop

回来时 onStart - onResume

打开DialogActivity onPause

回来时 onResume

3.4.5 活动被回收之前的处理方法

  1. 重写方法存数据(注:一定要重写一个参数的这个方法,两个参数的不行)
override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData = "Something you just typed"
        outState.putString("data_key",tempData)
    }
  1. 取出数据
if (savedInstanceState != null) {
            val tempData = savedInstanceState.getString("data_key")
            Log.d(TAG, tempData+"")
        }

补充:

  1. 横竖屏的时候会重新创建活动,可以利用这个方法来保存数据。
  2. 传递数据的时候可以先将数据存在Buddle里然后再存到Intent里,然后通过Intent的套娃取出

3.5 活动的启动模式

3.5.1 standard

默认的启动模式,每次启动活动,都会创建该活动的实例

 Log.d("FirstActivity", this.toString())
        button1.setOnClickListener {
//            val intent = Intent(this, SecondActivity::class.java)
//            startActivityForResult(intent,1)
            val intent = Intent(this, FirstActivity::class.java)
            startActivity(intent)
        }

3.5.2 singleTop

当活动处于栈顶的时候,启动该活动不会再创建这活动而是继续利用这个活动,但是不处于栈顶的时候还是会创建

3.5.3 singleTask

当活动已经在返回栈中存在,如果其他活动继续打开一个该活动,则这个活动之上的所有活动都会关闭,这个活动会重新回到栈顶,该活动执行onRestart其他活动执行onDestroy

3.5.4 singleInstance

如果其他程序和我的程序要共用一个活动,利用这个启动模式就可以创建一个新的共用的返回栈来共同管理这个活动

3.6 活动的最佳实践

3.6.1 知晓当前活动是哪一个活动

  1. 创建一个基类活动 新建 - Kotlin 类/文件
open class BaseActivity : AppCompatActivity(){
    private val TAG = "BaseActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, javaClass.simpleName)//获取当前实例的Class对象

    }
}
  1. 然后让所有其他活动继承它

3.6.2 随时随地的退出程序

  1. 创建专门的集合对所有的活动进行管理
object ActivityCollector {
    private val activities = ArrayList<Activity>()

    fun addActivity(activity: Activity){
        activities.add(activity)
    }

    fun removeActivity(activity: Activity){
        activities.remove(activity)
    }

    fun finishAll(){
        for(activity in activities){
            if (!activity.isFinishing) {
                activity.finish()
            }
        }
        activities.clear()
    }
}
  1. 修改基类活动里的方法
open class BaseActivity : AppCompatActivity(){
    private val TAG = "BaseActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, javaClass.simpleName)//获取当前实例的Class对象
        ActivityCollector.addActivity(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }
}
  1. 再要退出的地方调用
ActivityCollector.finishAll()
android.os.Process.killProcess(android.os.Process.myPid())//杀掉当前进程

3.6.3 启动活动的最佳写法

好处是很方便的知道要启动的活动需要传递哪些参数过去

  1. 在要启动的活动写下如下代码
 companion object{//类似java的静态方法
        fun actionStart(context: Context, data1: String, data2: String) {//通过调用这个方法就知道要传入哪些参数
            val intent = Intent(context, SecondActivity::class.java)
            intent.putExtra("param1", data1)
            intent.putExtra("param2", data2)
            context.startActivity(intent)
        }
    }
  1. 启动上面的活动
SecondActivity.actionStart(this,"data1","data2")

3.7 Kotlin 标准函数和静态方法

3.7.1 标准函数 with、run和apply

最基础的代码

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val builder = StringBuilder()
    builder.append("Start eating fruits.\n")
    for (fruit in list) {
        builder.append(fruit).append("\n")
    }
    builder.append("Ate all fruits.")
    val result =  builder.toString()
    println(result)
}

利用以下三个函数简化

1.with
val result = with(obj){
  //这里是obj的上下文
  "value"//with的返回值
}

with 传入的参数之后整个方法的上下文就是该参数,所以后面可以直接使用 append 和 toString

最后一行是with的返回值

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = with(StringBuilder()) {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")
        toString()
    }
    println(result)
}
2.run
val result = obj.run{
  //这里是obj的上下文
  "value" // run 函数的返回值
}

利用对象的 run 方法,之后整个方法都是该对象的上下文

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = StringBuilder().run {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")
        toString()
    }
    println(result)

}
3.apply
val result = obj.apply{
  //这里是obj的上下文
}
//result == obj

该方法和 run 的使用几乎一样,不过没有返回值,返回使用 apply 的对象

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = StringBuilder().apply {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")      
    }
    println(result.toString())
}
  • 补充:对启动活动并且传参的方式进行简化。当要传递的参数很多时很方便

原始代码:

val intent = Intent(context, SecondActivity::class.java)
intent.putExtra("param1", data1)
intent.putExtra("param2", data2)
context.startActivity(intent)

利用 apply 进行简化

val intent = Intent(context,SecondActivity::class.java).apply{
  putExtra("param1","data1")
  putExtra("param2","data2")
}
context.startActivity(intent)

3.7.2 定义静态方法

  1. 单例类:不是静态方法,效果相同
object Util{
  fun doAction(){
    println("do action")
  }
}

//调用
Util.doAction()

缺点:类中所有方法都变成了类似静态的效果

  1. 利用companion object:不是静态方法,效果相同
class Util{
  fun doAction1{
    println("do action1")
  }
  
  companion object{
    fun doAction2{
      println("do action2")
    }
  }
}

//调用
Util.doAction2()
  1. 注解:是静态方法
class Util{
  fun doAction1{
    println("do action1")
  }
  
  companion object{
    
    @JvmStatic//只能加在但单例类或companion object上
    fun doAction2{
      println("do action2")
    }
  }
}
  1. 顶层方法:里面的方法都是静态的

  2. new Kotlin File/Class - Helper.kt

  3. kotlin中调用,直接使用方法。java中调用 HelperKt.doSomething( )# 第三章 Activity

3.2 Activity的基本用法

3.2.4 Toast

val button1: Button = findViewById(R.id.button1)
        button1.setOnClickListener{
            Toast.makeText(this,"You clicked Button 1",Toast.LENGTH_SHORT).show()
        }
  • 省略 findViewById 的方法
  1. build.gradle中导入
id 'kotlin-android'
id 'kotlin-android-extensions'
  1. 直接使用控件id
   button1.setOnClickListener{
            Toast.makeText(this,"You clicked Button 1",Toast.LENGTH_SHORT).show()
        }

3.2.5 Menu

  1. Res -> menu -> main
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/add_item"
        android:title="Add">
    </item>

    <item android:id="@+id/remove_item"
        android:title="Remove">
    </item>

</menu>
  1. 重写 onCreateOptionsMenu( )
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main,menu)
        return true
    }
  1. 重写 onOptionsItemSelected( )
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_LONG).show()
        }
        return true
    }
  • kotlin 的语法糖
val book = Book()
book.pages = 500 //背后调用了set方法
val bookPages = book.pages //背后调用了get方法

3.2.6 销毁一个活动

button1.setOnClickListener { finish() }

3.3 Intent

3.3.1 使用显示Intent

  1. 创建 SecondActivity.class
  2. 修改activity_second.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".SecondActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:text="Button 2"
        ></Button>

</LinearLayout>
  1. 跳转
button1.setOnClickListener {
            val intent = Intent(this,SecondActivity::class.java)
            startActivity(intent)
        }

3.3.2 隐式 Intent

  1. 指定要跳转的活动的action 和 category
  <activity
            android:name=".SecondActivity"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.example.activitytext.ACTION_START"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>

        </activity>
  1. 跳转
button1.setOnClickListener {
            val intent=  Intent("com.example.activitytext.ACTION_START")
            startActivity(intent)
        }

注:

  • Action 只有一个,category 可以指定多个
  • 这条写了之后才能自己指定其他 category
  1. 指定要跳转的活动的action 和 category
<activity
            android:name=".SecondActivity"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.example.activitytext.ACTION_START"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="com.example.activitytest.MY_CATEGORY"></category>
            </intent-filter>

        </activity>
  1. 跳转
button1.setOnClickListener {
            val intent=  Intent("com.example.activitytext.ACTION_START")
            intent.addCategory("com.example.activitytest.MY_CATEGORY")
            startActivity(intent)
        }

3.3.3 更多隐式 Intent 的用法

1跳转到网页
 button1.setOnClickListener {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.data = Uri.parse("https://www.baidu.com") //data:指定当前 intent 正在操作的动作
            startActivity(intent)
        }

补充:

  1. <intent - filter> 标签中还可以再配置 标签:用于更精确指定当前activity 能够响应的数据
  • android:scheme : 数据的协议部分 https
  • android:host : 数据的主机名部分 www.baidu.com
  • android:port : 数据的端口部分,在主机名后
  • android:path : 主机名和端口后面的部分
  • android:mimeType : 指定处理的数据类型
    • 只有当 data 标签和 Intent 中的 data携带信息完全一致时才会响应
2 响应打开网页的Intent
  1. 指定要跳转的活动的配置信息
<activity android:name=".ThirdActivity"
            android:exported="true">
  					<!--     需要指定为true不然会爆红       -->
            <intent-filter tools:ignore="AppLinkUrlError">
              <!--     将警告忽略       -->
                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:scheme="https"></data>
            </intent-filter>
        </activity>
  1. 跳转
 button1.setOnClickListener {
            val intent = Intent()//需要指定action为空,不然无法跳转
            intent.data = Uri.parse("https://www.baidu.com")
            startActivity(intent)
        }

补充其他协议:

  • geo 显示地理位置
  • tel 表示拨打电话
3 调用系统拨打电话界面
button1.setOnClickListener {
            val intent = Intent(Intent.ACTION_DIAL)
            intent.data = Uri.parse("tel:10086")//指定协议是tel号码是10086
            startActivity(intent)
        }

3.3.4 向下一个活动传递数据

  1. 设置要传递的数据
button1.setOnClickListener {
            val data = "Hello SecondActivity"
            val intent = Intent(this,SecondActivity::class.java)
            intent.putExtra("extra_data",data)
            startActivity(intent)
        }
  1. 获取传递数据
val extraData = intent.getStringExtra("extra_data")
Log.d("SecondActivity", "extra data is $extraData")

补充获取传递来的不同数据:

  • 整型 getIntentExtra
  • 字符串 同上
  • 布尔型 getBooleanExtra

3.3.5 返回传递数据给上一个活动

  1. 打开活动
button1.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            startActivityForResult(intent,1)//利用请求码标记打开的活动
        }
  1. 处理返回数据
button2.setOnClickListener {
            val intent =  Intent()
            intent.putExtra("data_return","Hello FirstActivity")
            setResult(RESULT_OK,intent)//结果码也可以为RESULT_CANCELED,这个方法用于向上个活动返回处理结果
            finish()
        }
  1. 获得返回数据
 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {//过滤是否请求码是否为1的活动
            1 -> {
                if (resultCode == RESULT_OK) {//利用处理结果进行过滤
                    val returnedData = data?.getStringExtra("data_return")//?.后面为空时不操作,不为空时进行
                    Log.d("FirstActivity", "returned data is $returnedData")
                }
            }
        }
    }

补充:按下back时的回调

override fun onBackPressed() {
  			//不需要调用父类的构造方法,否则会不执行
        val intent =  Intent()
        intent.putExtra("data_return","Hello FirstActivity")
        setResult(RESULT_OK,intent)
        finish()
    }

3.4 活动的声明周期

3.4.2 活动状态

  1. 运行状态 活动处于栈顶
  2. 暂停状态 如对话框下
  3. 停止状态 完全不可见,仍然会保存相应的状态和成员变量,但是有可能会被回收
  4. 销毁状态 从返回栈中移除

3.4.3 活动的生存期

  • onCreate 活动第一次创建的时候调用。一般加载布局、绑定实践
  • onStart 活动由不可见到可见的时候调用
  • onResume 活动准备好和用户交互的时候调用。处于栈顶
  • onPause 活动准备启动或恢复另一个活动的时候调用。一般将消耗CPU的资源释放掉,保存一些关键数据
  • onStop 活动完全不可见的时候调用。和上面的区别在于,如果启动的是对话框式的活动,上面的方法会执行,这个不会。
  • onDestroy 活动销毁之前调用,之后被销毁
  • onRestart 这个方法由停止状态到运行状态之前调用,也就是活动重新启动了

上面的方法两两配对,分为三种生存期。

  • 完整生存期。onCreate和onDestroy之间,一般在前者会完成初始化操作,后者会释放内存。
  • 可见生存期。onStart 和 onStop 之间,活动对用户总是可见,虽然可能无法进行交互。一般前者会对资源进行加载,后者对资源进行释放。
  • 前台生存期。onResume和onPause,在这个生存期,活动总是可以和用户进行交互的,接触最多。

3.4.4 体验生命周期

  1. 创建三个活动 主活动,NormalActivity、DialogActivity(主题为Dialog),主活动代码:
 private val TAG = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d(TAG, "onCreate: ")
        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()
    }
  1. 主活动布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/startNormalActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start NormalActivity"
            >
    </Button>

    <Button
        android:id="@+id/startDialogActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity"
        >
    </Button>

</LinearLayout>

当打开项目时 onCreate - onStart - onResume

打开normalActivity时 onPause - onStop

回来时 onStart - onResume

打开DialogActivity onPause

回来时 onResume

3.4.5 活动被回收之前的处理方法

  1. 重写方法存数据(注:一定要重写一个参数的这个方法,两个参数的不行)
override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData = "Something you just typed"
        outState.putString("data_key",tempData)
    }
  1. 取出数据
if (savedInstanceState != null) {
            val tempData = savedInstanceState.getString("data_key")
            Log.d(TAG, tempData+"")
        }

补充:

  1. 横竖屏的时候会重新创建活动,可以利用这个方法来保存数据。
  2. 传递数据的时候可以先将数据存在Buddle里然后再存到Intent里,然后通过Intent的套娃取出

3.5 活动的启动模式

3.5.1 standard

默认的启动模式,每次启动活动,都会创建该活动的实例

 Log.d("FirstActivity", this.toString())
        button1.setOnClickListener {
//            val intent = Intent(this, SecondActivity::class.java)
//            startActivityForResult(intent,1)
            val intent = Intent(this, FirstActivity::class.java)
            startActivity(intent)
        }

3.5.2 singleTop

当活动处于栈顶的时候,启动该活动不会再创建这活动而是继续利用这个活动,但是不处于栈顶的时候还是会创建

3.5.3 singleTask

当活动已经在返回栈中存在,如果其他活动继续打开一个该活动,则这个活动之上的所有活动都会关闭,这个活动会重新回到栈顶,该活动执行onRestart其他活动执行onDestroy

3.5.4 singleInstance

如果其他程序和我的程序要共用一个活动,利用这个启动模式就可以创建一个新的共用的返回栈来共同管理这个活动

3.6 活动的最佳实践

3.6.1 知晓当前活动是哪一个活动

  1. 创建一个基类活动 新建 - Kotlin 类/文件
open class BaseActivity : AppCompatActivity(){
    private val TAG = "BaseActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, javaClass.simpleName)//获取当前实例的Class对象

    }
}
  1. 然后让所有其他活动继承它

3.6.2 随时随地的退出程序

  1. 创建专门的集合对所有的活动进行管理
object ActivityCollector {
    private val activities = ArrayList<Activity>()

    fun addActivity(activity: Activity){
        activities.add(activity)
    }

    fun removeActivity(activity: Activity){
        activities.remove(activity)
    }

    fun finishAll(){
        for(activity in activities){
            if (!activity.isFinishing) {
                activity.finish()
            }
        }
        activities.clear()
    }
}
  1. 修改基类活动里的方法
open class BaseActivity : AppCompatActivity(){
    private val TAG = "BaseActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, javaClass.simpleName)//获取当前实例的Class对象
        ActivityCollector.addActivity(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }
}
  1. 再要退出的地方调用
ActivityCollector.finishAll()
android.os.Process.killProcess(android.os.Process.myPid())//杀掉当前进程

3.6.3 启动活动的最佳写法

好处是很方便的知道要启动的活动需要传递哪些参数过去

  1. 在要启动的活动写下如下代码
 companion object{//类似java的静态方法
        fun actionStart(context: Context, data1: String, data2: String) {//通过调用这个方法就知道要传入哪些参数
            val intent = Intent(context, SecondActivity::class.java)
            intent.putExtra("param1", data1)
            intent.putExtra("param2", data2)
            context.startActivity(intent)
        }
    }
  1. 启动上面的活动
SecondActivity.actionStart(this,"data1","data2")

3.7 Kotlin 标准函数和静态方法

3.7.1 标准函数 with、run和apply

最基础的代码

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val builder = StringBuilder()
    builder.append("Start eating fruits.\n")
    for (fruit in list) {
        builder.append(fruit).append("\n")
    }
    builder.append("Ate all fruits.")
    val result =  builder.toString()
    println(result)
}

利用以下三个函数简化

1.with
val result = with(obj){
  //这里是obj的上下文
  "value"//with的返回值
}

with 传入的参数之后整个方法的上下文就是该参数,所以后面可以直接使用 append 和 toString

最后一行是with的返回值

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = with(StringBuilder()) {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")
        toString()
    }
    println(result)
}
2.run
val result = obj.run{
  //这里是obj的上下文
  "value" // run 函数的返回值
}

利用对象的 run 方法,之后整个方法都是该对象的上下文

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = StringBuilder().run {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")
        toString()
    }
    println(result)

}
3.apply
val result = obj.apply{
  //这里是obj的上下文
}
//result == obj

该方法和 run 的使用几乎一样,不过没有返回值,返回使用 apply 的对象

fun main(){
    val list = listOf("Apple","Banana","Orange","Pear","Grape")
    val result = StringBuilder().apply {
        append("Start eating fruit.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruit.")      
    }
    println(result.toString())
}
  • 补充:对启动活动并且传参的方式进行简化。当要传递的参数很多时很方便

原始代码:

val intent = Intent(context, SecondActivity::class.java)
intent.putExtra("param1", data1)
intent.putExtra("param2", data2)
context.startActivity(intent)

利用 apply 进行简化

val intent = Intent(context,SecondActivity::class.java).apply{
  putExtra("param1","data1")
  putExtra("param2","data2")
}
context.startActivity(intent)

3.7.2 定义静态方法

  1. 单例类:不是静态方法,效果相同
object Util{
  fun doAction(){
    println("do action")
  }
}

//调用
Util.doAction()

缺点:类中所有方法都变成了类似静态的效果

  1. 利用companion object:不是静态方法,效果相同
class Util{
  fun doAction1{
    println("do action1")
  }
  
  companion object{
    fun doAction2{
      println("do action2")
    }
  }
}

//调用
Util.doAction2()
  1. 注解:是静态方法
class Util{
  fun doAction1{
    println("do action1")
  }
  
  companion object{
    
    @JvmStatic//只能加在但单例类或companion object上
    fun doAction2{
      println("do action2")
    }
  }
}
  1. 顶层方法:里面的方法都是静态的

  2. new Kotlin File/Class - Helper.kt

  3. kotlin中调用,直接使用方法。java中调用 HelperKt.doSomething( )

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蒋的学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值