美文网首页
Retrofit2线程切换

Retrofit2线程切换

作者: 机器大娃 | 来源:发表于2023-08-13 16:34 被阅读0次

一、retrofit使用

interface RequestService {
  @GET
  operator fun get(@Url url: String,@QueryMap params: HashMap<String, @JvmSuppressWildcards Any>): Call<String>
}

val client = Retrofit.Builder().apply {
   baseUrl("xxx")
   client(OkHttpHolder.okHttpClient)
}.build()

val service: RequestService = client.create(RequestService::class.java)
val call: Call<String> = service.get("xxx",HashMap<String, String>())
call.enqueue(object :Callback<String>{
              override fun onResponse(call: Call<String>, response: Response<String>) {
              }
              override fun onFailure(call: Call<String>, t: Throwable) {
              }
          })

二、DefaultCallAdapterFactory.ExecutorCallbackCall

service.get("xxx",HashMap<String, String>())

通过源码可知,在调用get时,通过代理,会得到DefaultCallAdapterFactory.ExecutorCallbackCall,而ExecutorCallbackCall就是接口Call的实现类,那么,call.enqueue()时,将会执行ExecutorCallbackCall的enqueue方法,看下ExecutorCallbackCall的enqueue(final Callback<T> callback)源码:

  @Override
    public void enqueue(final Callback<T> callback) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(
                  () -> {
                    if (delegate.isCanceled()) {
                      // Emulate OkHttp's behavior of throwing/delivering an IOException on
                      // cancellation.
                      callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                    } else {
                      callback.onResponse(ExecutorCallbackCall.this, response);
                    }
                  });
            }

            @Override
            public void onFailure(Call<T> call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

显然,线程就是通过callbackExecutor.execute()切换的,看下callbackExecutor怎么来的。
通过代码追踪,发现,callbackExecutor来自Retrofit中的build(),而当我们创建Retrofit的时候,就调用了这个方法。

三、Retrofit.build()

public final class Retrofit {
    public Retrofit build() {
        //这里仅贴出获取callbackExecutor的代码
        ...
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
           callbackExecutor = platform.defaultCallbackExecutor();
        }
        ...
     }

    public static final class Builder {
         public Builder() {
            this(Platform.get());
         }
    }
}
class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }

   static final class Android extends Platform {
       Android() {
         super(Build.VERSION.SDK_INT >= 24);
       }

      @Override
       public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
       }
   }

  static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
}

platform是通过Platform.get()获取的,System.getProperty("java.vm.name")获取的是java VM的名称,显然,Android系统下将返回Android(),Android是Platform实现类,当调用latform.defaultCallbackExecutor()时,将返回一个MainThreadExecutor对象,而,当执行MainThreadExecutor.execute的时候,通过new Handler(Looper.getMainLooper())讲子线程切到了UI线程。

四、如何让Retrofit请求结束后的回调中还在子线程

   val client = Retrofit.Builder().apply {
                baseUrl("")
                callbackExecutor(ThreadExecutor())
                addConverterFactory(ScalarsConverterFactory.create())
                client(OkHttpHolder.okHttpClient)
            }.build()
    class ThreadExecutor : Executor {
        override fun execute(r: Runnable) {
            r.run()
        }
    }

给Retrofit重新创造一个Executor就行了。

相关文章

  • Rxjava2 Note

    线程切换 subscribeOn - 切换上游线程,但仅调用的第一次生效 observeOn - 切换下游线程,调...

  • RxJava系列(三)--切换线程

    1.主线程是怎么切换到子线程2.为什么只有第一次切换有效3.子线程是怎么切换到主线程1>问题1,主线程是怎么切换到...

  • subscribeOn 谐音上 就是上面的

    subscribeOn的调用切换之前的线程。 observeOn的调用切换之后的线程。 observeOn之后,不...

  • 2020-12-07

    1、进程线程协程2、进程切换、线程切换https://www.cnblogs.com/xiangshihua/p/...

  • rxjava源码解析

    线程切换原理 案例 subscribeOn切换子线程 先看subscribe的执行,最后会执行Observable...

  • 一种估计服务器线程个数的方法

    1.估计线程数存在的难点 线程个数越多,线程切换频繁,会浪费资源在线程切换上面;线程个数少无法充分利用cpu资源,...

  • 进程和线程的对比

    问题 一 进程和线程的对比 二 为什么进程切换开销大,线程切换开销低呢? .......................

  • android协程

    Kotlin的协程,本质上是一个线程框架,它可以方便的切换线程的上下文(如主线程切换到子线程/子线程切回主线程)。...

  • RxJava源码分析(四)线程切换observeOn

    引言 前面的文章我们走完了订阅方法线程切换的实现,今天我们来看观察方法的线程切换。 线程调度observeOn 接...

  • 线程的基本操作

    线程的基本操作 •线程状态切换 •终止线程(stop) •中断线程(interrupt) •挂起(suspend)...

网友评论

      本文标题:Retrofit2线程切换

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