Retrofit是否在主线程上进行网络调用?

时间:2014-01-08 21:22:30

标签: android retrofit okhttp

我正在尝试在Android上探索Retrofit + OkHttp。这是我在网上找到的一些代码:

RestAdapter restAdapter = new RestAdapter.Builder().setExecutors(executor, executor)
.setClient(new OkClient(okHttpClient))
.setServer("blah").toString())
.build();

如果我不使用执行程序服务,我的代码是否会在主线程上运行?我应该在新线程中发出Web请求吗?

4 个答案:

答案 0 :(得分:112)

可以为同步或异步执行声明Retrofit方法。

具有返回类型的方法将同步执行。

@GET("/user/{id}/photo")
Photo getUserPhoto(@Path("id") int id);

异步执行要求方法的最后一个参数为Callback

@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);

在Android上,回调将在主线程上执行。对于桌面应用程序,回调将在执行HTTP请求的同一线程上发生。

Retrofit还集成了RxJava以支持返回类型为rx.Observable的方法

@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);

可观察请求是异步订阅的,并在执行HTTP请求的同一线程上观察到。要在不同的主题(例如Android主线程)上观察,请在返回的observeOn(Scheduler)上调用Observable

注意:RxJava集成是实验性的。

答案 1 :(得分:17)

返回值的方法是同步的。

@GET("/user/{id}/asset")
Asset getUserAsset(@Path("id") int id);

要做到这一点异步你只需要添加一个回调。

@GET("/user/{id}/asset")
void getUserAsset(@Path("id") int id, Callback<Asset> cb);

希望这有助于。

问候!

答案 2 :(得分:2)

Kotlin协程

使用suspend函数发出网络请求时,Retrofit使用协程CallAdapter来调度工作线程。

因此,协程不需要在Dispatcher.IO线程上显式启动。

请参阅Android文档:Page from network and database> Implement a RemoteMediator

样本

Injection.kt

object Injection {
    val feedService = Retrofit.Builder()
        .baseUrl(TWITTER_API_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(FeedService::class.java)
}

FeedService.kt

interface FeedService {
    // Retrofit makes the request on a background thread.
    @GET("lists/{listType}")
    suspend fun getTweets(
        @Path(LIST_TYPE_PATH) listType: String,
        @Query(LIST_ID_QUERY) listId: String,
        @Query(LIST_COUNT_QUERY) count: String,
        @Query(LIST_PAGE_NUM_QUERY) page: String
    ): List<Tweet>
}

FeedPagingSource

class FeedPagingSource : PagingSource<Int, Tweet>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Tweet> {
        try {
            // The results are returned on the main thread.
            val tweets: List<Tweet> = Injection.feedService.getTweets(...)
            return LoadResult.Page(...)
        } catch (error: Exception) { ... }
    }
}

答案 3 :(得分:0)

Retrofti 2

众所周知,翻新可以同步和异步执行请求。

同步方法在主线程上执行。这意味着UI在请求执行期间阻塞,并且在此期间无法进行交互。

对于非阻塞UI,您必须自己在单独的线程中处理请求执行。这意味着,您仍然可以在等待响应的同时与应用本身进行交互。

在Retrofit2中,如果要同步执行请求:

同步请求

\n

从同步请求中获取结果

public interface TaskService {  
  @GET("/tasks")
  Call<List<Task>> getTasks();
}

但是,如果要异步执行请求:

异步请求

//service generator
TaskService taskService = ServiceGenerator.createService(TaskService.class); 

Call<List<Task>> call = taskService.getTasks();  
List<Task>> tasks = call.execute().body();  

从异步请求中获取结果

public interface TaskService {  
  @GET("/tasks")
  Call<List<Task>> getTasks();
}

如上所述,:Retrofit 2中的接口定义对于同步和异步请求都是相同的。换句话说,在Retrofit 2中,每个请求都包装到一个Call对象中。实际的同步或异步请求是在以后创建的调用对象上使用所需方法来不同地执行的。

  • 使用//service generator TaskService taskService = ServiceGenerator.createService(TaskService.class); Call<List<Task>> call = taskService.getTasks(); call.enqueue(new Callback<List<Task>>() { @Override public void onResponse(Call<List<Task>> call, Response<List<Task>> response) { if (response.isSuccessful()) { // tasks available } else { // error response, no access to resource? } } @Override public void onFailure(Call<List<Task>> call, Throwable t) { // something went completely south (like no internet connection) Log.d("Error", t.getMessage()); } } 来同步运行。
  • 使用call.execute()异步运行。