12Kotlin函数泛型协程

Posted 清风百草

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了12Kotlin函数泛型协程相关的知识,希望对你有一定的参考价值。

(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

【12】Kotlin函数泛型与协程

文章目录

1.项目增加WebView模块

package com.gdc.kotlinproject

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebSettings
import com.gdc.kotlinproject.config.Flag
import kotlinx.android.synthetic.main.activity_detail_link.*

class DetailLinkActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_detail_link)

        //1.隐藏ActionBar
        supportActionBar?.hide()
        //2.获取上个页面传递过来的url
        val mUrl: String? = intent.getStringExtra(Flag.URL_KEY)

        //3.设置WebView的一些参数
        //(1)获取WebView参数设置
        val mWebSettings:WebSettings = web_view.settings
        //(2)将图片调整到适合webview的大小
        mWebSettings.useWideViewPort = false
        //(3)支持js
        mWebSettings.javascriptEnabled = true
        //(4)支持自动加载图片
        mWebSettings.loadsImagesAutomatically = true
        /*
         *(5)利用WebView直接加载网页链接
         * - 每次启动这个activity 所加载的url网页路径肯定是不一样的 , Intent传值
         * - ?.意思是这个参数可以为空,并且程序继续运行下去
         * - !!.的意思是这个参数如果为空,就抛出异常
         */
        web_view.loadUrl(mUrl!!)

    

2.高阶函数续

2.1普通函数中定义高阶函数

2.1.1定义

/**
 * 1.普通函数中定义高阶函数
 * (1)一个参数无返回
 * myMethod:(String)-> Unit
 */
fun show1(name:String,myMethod:(String)-> Unit)
    myMethod(name)

2.2使用

fun main() 
    //1.调用方式1
    show1("Derry")
        println("输出1:$it")
    

    //1.调用方式2
    show1("张华",myMethod=
        println("输出2:$it")
    )

    //1.调用方式3
    show1("杨红",
        println("输出3:$it")
    )

2.2函数参数有默认值

fun show2(name:String="李连杰",myMethod:(String)-> Unit)
    myMethod(name)

//1.调用有默认值的
    show2
        println("输出4:$it")
    

2.3高阶函数一个形参

fun sum1(myMethod:(Int) -> Unit)
    myMethod(11)

	sum1 
        println("输出5:$it")
    

    sum1 (
        println("输出6:$it")
    )

2.4高阶函数两个形参

fun sum2(myMethod:(Int,Boolean) -> Unit)
    myMethod(11,true)

	/**
     * 1.两个参数就没法默认it
     * (1)需要手动指定参数名
     * (2)只有一个参数时就是默认的it
     */

    sum2(
        n1,b1->
    )

2.5由一个函数直接完成另一个函数的业务操作

/**
 * 1.高阶函数
 */
fun thread01(myMethod:(Int) -> String)
    var ret = myMethod(99)
    println(ret)

/**
 * 1.将Int转换为String类型
 */
fun run01(number:Int):String = "OK $number"
fun main() 
    //以前是在里面直接做业务操作
    thread01() 
        ""
    

    /**
     * 1.组合使用函数
     * (1)::run01的结果拿过来使用,意思是直接交给run01去完成thread01的业务操作
     * (2)将run01变成函数类型的对象将给thread01函数
     */
    thread01(::run01)

    //将run01变成函数类型的对象将给thread01函数
    val r01 = ::run01
    var r02 = r01
    thread01(r01)
    thread01(r02)

2.6高阶函数三数相乘

/**
 * 1.三数相乘
 * (1)高阶函数返回一个泛型
 * myMethod:(Int,Int,Int)-> R
 *
 * (2)函数也返回一个泛型
 */
fun <R> sum(n1:Int,n2:Int,n3:Int,myMethod:(Int,Int,Int)-> R):R
    return myMethod(n1,n2,n3)

fun main() 
    //Unit
    //String
    //Boolean
    //Double
    var ret = sum(10,20,30)
        i1,i2,i3 ->
        println("i1:$i1,i2:$i2,i3:$i3")
        //其他操作
        "Ok"
        true
        9999.3
    

    println(ret)

2.7给泛型增加扩展类型

val name = "张三"
val age = 24
val sex = 'M'

fun main() 
    name.myApply()
    age.myApply()
    sex.myApply()
    func().myApply()


fun func()


/**
 * (1)返回类型泛型
 * (2)给泛型增加扩展函数
 * (3)意味着类中的属性、函数都可以使用扩展函数
 */
fun <T> T.myApply()


2.8链式调用

/**
 * (1)返回类型泛型
 * (2)给泛型增加扩展函数
 * (3)意味着类中的属性、函数都可以使用扩展函数
 * (4)无参的高阶函数
 */
fun <T> T.myApply1(myMethod:() ->Unit):T
    //T:就是this
    myMethod()
    return this

    /**
     * 链式调用
     */
    val length = name.myApply1 

    .myApply1() 

    .myApply1() 

    .length as Double

2.9扩展函数高阶函数有参数

/**
 * (1)扩展函数
 * (2)返回类型泛型
 * (3)高阶函数有参数无返回值
 * myMethod:(T) -> Unit
 * (4)it == T == this
 */
fun <T> T.myAlso(myMethod:(T) -> Unit):T
    //it == T == this==name
    myMethod(this)
    return this

val d = name.myAlso 
        it.length
        println("ret:$it")
    .myAlso 
        it.length
    .myAlso 
        it.length
    .length as Double
/**
 * (1)返回值泛型R
 * (2)高阶函数返回泛型R
 * myMethod: (T) -> R
 */
fun <T,R> T.myLet(myMethod: (T) -> R):R = myMethod(this)

2.10执行自定义线程

/**
 * 1.自定义线程封装
 * (1)start:是否启动标识
 * (2)name:线程名称
 * (3)myMethod高阶函数
 * (4)返回线程
 * (5)如果启动线程就直接启动,不启动,则返回线程对象
 */
fun ktrun(
        start:Boolean = true,
        name:String ? = null,
        myMethod:() -> Unit):Thread
    val thread = object :Thread()
        override fun run() 
            super.run()

            myMethod()
        
    

    name?: "myThread1"

    if(start)
        thread.start()
    
    return thread

fun main() 
    ktrun()
        //1.耗时操作
        println("如果设置了启动线程,则执行自定义线程")
    

2.11自定义轮循器

/**
 * 自定义轮循器,传入多少次就跌代多少次
 */
fun doCounts(counts:Int,myMethod:(Int) -> Unit)
    //0-counts区间
    for(index in 0 until counts)
        myMethod(index)
    

 	doCounts(100)
        println("执行了一次下标是:$it")
    

3.项目代码优化

/**
 * (1)返回类型泛型
 * (2)给泛型增加扩展函数
 * (3)意味着类中的属性、函数都可以使用扩展函数
 * (4)无参的高阶函数
 */
fun <T> T.myApply(myMethod:T.() ->Unit):T
    //T:就是this
    myMethod()
    return this

	/**
     * 优化之前的代码
     * 1.创建客户端API接口
     * (1)WanAndroidAPI实例化
     * (2)XXXAPI实例化
     * (3)动态的实例化,可以使用到泛型
     * (4)fun <T> instanceRetrofit(apiInterface: Class<T>): T表示此为泛型方法
     * (5)apiInterface: Class<T>:表示此为泛型参数
     * (6): T表示返回类型为泛型
     */
    /*fun <T> instanceRetrofit(apiInterface: Class<T>) : T

        //1.1.1OKHttpClient请求服务器
        val okHttpclient = OkHttpClient().newBuilder()
        //1.1.1.1添加读取超时时间
            .readTimeout(10000, TimeUnit.SECONDS)
        //1.1.1.2添加连接超时时间
            .connectTimeout(10000,TimeUnit.SECONDS)
        //1.1.1.3添加写出超时时间
            .writeTimeout(10000,TimeUnit.SECONDS)
            .build()

        val retrofit:Retrofit = Retrofit.Builder()
            //1.1请求方 <-
            .baseUrl(Flag.BASE_URL)
            .client(okHttpclient)

            //1.2响应方 ->
            //1.2.1RxJava来处理
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            //1.2.2Gson来解析JavaBean
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //1.3将请求方与响应方建好后,将请求api的参数
        return retrofit.create(apiInterface)
    */


    //优化后的代码
    fun <T> instanceRetrofit(apiInterface: Class<T>) : T

        //1.1.1OKHttpClient请求服务器
        val okHttpclient = OkHttpClient().newBuilder().myApply 
            //1.1.1.1添加读取超时时间
            readTimeout(10000, TimeUnit.SECONDS)
            //1.1.1.2添加连接超时时间
            connectTimeout(10000,TimeUnit.SECONDS)
            //1.1.1.3添加写出超时时间
            writeTimeout(10000,TimeUnit.SECONDS)
        .build()


        val retrofit:Retrofit = Retrofit.Builder()
            //1.1请求方 <-
            .baseUrl(Flag.BASE_URL)
            .client(okHttpclient)

            //1.2响应方 ->
            //1.2.1RxJava来处理
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            //1.2.2Gson来解析JavaBean
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //1.3将请求方与响应方建好后,将请求api的参数
        return retrofit.create(apiInterface)
    

4.Kotlin泛型

(1)?是java泛型通配符
(2)*是Kotlin的通配符
(3)Kotlin简单平常的泛型与Java是一样的。
(4)泛型不一样的地方是out与in

4.1泛型的读取模式

private ParentClass parentClass = new ParentClass();
    
    private ChildClass childClass = new ChildClass();

    /**
     * 泛型的读取模式
     */
    public void test01()

        //(1)想实现这种多态,java是不支持的,使用权限模式解决
        //List<ParentClass> list = new ArrayList<ChildClass>();

        //(2)解决问题 ? extends ParentClass :权限获取模式,只能获取,不能修改
        List<? extends ParentClass> list = new ArrayList<ChildClass>();

        //(3)不能添加,不能对集合做修改操作
        //list.add(parentClass);
        //list.add(null);是特殊情况

        //(4)能获取
       ParentClass p = list.get(0);


        /**
         * (5)只能修改,不能获取的情况
         * ? super ChildClass,只能修改,不能获取
         */
        List<? super ChildClass> childList = new ArrayList<ParentClass>();

        //(6)能添加但是不能获取
        childList.add(childClass);

        //(7)不能获取
        //ChildClass c = childList.get(0);
    

4.2泛型的上限与下限

public class TestOutIn<T extends String> 

4.3泛型场景1可修改不能获取

	private void show(List<? extends ParentClass> list)
        //(1)能获取
        list.get(0);
        for (ParentClass p : list)

        
        
        //(2)不能修改
        //list.add(parentClass);
    

    private void test2()
        List<ChildClass> childList = new ArrayList<ChildClass>();
        //(1)show方法要求是传父类,而此处传子类,就可以修改泛型的参数
        show(childList);
    

4.4泛型场景2不可修改能获取

	/**
     * (1)不可以获取
     * (2)可以修改
     * @param list
     */
    private void show1(List<? super ChildClass> list)
        //ChildClass c = list.get(0);
        /*for(ChildClass c : list)

        */

        list.add(childClass);
    

    private void test3()
        List<ParentClass> parentList = new ArrayList<ParentClass>();
        //(1)show1方法要求是传子类,但此处传的是父类,可以修改泛型参数
        show1(parentList);
    

4.5Kotlin泛型与java泛型对应关系

4.6 in out关键字实现权限的读取模式

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktoutin
 * @file
 * @Description:
 *
 * 1.权限的读取模式
 *
 * @date 2021-6-6 20:53
 * @since appVer
 */

val parentClass = ParentClass()

val childClass = ChildClass()

fun test01()
    /**
     * 1.out 只能读取,不能修改
     *(1)同Java
     * List<? extends ParentClass> list = new ArrayList<ChildClass>();
     */
    val list : MutableList<out ParentClass> = ArrayList<ChildClass>()

    /**
     * 2.in 不能读取,只能修改
     * (1)同Java
     *  List<? super ChildClass> childList = new ArrayList<ParentClass>();
     */
    val list1 : MutableList<in ChildClass> = ArrayList<ParentClass>()

4.7限定类只能修改不能读取

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktobj
 * @file
 * @Description:
 * 1.泛型的读取模式
 *
 * (1)Student <in T>:限定该类只能修改不能读取
 *
 * (2)为了解决多个函数都需要添加泛型读取模式限定,可以直接在类上做限定,一劳永逸
 *
 * 而Java是做不到的
 *
 * @date 2021-6-6 21:31
 * @since appVer
 */ 
class Student <in T> 

    fun a1(list:T)

    

   /* fun a2(list:MutableList<in T>)

    

    fun a3(list:MutableList<in T>)

    

    fun a4(list:MutableList<in T>)

    

    fun a5(list:MutableList<in T>)

    

    fun a6(list:MutableList<in T>)

    */

    /**
     * 如此限定的好处
     */
    fun setData(data : T)

    

    /**
     * 不能从此类获取数据
     */
    /*fun getData() : T

    */


4.8限定类可以获取,不能修改

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktobj
 * @file
 * @Description:
 *
 * (1)限定类可以获取,不能修改
 *
 * @date 2021-6-6 21:42
 * @since appVer
 */
class Teacher<out T> 

    /**
     * 1.能获取
     */
    fun getData() : T? = null

    /**
     * 2.不能修改
     */
    /*fun setData(data:T)

    */

5.协程使用篇

5.1线程环境到协程环境的切换

    fun click1(view: View) = runBlocking

        /**
         * (1)由main线程切换到协程环境,默认是main线程
         * (2)runBlocking切换到的是外协程
         * (3)launch切换到的是内协程
         * (4)由main线程变为异步线程
         * aunch(Dispatchers.IO)
         * (5)轮循
         *
         */
        launch(Dispatchers.IO) 
            Log.e("click1:","lunch $Thread.currentThread().name")

            repeat(10)
                Thread.sleep(1000)
                Log.e("click:","计数中:$it")
            
        
    

5.2不使用协程更新UI

private val mOkHttpClient : OkHttpClient = OkHttpClient()
private val mRequest = Request.Builder().url("http://www.baidu.com").get().build()

fun displayMethod(textView:TextView)

    /**
     * 切换为主线程更新UI
     */以上是关于12Kotlin函数泛型协程的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin学习

怎么区别java泛型的上限和下限??

java 泛型的上限与下限

java泛型上限下限,通配符

java泛型上限下限,通配符

泛型的上限和下限的Demo