Android 网络请求框架Retrofit2.0使用笔记

时间:2021-08-26 19:46:58

说明

说起Retrofit必须要提到RxJava,但是本文只是简单介绍一下Retrofit的使用流程,为RxJava+Retrofit的实现做好准备,稍后会继续写一遍RxJava+Retrofit的博客笔记。

本文参考:http://gank.io/post/56e80c2c677659311bed9841

Retrofit”改造”

适用于Android和Java的类型安全的HTTP客户端.
Retrofit requires at minimum Java 7 or Android 2.3.

GitHub地址:https://github.com/square/retrofit
官方文档:http://square.github.io/retrofit/

特点

1.基于RESTful API原则

还不知道什么是RESTful API的可以点击:
RESTful API 设计指南

2.基于Okhttp

Retrofit”改造”,改造的就是Okhttp,内部的网络请求都是基于Okhttp实现的。

3.使用注释来描述HTTP请求:
  1. URL参数替换和查询参数支持
  2. 对象转换为请求体(如JSON,协议缓冲区)
  3. 多部分请求身份和文件上传

添加依赖

    //Retrofit2所需要的包
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    //ConverterFactory的Gson依赖包,用于对获取的数据进行解析转换为请求实体
    compile 'com.squareup.retrofit2:converter-gson:2.3.0' 

添加权限

<uses-permission android:name="android.permission.INTERNET"/>

GET

测试Api

我们使用官方文档的api做测试:

https://api.github.com/users/octocat/repos

返回的数据格式,大家自己访问下链接就看到了。

1.创建实体类

知道了数据格式,我们可以根据自己想要的数据编写实体类。如下:

public class Repo {
    private String id, name, full_name;

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getFull_name() {
        return full_name;
    }
}

2.创建Service类

基于RESTful API原则,在 https://api.github.com/users/octocat/repos 这个Api url中:

  1. 域名是:"https://api.github.com/"
  2. 路径(Endpoint)是:users/{user}/repos
public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

3.创建Retrofit类


public class RetrofitApi {
   String baseUrl = "https://api.github.com/";
    private static GitHubService service;

    public RetrofitApi() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        service = retrofit.create(GitHubService.class);
    }

    //单例
    public static GitHubService getService() {
        if (service == null) {
            synchronized (RetrofitApi.class) {
                if (service == null) {
                    new RetrofitApi();
                }
            }
        }
        return service;
    }
}

4.MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
          Call<List<Repo>> repos = RetrofitApi.getService().listRepos("octocat");
        repos.enqueue(new Callback<List<Repo>>() {
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
                List<Repo> list = response.body();//获取数据
                for (int i = 0; i < list.size(); i++) {
                    Log.d(TAG, i + ": " + list.get(i).getId() + "," + list.get(i).getName() + "," + list
                            .get(i).getFull_name());
                }
                Toast.makeText(MainActivity.this, "over!", Toast.LENGTH_SHORT).show();
                //获取当前所在线程
                Log.i("TAG", Thread.currentThread().getName());
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
                Log.e(TAG, "onFailure: " + t.getMessage());
            }
        });
    }
}

5.测试结果

09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 0: 18221276,git-consortium,octocat/git-consortium
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 1: 20978623,hello-worId,octocat/hello-worId
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 2: 1296269,Hello-World,octocat/Hello-World
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 3: 64778136,linguist,octocat/linguist
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 4: 17881631,octocat.github.io,octocat/octocat.github.io
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 5: 1300192,Spoon-Knife,octocat/Spoon-Knife
09-05 17:29:35.958 30462-30462/demon.retrofitdemon D/MainActivity: 6: 56271164,test-repo1,octocat/test-repo1
09-05 17:29:35.966 30462-30462/demon.retrofitdemon I/TAG: main

I/TAG: main表明结果返回在main线程中。

POST

实现了GET请求,接下来我们简单了解一下POST请求。

测试Api

阿里云根据地区名获取经纬度接口:

http://gc.ditu.aliyun.com/geocoding

1.创建实体类

public class City {
    private String lon, lat;

    public String getLon() {
        return lon;
    }

    public String getLat() {
        return lat;
    }
}

2.Service类中添加如下代码

    @POST("geocoding")
   Call<City> getCity(@Query("a") String a);

3.修改Retrofit类中的baseUrl

String baseUrl = "http://gc.ditu.aliyun.com/";

4.MainActivity

修改代码如下:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main)

        final String[] pos = {"北京市","上海市","广州市"};
        for (int i = 0; i < pos.length; i++) {
            getLonLat(pos[i]);
        }
    }

    public void getLonLat(final String pos) {
        RetrofitApi.getService().getCity(pos).enqueue(new Callback<City>() {
            @Override
            public void onResponse(Call<City> call, Response<City> response) {
                City city = response.body();
                Log.d(TAG, pos + "的经度,纬度:" + city.getLon() + "," + city.getLat());
            }

            @Override
            public void onFailure(Call<City> call, Throwable t) {
                Log.e(TAG, "onFailure: " + t.getMessage());
            }
        });
    }
}

5.测试结果

09-05 18:00:24.121 24954-24954/demon.retrofitdemon D/MainActivity: 上海市的经度,纬度:121.4737,31.23041
09-05 18:00:24.121 24954-24954/demon.retrofitdemon D/MainActivity: 广州市的经度,纬度:113.26443,23.12916
09-05 18:00:24.121 24954-24954/demon.retrofitdemon D/MainActivity: 北京市的经度,纬度:116.40752,39.90403

返回的结果与请求顺序不同,说明每次请求是在异步线程中进行,然后传到主线程。

总结

结合两次测试结果可知,Retrofit在Okhttp的基础上主动将结果返回到了主线程。
无需我们再采取措施将结果传递到主线程,这点也是在在Okhttp的基础上做的最大改动了。