这里使用call参数有什么用? 如何在这里使用call参数?为什么会这样?
{{1}}
答案 0 :(得分:2)
Call
类的需求。
Getting started with Retrofit 2
以下是供您参考的内容。
Retrofit 2是Android(和Java)的类型安全HTTP客户端,但首先,它是一个库,因此要使用它,我们需要声明正确的依赖项。但是,请注意,我们需要明确依赖gson转换器将JSON响应转换为模型类。改装1并非如此,所以要小心。
将这两行添加到build.gradle文件中:
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
然后,鉴于我们希望我们的应用程序访问网络,我们需要在Android清单文件中声明INTERNET权限。这非常简单,只需将此行添加到app/src/main/AndroidManifest.xml
文件中:
<uses-permission android:name="android.permission.INTERNET" />
将这些初步任务排除在外,我们可以查看实际代码。 Retrofit背后的主要思想是,可以生成在运行时查询HTTP服务的代码,要求开发人员只生成一个接口作为“规范”。想象一下,我们有以下模型类:
public class Contributor {
String login;
String html_url;
int contributions;
@Override
public String toString() {
return login + " (" + contributions + ")";
}
}
由此我们可以创建 GithubService 接口,它将体现我们的HTTP通信。
public interface GitHubService {
@GET(“repos/{owner}/{repo}/contributors”)
Call<List<Contributor>> repoContributors(
@Path(“owner”) String owner,
@Path(“repo”) String repo);
}
这是最简单的示例,我们在接口方法上添加@GET
注释,并提供我们要在其上公开的URL的路径部分。方便的是,方法参数可以在路径字符串中引用,因此您不需要跳过箍来设置它们。此外,使用其他注释,您可以指定查询参数,POST请求正文等:
@Query(“key”)
- 用于GET请求查询参数@QueryMap
- 参数地图@Body
- 将其与@POST
注释一起使用,以提供查询正文内容。
现在,要在运行时使用此接口,我们需要构建一个Retrofit对象:
interface GitHubService {
@GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> repoContributors(
@Path("owner") String owner,
@Path("repo") String repo);
public static final Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
我喜欢在包含对网站的查询的同一界面中使用“Retrofit”构建器。这样我就不会试图让事情变得复杂。是的,这里有一些常规配置。我们提供默认的转换器工厂来将JSON响应对象转换为Java对象,但最好将它复制粘贴到您拥有的每个服务类中,而不是仅使用单个抽象来发现它正在泄漏。
有了这些部分,我们只需要执行网络呼叫:
要创建 GitHubService 接口的实现,请为我们要执行的HTTP查询实例化 Call 对象并执行请求。
GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
Call<List<Contributor>> call = gitHubService.repoContributors(“square”, “retrofit”);
List<Contributor> result = call.execute().body();
或者,可以选择将调用安排为异步发生,并提供在完成时执行的回调。
call.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(Response<List<Contributor>> response, Retrofit retrofit) {
// handle success
}
@Override
public void onFailure(Throwable t) {
// handle failure
}
});
听起来很简单!让我们准备一些UI并将代码连接起来。按照浮动按钮应用程序模板设计,我们需要更改 content_main.xml 文件。这是我添加一个按钮来启动查询和一个文本区域来显示结果:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fetch"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="151dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:id="@+id/textView"
android:layout_above="@+id/button"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:textIsSelectable="false" />
以下是第一次尝试时网络呼叫代码的外观:
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
Call<List<Contributor>> call = gitHubService.repoContributors(“square”, “retrofit”);
String result = call.execute().body().toString();
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(result);
}
});
<p>Naturally, t
他的代码不起作用; Android框架不允许您在UI线程上执行网络调用。 UI线程应该只处理来自用户的输入。在此线程上执行任何长时间阻塞操作只会使用户体验缓慢。
因此,我们需要通过将网络调用移动到后台线程来重构此代码。使用JRebel for Android,这根本不需要任何时间。让我们重构它以使用我们在上面看到的enqueue
方法
现在代码看起来像下面的代码片段并且也可以使用:
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
final Call<List<Contributor>> call =
gitHubService.repoContributors("square", "retrofit");
call.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
final TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(response.body().toString());
}
@Override
public void onFailure(Call<List<Contributor>> call, Throwable t) {
final TextView textView = (TextView) findViewById(R.id.textView);
textView.setText("Something went wrong: " + t.getMessage());
}
});
}
});
就是这样,代码现在运行了,文本视图得到了更新的HTTP查询结果。
骨架应用程序准备就绪,代码构建并运行。现在,您可以使用Retrofit和JRebel for Android。您可以在此处更改一行代码,并在正在运行的应用程序中查看新代码的结果,而不会浪费任何时间。尝试向Contributor类添加几个字段。将文本视图替换为每个贡献者的正确小部件列表。完全更改HTTP端点并查询其他网站。
答案 1 :(得分:1)
实际上使用Retrofit 2,即使出现故障,也会调用onResponse。 即有时呼叫可能成功但由于某种原因数据可能为空。您可以在获取数据后使用response.isSuccessful()检查响应是否成功。
如果失败,响应中的“call”允许你再次调用相同的api。但是没有推荐,因为有时它可能导致api持续失败的循环。