美文网首页kotlin
kotlin之协程一简单使用

kotlin之协程一简单使用

作者: 海晨忆 | 来源:发表于2019-07-16 18:11 被阅读10次

    个人博客:haichenyi.com。感谢关注

      kotlin协程用于线程切换,kotlin里面不需要new Thread,并且,协程的开销小于new Thread。有三种写法:runBlocking,launch,async

    既然协程的出现可以取代Thread,我们这里想要验证的是:

    1. 会不会阻塞主线程?
    2. 协程里面的代码是怎么执行的?按顺序执行还是并行?
    3. 协程里面能不能更新页面?

    依赖

      协程需要额外依赖一个库协程用于android的库,它会自动依赖官方提供的那个协程的代码库。

        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M2'
    

    runBlocking

    用法:

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            runBlocking {
                Log.e("wz", "for_start")
                for (i in 0..5) {
                    Log.e("wz", i.toString())
                }
                Log.e("wz", "for_end")
                tvName.text =  "for_end"
            }
            Log.e("wz", "runBocking外")
        }
    

    结果:


    runBlocking.png

      从打印顺序上看,runBlocking的执行顺序是从上往下执行的,并且能更新页面。回答上面的三个问题:

    1. 会阻塞线程
    2. 从上往下按顺序执行的
    3. 可以更新页面

      java里面有Thread,所以线程休眠用Thread.sleep()。kotlin里面既然协程可以取代Thread,所以,kotlin也有自己的休眠方法,也就是上面的delay(),注意,这里delay只能用在协程里面,不能用在外面。

    GlobalScope.launch

    用法:

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            GlobalScope.launch {
                Log.e("wz", "for_start")
                for (i in 0..5) {
                    Log.e("wz", i.toString())
                }
                Log.e("wz", "for_end")
                tvName.text =  "for_end"
            }
            Log.e("wz", "协程外")
        }
    

    结果:

    launch.png

      从打印顺序上面看,launch是先执行外面的代码,然后执行协程里面的代码,并且更新了页面。回答上面的三个问题:

    1. 不会阻塞线程
    2. 既然不会阻塞线程,那就是并行的
    3. 能更新页面

    GlobalScope.async

    用法:

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            GlobalScope.async {
                Log.e("wz", "for_start")
                for (i in 0..5) {
                    Log.e("wz", i.toString())
                }
                Log.e("wz", "for_end")
                tvName.text =  "for_end"
            }
            Log.e("wz", "协程外")
        }
    

    结果:

    async.png

      从打印顺序上看,跟launch是一样的,并且也更新了页面。所以结论更launch是一样的。

      都一样的话,那么launch和async有什么区别呢?他们俩的返回值不一样。launch的返回值:Job,而async的返回值:Deferred<T>。async与await()联用。

      Job是一个接口,有join,cancel,cancelAndJoin等等方法,Deferred实现了Job接口。

      launch和async的区别:launch返回值是job,而async的返回值是:把async的最后一行封装成Deferred返回。

    val job = GlobalScope.launch {
    
            }
            Log.e("wz", job.toString())
    
            runBlocking {
                val b = GlobalScope.async {
                    1111
                }.await()
                Log.e("wz", b.toString())
            }
    

    async并发

      我们项目里面有时候会碰到,我们做某个功能的时候,需要拿到两个数据A,B。我们要先算出A,接着算出B,最后,拿到这两个数据再做处理。那么,time(总) = time(A)+time(B)。

      用async,我们可以怎么处理呢?

    runBlocking {
                measureTimeMillis {
                    val n1 = GlobalScope.async { doA() }
                    val n2 = GlobalScope.async { doB() }
                    val time = n1.await() + n2.await()
                    Log.e("wz", time.toString())
                }
            }
    
    suspend fun doA(): Int {
            //做其他操作花费2秒钟
            return 3
        }
    
    suspend fun doB(): Int {
            //做其他操作花费4秒钟
            return 4
        }
    

      前面,我们得到结论async是不阻塞线程的,所以,doA和doB是同时进行的。当同时获取到A,B的结果所花费的时间,是doA和doB中花费时间长的那一个,所以,这里花费的总时间是4秒钟,而不是6秒

    相关文章

      网友评论

        本文标题:kotlin之协程一简单使用

        本文链接:https://www.haomeiwen.com/subject/pyztlctx.html