项目中使用了Java和Kotlin混编,然后在线程调度中,Java用的是线程,Kotlin用的协程,现在有一种场景如下
1.Kotlin中调用Java中的异步调度,然后通过回调Runnable回调到Kotlin中
- Kotlin监听回调通过launch到Main中,发现没执行,部分代码如下。
public class TestJava {
@SuppressLint("LogUsage")
public void testOnThread(Runnable runnable) {
if (runnable ==null) {
return;
}
Publishable.create(() -> {
Log.i("test ", "xxxxx java");
runnable.run();
return null;
}).publishOn(IM5Schedulers.newThread()).exePublisher();
}
}
Kotlin代码
class TestKotlin : TestJava() {
@SuppressLint("LogUsage")
fun testOnKotlin(run: Runnable) {
GlobalScope.launch {
Log.i("test " , "xxxxx 1");
testOnKotlin1(Runnable {
onMain(run)
})
}
}
@SuppressLint("LogUsage")
fun onMain(run: Runnable) {
GlobalScope.launch (Dispatchers.Main){
Log.i("test " ,"xxxxx 3")
run.run()
}
}
@SuppressLint("LogUsage")
fun testOnKotlin1(run: Runnable) {
testOnThread{
Log.i("test " , "xxxxx 2");
run.run()
}
}
}
调用testOnKotlin, 这种发现是正常的
但是如果把kotlin中的onMain调用部分,不要用函数,直接用
GlobalScope.launch {
Log.i("test " , "xxxxx 1");
testOnKotlin1(Runnable {
launch (Dispatchers.Main){
// do something
// do not invoke
}
})
}
}
}
就发现不起作用,初步怀疑是java的线程回调,没法直接在kotlin中起一个协程,但是如果是调用kotlin的函数,在koltin函数中去切线程,刚好就是kotlin的上下文,就可以.
通过分析,协程其实就是一个协程任务,执行完就退出
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
通过转java可以看出
@SuppressLint({"LogUsage"})
public final class TestKotlin extends TestJava {
public final void testOnKotlin(@NotNull Runnable run) {
Intrinsics.checkParameterIsNotNull(run, "run");
BuildersKt.launch$default((CoroutineScope)GlobalScope.INSTANCE, (CoroutineContext)Dispatchers.getIO(), (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
// $FF: synthetic field
private Object L$0;
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch(this.label) {
case 0:
ResultKt.throwOnFailure($result);
final CoroutineScope $this$launch = (CoroutineScope)this.L$0;
Log.d("hzhenx test", "testOnKotlin 1");
TestKotlin var10000 = TestKotlin.this;
Runnable var10001 = (Runnable)(new Runnable() {
public final void run() {
Log.d("hzhenx test", "testOnKotlin 2");
BuildersKt.launch$default($this$launch, (CoroutineContext)Dispatchers.getMain(), (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object var1) {
Object var2 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch(this.label) {
case 0:
ResultKt.throwOnFailure(var1);
Log.d("hzhenx test", "testOnKotlin 3");
return Unit.INSTANCE;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkParameterIsNotNull(completion, "completion");
Function2 var3 = new (completion);
return var3;
}
public final Object invoke(Object var1, Object var2) {
return (()this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 2, (Object)null);
Log.d("hzhenx test", "testOnKotlin 4");
}
});
this.label = 1;
if (var10000.testOnKotlin1(var10001, this) == var3) {
return var3;
}
break;
case 1:
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
return Unit.INSTANCE;
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkParameterIsNotNull(completion, "completion");
Function2 var3 = new (completion);
var3.L$0 = value;
return var3;
}
public final Object invoke(Object var1, Object var2) {
return (()this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 2, (Object)null);
}
public final void onMain() {
BuildersKt.launch$default((CoroutineScope)GlobalScope.INSTANCE, (CoroutineContext)Dispatchers.getMain(), (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object var1) {
Object var2 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch(this.label) {
case 0:
ResultKt.throwOnFailure(var1);
Log.d("hzhenx test", "testOnKotlin 3");
return Unit.INSTANCE;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkParameterIsNotNull(completion, "completion");
Function2 var3 = new (completion);
return var3;
}
public final Object invoke(Object var1, Object var2) {
return (()this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 2, (Object)null);
}
@Nullable
public final Object testOnKotlin1(@NotNull final Runnable run, @NotNull Continuation $completion) {
this.testOnJava((Runnable)(new Runnable() {
public final void run() {
Log.d("hzhenx test", "testOnKotlin1 1");
run.run();
Log.d("hzhenx test", "testOnKotlin1 2");
}
}));
return Unit.INSTANCE;
}
}””
由于在协程中调用了一个java线程任务,对于协程任务,当前的任务已经完成了,但是线程任务还在执行,最后回调回来,回到当前协程任务(已经完成),这时候在当前的上下文继续执行任务,就会失效,但是如果是新起协程去执行就可以,也就是直接用
GlobalScope.launch
而不是在之前的任务中调用
launch