40

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

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

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

4

4 回答 4

132

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

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

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

异步执行要求方法的最后一个参数是 a 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 集成是实验性的。

于 2014-01-09T01:41:57.480 回答
18

返回值的方法同步执行。

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

要做到这一点,您只需要添加一个回调即可。

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

希望这可以帮助。

问候!

于 2014-01-08T21:26:50.307 回答
7

Kotlin 协程

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

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

请参阅 Android 文档:来自网络和数据库的页面>实施 RemoteMediator

样本

注入.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) { ... }
    }
}
于 2020-09-21T04:06:44.563 回答
4

改造 2

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

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

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

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

同步请求

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();
}

从异步请求中获取结果

//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());
 }
}

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

  • 用于call.execute()同步运行。
  • 用于call.enqeue()异步运行。
于 2020-12-02T07:50:55.787 回答