📜  Kotlin协程的作用域

📅  最后修改于: 2021-05-10 13:43:34             🧑  作者: Mango

先决条件:

  • Android上的Kotlin协程
  • Kotlin协程中的挂起函数

Kotlin协程的范围可以定义为执行Kotlin协程的限制。范围帮助预测协程的生命周期。 Kotlin协程基本上有3个作用域

  1. 全球范围
  2. 生命周期范围
  3. ViewModel范围

要在Build.gradle中导入的依赖项(应用程序级文件)

将以下依赖项导入到build.gradle(应用程序)级别的文件中。

1.全球范围

全球范围是启动协程的方式之一。当协程在全球范围内启动时,它们的寿命与应用程序一样长。如果协程完成了一项工作,它将被销毁,直到应用程序死亡后才能存活,但是让我们想象一下这样一种情况:协程还有一些工作或指令要做,突然我们结束了应用程序,那么协程将因为协程的最大寿命等于应用程序的寿命,所以它们也会死亡。在全球范围内启动的协程将在单独的线程中启动。下面的示例显示在全局范围内的协程在单独的线程中启动。

Kotlin
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
  
class MainActivity : AppCompatActivity() {
    val TAG = "Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch {
            Log.d(TAG, Thread.currentThread().name.toString())
        }
        Log.d("Outside Global Scope", Thread.currentThread().name.toString())
    }
}


XML


  
    


Kotlin
// program for main activity which intent to another activity
// it uses global scope to launch the coroutine
  
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
const val TAG = "Main Activity"
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        btnStartActivity.setOnClickListener {
            // coroutine will launch when button got pressed
            GlobalScope.launch {
                // infinite loop
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
  
            GlobalScope.launch {
                delay(5000L)
                // new activity will get intended after 5 sec
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                // calling finish() method,so that first activity will not be alive
                // after being intended to second activity
                finish()
            }
        }
    }
}


XML


  
    
    


Kotlin
// program for second activity
  
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
  
class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.i("Second Activity", "Second Activity Running ....")
        Toast.makeText(this, "Second Activity", Toast.LENGTH_SHORT).show()
    }
}


Kotlin
// program to show how lifecycle scope works
  
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
const val TAG = "Main Activity"
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        btnStartActivity.setOnClickListener {
            // launching the coroutine in the lifecycle scope
            lifecycleScope.launch {
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
  
            GlobalScope.launch {
                delay(5000L)
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                finish()
            }
        }
    }
}


以下是上述程序的日志输出:

日志输出

众所周知,在全局范围内启动的协程与应用程序一样有效,但是开发人员需要协程与应用程序一样有效的机会很少。在全球范围内启动协程的主要问题是,当启动协程的活动死亡时,协程不会随着活动而死亡,因为协程的生存期取决于应用程序的生命周期,而不是活动的生命周期。由于协程正在使用启动它的活动的资源,并且由于该活动已经死亡,因此该资源将不会被垃圾回收,因为协程仍在引用该资源。此问题可能导致内存泄漏。因此,始终使用全局范围并不总是一个好主意。让我们尝试启动一个协程,并以1秒的延迟运行无限循环,并在从启动开始延迟5秒后,通过终止第一个活动和意图转移到另一个活动,在全局范围内启动另一个协程。我们在输出中可以看到,即使以编程方式终止了第一个活动,与第一个活动相关联的协程也不会消失。让我们尝试以编程方式了解上一段中的内容。以下是activity_main.xmlMainActivity.kt文件的代码。

XML格式



  
    

科特林

// program for main activity which intent to another activity
// it uses global scope to launch the coroutine
  
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
const val TAG = "Main Activity"
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        btnStartActivity.setOnClickListener {
            // coroutine will launch when button got pressed
            GlobalScope.launch {
                // infinite loop
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
  
            GlobalScope.launch {
                delay(5000L)
                // new activity will get intended after 5 sec
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                // calling finish() method,so that first activity will not be alive
                // after being intended to second activity
                finish()
            }
        }
    }
}

转到应用程序> Java >第一个程序包名称>右键单击>新建>活动>空活动以创建新活动并将其命名为SecondActivity 。下面是activity_second.xmlSecondActivity.kt文件的代码。

XML格式



  
    
    

科特林

// program for second activity
  
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
  
class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.i("Second Activity", "Second Activity Running ....")
        Toast.makeText(this, "Second Activity", Toast.LENGTH_SHORT).show()
    }
}

输出:

从下面的注销中可以看出,即使在启动第二个活动之后,主活动的协同程序仍在运行。椭圆形的圆圈用于显示时间戳。

日志输出

2.生命周期范围

生命周期作用域与全局作用域相同,但是唯一的区别是,当我们使用生命周期作用域时,活动中启动的所有协程在活动死亡时也会死亡。这是有益的,因为即使我们的活动终止,我们的协程也不会继续运行。为了在我们的项目中实现生命周期范围,只需在生命周期范围而不是全局范围中启动协程,即可在运行无限循环的主要活动中将全局范围更改为生命周期范围。除了上面提到的主要活动的代码中的一些更改外,所有代码都将保持不变。

科特林

// program to show how lifecycle scope works
  
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
const val TAG = "Main Activity"
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        btnStartActivity.setOnClickListener {
            // launching the coroutine in the lifecycle scope
            lifecycleScope.launch {
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
  
            GlobalScope.launch {
                delay(5000L)
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                finish()
            }
        }
    }
}

日志输出:

椭圆形的圆圈用于显示时间戳。

日志输出

从上面的日志输出中可以看出,在启动第二个活动之后,主活动停止进行打印。

3. ViewModel范围

它也与生命周期作用域相同,唯一的区别是,只要视图模型处于活动状态,此范围内的协程将继续存在。 ViewModel是一个类,它通过遵循android中生命周期系统的原理来管理和存储与UI相关的数据。如果您想更深入地了解基本上视图模型类是什么,可以参考android官方文档的此链接。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处,前往由我们的专家精心策划的指南,以使您立即做好行业准备!