在Retrofit2的onResponse()和onFailure()方法中使用first(Call <t> call)参数有什么用?

时间:2017-09-28 09:12:52

标签: android retrofit2

这里使用call参数有什么用? 如何在这里使用call参数?为什么会这样?

{{1}}

2 个答案:

答案 0 :(得分:2)

Dhiren,在发布问题之前,你真的需要做一些研究。对于一个非常广泛使用的库,这是一个非常简单的问题。有很多例子显示它的使用。请查看以下链接,该链接解释了Retrofit2 Library的使用以及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对象,但最好将它复制粘贴到您拥有的每个服务类中,而不是仅使用单个抽象来发现它正在泄漏。

    有了这些部分,我们只需要执行网络呼叫:

  • 我们的查询规范
  • Retrofit对象构建器
  • 要创建 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持续失败的循环。