Kotlin安卓称王?Java如何调用Kotlin的高级特性?_android kt context class

31 阅读10分钟
    }

    @JvmStatic
    fun callStaticMethod2() {
        YYLogUtils.w("调用静态方法")
    }
}

}


能点出来的方法:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/45e05b6887d749da94523682baf91870~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=UNgQoh8ZIiUbnmnlvhFH91UYB7M%3D)


具体的使用:



KotlinDemo.Companion.callStaticMethod1();
KotlinDemo.callStaticMethod2();

KotlinDemo.Companion.getSchool();
KotlinDemo.Companion.setSchool("11");
KotlinDemo.industry = "xx";

##### 三、Java调用KT顶层函数/扩展函数


Kotlin的顶层函数或者叫扩展函数,我们把函数的类名加上后缀kt即可直接调用,默认的扩展函数都是可以调用的,需要注意的是加上泛型的一些方法。


比如我们的Kotlin类中定义的顶层函数



fun topLevelFun() { YYLogUtils.w("调用顶层函数") }


我们在基类中定义的一些扩展函数: CommonExt.kt:



fun Context.dp2px(dpValue: Float): Int { return (dpValue * resources.displayMetrics.density + 0.5f).toInt() }


ActivityExt.kt:



inline fun Context.gotoActivity( flag: Int = -1, bundle: Array<out Pair<String, Any?>>? = null ) { val intent = Intent(this, T::class.java).apply { if (flag != -1) { this.addFlags(flag) } if (this !is Activity) { this.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } if (bundle != null) { putExtras(bundle.toBundle()!!) } } startActivity(intent) }


我们可用的一些扩展函数和一些不可用的扩展函数:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/b24b01235d05458ba06447daf436dfda~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=GE9USzrAwN1kGORvqrFmiERafw0%3D)


可以看到 ActivityExt 类中的部分扩展函数不能使用。一些内联函数+标注泛型的扩展方法确是无法使用。(还我用的不对吗?不知道有没有大佬指点!)


##### 四、Java调用KT高阶函数


高阶函数就是可以当参数方法函数,例如最简单的高阶函数对象 `() -> Unit` 这种函数在转成 Java 的过程会生成对应的 Function 接口。我们直接 new Function 的匿名接口对象即可。


比如我们定义一些高级函数的方法:



class KotlinDemo {

fun String.setValueCallback(block: () -> Unit) {

    block()
}

fun setValueCallback2(block: () -> Unit, action: (Int) -> Int) {

    block()

    val action1 = action(1)
    YYLogUtils.w("我收到处理的值了-计算的结果:$action1")
}

}


那么我在Java中怎么调用呢?



public void demo2(View view) {

    KotlinDemo demo = new KotlinDemo();

    demo.setValueCallback("str", new Function0<Unit>() {
        @Override
        public Unit invoke() {

            ToastUtils.INSTANCE.makeText(mActivity, "我被回调了!!");

            return null;
        }
    });

    demo.setValueCallback2(new Function0<Unit>() {
        @Override
        public Unit invoke() {

            YYLogUtils.w("这里没有返回值,我回调到我就行了");

            return null;
        }
    }, new Function1<Integer, Integer>() {
        @Override
        public Integer invoke(Integer integer) {

            YYLogUtils.w("这里有返回值,回调到这里,我还需要处理运算,我的上级才能收到我处理的值");

            return integer + 10;
        }
    });

}

打印的结果:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/97188fd22e2e4a47baf2f46be5919093~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=%2B3%2BPRIBCWnkVUIKXlT5n%2BtnNvys%3D)


高阶函数的Java调用可以说是后续的基础,关于 Function 的接口,从Function1 到 Function22 Kotlin给我们定义了20多个接口对象,只是用于区分有多少个参数,本质都是一样的。


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/4b6cb697796046f384f0361f8c63060a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=gZp842%2F%2FSRKKEqtqA6nTvjgZeTg%3D)


不会真有人定义这么多参数吧,我最多用到三个参数 😅 😅


##### 五、Java调用KT的SAM方式


其实Sam是基于Kotlin的简化方式,对应Java调用Kotlin来说其实是一样的,它只适应于Kotlin。


比如:



interface MyCustomCallback {

fun onCallback()

}




---



fun interface MyCustomCallback {

fun onCallback()

}




---



fun setSamMethod(callback: MyCustomCallback) {

    callback.onCallback()
}

在Java中是一样的调用



public void demo5(View view) {

    KotlinDemo demo = new KotlinDemo();

    demo.setSamMethod(new MyCustomCallback() {
        @Override
        public void onCallback() {
            YYLogUtils.w("回调到了");
        }
    });
}

只是在Kotlin语言中new的方式不同罢了:



fun setValueCallback2(block: MyCustomCallback.() -> Unit) {

    block(object : MyCustomCallback {
        override fun onCallback() {
            YYLogUtils.w("对方调用了,然后我来继续执行")
        }
    })

}



---



fun setValueCallback2(block: MyCustomCallback.() -> Unit) {

    block(MyCustomCallback { YYLogUtils.w("对方调用了,然后我来继续执行") })

}

其实是和高阶函数的调用比较类似,只是一个是我们自己定义的接口,一个是高阶函数Java转换的Function接口,使用起来是一样的。


##### 六、Java调用KT高阶扩展函数


什么叫高阶扩展函数,其实就高阶函数,只是把原本回调的对象类型放在了前面以扩展的方式表达。**以扩展的方式定义高阶函数**,我把它叫做高阶扩展函数,但其本质还是高阶函数。


举一个很简单的例子



fun String.setValueCallback11(block: Industry.(Int) -> Unit) { block(Industry(0, this, "123", "456"), 10) }

fun String.setValueCallback12(block: (Industry, Int) -> Unit) { block(Industry(0, this, "123", "456"), 10) }


前者是高阶扩展函数,后者是高阶函数,使用的方式是一样的,只是高阶函数回调的时候一个需要用it或者指定变量接收,而高阶扩展函数只需要this接收,并且高阶扩展函数默认在回调的第一个参数上。


例如:



"test".setValueCallback11 { int ->
    YYLogUtils.w("收到回调:industry:" + this.toString() + " int:" + int)
}

"test".setValueCallback12 { industry, int ->
    YYLogUtils.w("收到回调:industry:" + industry.toString() + " int:" + int)
}

一个直接用this,另一种需要用it或者自定义名称来接收。用起来都是一样的,只是使用高阶扩展函数的话,会有一些简写方式更加方便,(如果不懂的话可能会更懵吧)


**如何定义高阶扩展函数**


这种方式有几种定义方式,以函数的类型定义为扩展函数定义和非扩展函数定义。参数又分基本类型,自定义类型,与接口类型。


下面都会讲到,先从简单的常用的讲起。


**基本数据类型:**



//这种比较常见
fun String.setValueCallback(block: String.() -> Unit) {

    block(this.length.toString())
}



---



demo.setValueCallback("test", new Function1<String, Unit>() {
    @Override
    public Unit invoke(String s) {
        YYLogUtils.w("看看我收到的什么:" + s);
        return null;
    }
});

使用扩展方法再加上高阶扩展函数的参数,我们就可以直接使用this。就可以直接拿到数据设置回调。


这样的方式主要用于**直接回调给对方**


打印结果:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/15bc6e29e44e4186a4fe32ebc6d981d5~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=RXQ5uN1W0f3Hr%2B11aVxtwx1aY%2BM%3D)


**自定义对象类型:**


如果我们修改高阶扩展函数的对象,你看这样就不协调了,String的扩展方法,确实回调的Industry对象



fun String.setValueCallback(block: Industry.() -> Unit) {
    //直接回调给对方
    block(this.length.toString())
}

如果还是使用String的参数,上面的用法就会报错,我们应该回调Industry的对象。



fun String.setValueCallback(block: Industry.() -> Unit) {
    //直接回调给对方
    block(Industry(0, this, "123", "456"))
}

我们把String的扩展this当做Industry的构造参数的一个属性,这样才能回调一个Industry对象给Java


看Log打印,回调的就是Industry


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/29cd196dc4104aed9201d97cb4a5324e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=4Z6D47Ixd7oq5gdFMw6e%2FiI8xjM%3D)


**接口类型:**


除了用对象做高阶扩展函数,我们还能以接口的形式做高阶扩展函数。



//还能设置不相关的对象扩展 fun setValueCallback2(block: MyCustomCallback.() -> Unit) {

    block(object : MyCustomCallback {
        override fun onCallback() {

        }
    })

}

使用接口类型做我参数的扩展,这里我们需要new一个对象给调用者。就导致这种方法是 **回调给对方调用再通过对方回调给自己**


在Java的代码中我们可以直接调用接口的方法,让对方去执行



public void demo3(View view) {
    KotlinDemo demo = new KotlinDemo();

    demo.setValueCallback2(new Function1<MyCustomCallback, Unit>() {
        @Override
        public Unit invoke(MyCustomCallback myCustomCallback) {

            //调用
            myCustomCallback.onCallback();

            return null;
        }
    });
}

打印的Log如下:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/cd916c018e3c4167b4143e499b3f0c13~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=IbZz%2BcKYsJ%2BFkhPBgEgZy%2FnPl50%3D)


不管是用Java代码去调用,还是用Ktolin代码调用,本质是一样的。


需要注意方法的参数,是否是基本类型的高阶扩展函数,还是对象类型的高阶扩展函数,还是接口类型的高阶扩展函数。这会导致是回调的方式不同。


而方法本身是否是扩展函数,则相对没有那么重要,主要是看方便我们能否使用this,如果需要this对象就用扩展函数,如果不需要那我们可以不用。


**关于高阶扩展函数的补充**


其实前文也说了,本质还是高阶扩展函数,只是区分是否用this接收而已,所以高阶扩展函数也是针对Kotlin来说的,对Java语言来说,还是以高阶函数的方式来处理。


举例说明:



fun String.setValueCallback1(block: String.(Int) -> Unit) { block(this, 10) }


Java代码中使用这一种高阶扩展函数:



KotlinDemoKt.setValueCallback1("test", new Function2<String, Integer, Unit>() {
     @Override
    public Unit invoke(String s, Integer integer) {
        YYLogUtils.w("收到回调:s:" + s + "integer:" + integer);
        return null;
    }
});

可以看到Java语言可不管你扩不扩展,对它来说就是两个参数,我也不能用this什么的,我只能用转换过的Function。可以看到Kotlin虽然定义的是Int,但是Java接收到的是 Function2 是两个参数的回调,顺序是第一个是String第二个是Int。


前文讲到的基本类型,对象类型,接口类型,这里做一个全部的Demo



fun String.setValueCallback0(block: (Int) -> Unit) { block(10) }

fun String.setValueCallback1(block: String.(Int) -> Unit) { block(this, 10) }

fun String.setValueCallback11(block: Industry.(Int) -> Unit) { block(Industry(0, this, "123", "456"), 10) }

fun String.setValueCallback12(block: (Industry, Int) -> Unit) { block(Industry(0, this, "123", "456"), 10) }

fun String.setValueCallback13(block: MyCustomCallback.(String) -> Unit) {

block(MyCustomCallback { YYLogUtils.w("对方调用了,然后我来继续执行") }, this + "加点后缀")

}


为了方便理解,回调的时候我故意没有省略this,一般大家写代码都会省略this。


如果是Kotlin代码调用,很简单



    "test".setValueCallback1 { int ->
        YYLogUtils.w("收到回调:str:" + this + " int:" + int)
    }

    "test".setValueCallback11 { int ->
        YYLogUtils.w("收到回调:industry:" + this.toString() + " int:" + int)
    }

    "test".setValueCallback12 { industry, int ->
        YYLogUtils.w("收到回调:industry:" + industry.toString() + " int:" + int)
    }

    "test".setValueCallback13 { str ->
        YYLogUtils.w("收到回调:callback:" + this + " str:" + str)
        this.onCallback()
    }

打印如下:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/e4d88ec8219b44598856b5b6afa2279f~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=%2BGhaTH5EJ9zfxsIokdUs26WSp3w%3D)


如果是Java代码调用:



public void demo2(View view) {

    KotlinDemo demo = new KotlinDemo();

    KotlinDemoKt.setValueCallback1("test", new Function2<String, Integer, Unit>() {
        @Override
        public Unit invoke(String s, Integer integer) {
            YYLogUtils.w("收到回调:s:" + s + "integer:" + integer);
            return null;
        }
    });

    KotlinDemoKt.setValueCallback11("test", new Function2<Industry, Integer, Unit>() {
        @Override
        public Unit invoke(Industry industry, Integer integer) {
            YYLogUtils.w("收到回调:industry:" + this.toString() + " integer:" + integer);
            return null;

        }
    });

    KotlinDemoKt.setValueCallback12("test", new Function2<Industry, Integer, Unit>() {
        @Override
        public Unit invoke(Industry industry, Integer integer) {
            YYLogUtils.w("收到回调:industry:" + this.toString() + " integer:" + integer);
            return null;

        }
    });

    KotlinDemoKt.setValueCallback13("test", new Function2<MyCustomCallback, String, Unit>() {
        @Override
        public Unit invoke(MyCustomCallback myCustomCallback, String s) {

            YYLogUtils.w("收到回调:callback:" + myCustomCallback.toString() + " str:" + s);
            myCustomCallback.onCallback();

            return null;
        }
    });

可以看到这种方式对Java是没有效果的,和高阶函数的使用是一模一样的。


打印Log如下:


![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/ff5d36d8ad4e42beb2948a181485d855~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MDY4Mzc0MTQxMzQ0:q75.awebp?rk3s=f64ab15b&x-expires=1771253461&x-signature=ugKm5CSbi%2Fl0awxI869%2Bg%2FxeNR8%3D)


结论:这种以高阶函数定义的扩展函数,对Java的调用来说没效果,只是Kotin语言的一些简化。


##### 七、Java调用KT的DSL方式


按照顺序一步一步的来,我们会了Java调用扩展函数和高阶扩展函数,那么在此基础上我们就能完成Kotlin的DSL调用了。


我们都知道DSL的简化规则是基于高阶扩展函数间接实现的(也可以直接高阶函数实现,不过使用的时候就需要用it去点出方法,不够优雅,所以一般大家都用高阶扩展函数的方式去实现)。


那么我们学了Java调用高阶扩展函数之后,再回头看看DSL的调用有什么不同。


之前的文章已经讲过DSL定义的几种方式,这里不多BB,直接快速过一次代码:



fun TestNet.setOnSuccessCallbackDsl(init: SuccessCallbackImpl.() -> Unit) { val listener = SuccessCallbackImpl() init(listener) this.setOnSuccessCallback(listener) }

var mCallback: SuccessCallback? = null

fun setOnSuccessCallback(callback: SuccessCallback) { this.mCallback = callback }

interface SuccessCallback { //多个参数不能使用fun修饰了 fun onSuccess(str: String): String

fun doSth()

}

class SuccessCallbackImpl : TestNet.SuccessCallback {

private var onSuccess: ((String) -> String)? = null

private var doSth: (() -> Unit)? = null

fun onSuccess(method: (String) -> String) {
    onSuccess = method
}

fun doSth(method: () -> Unit) {
    doSth = method
}

override fun onSuccess(str: String): String {
    return onSuccess?.invoke(str).toString()
}

override fun doSth() {
    doSth?.invoke()
}

}


我们定义一个测试方法用于回调数据



fun requestDSLCallback() {

最后看一下《Android框架体系架构(高级UI+FrameWork源码)》学习需要的所有知识点的思维导图。在刚刚那份学习笔记里包含了下面知识点所有内容!文章里已经展示了部分!如果你正愁这块不知道如何学习或者想提升学习这块知识的学习效率,那么这份学习笔记绝对是你的秘密武器!