标签:
Retrofit 2.1入门
几种网络框架的比较
1、volley
一个简单的http异步请求库,但不支持同步,不能post大数据(上传文件时有问题);
2、android-async-http
和volley一样,是异步的请求库,只不过volley使用的是httpUrlConnection,而它使用的是HttpClient。这个库已经不再适合Android;
3、okhttp
基于httpUrlConnection,支持同步和异步,但需要自己再封装下;
4、retrofit;
对 okhttp再次封装,在项目中可以直接使用。
在项目中引用retrofit,分为几个部分
- module对象
- Converter的实现类
- Service类(定义网址中不固定的部分)
- OkHttpClient和Retrofit
//1.创建Retrofit对象
//2.创建访问API的请求
//3.发送请求
//4.处理结果
1、配置
compile ‘com.squareup.okhttp3:okhttp-urlconnection:3.4.0-RC1‘
compile ‘com.google.code.gson:gson:2.7‘
compile ‘com.squareup.retrofit2:retrofit:2.1.0‘
compile ‘com.squareup.retrofit2:converter-gson:2.1.0‘
GET方式
public interface SimpleGET {
@GET("/") //表明是GET方式. "/"会拼接在setEndpoint(url)中url(主机地址)的后面.
Call<ResponseBody> getResponse();
//可以简单的理解为网络访问完把Response转换为一个对象.这里没有转换,还是Response.
}
public static void simpleGET(){
String url="http://tieba.baidu.com";
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(url)
.build();
SimpleGET create=retrofit.create(SimpleGET.class);
final Call<ResponseBody> call=create.getResponse();
try {
/*错误 的调用
Response response=create.getResponse().execute();
System.out.print(response.body().toString());*/
Response<ResponseBody> bodyResponse = call.execute();
String body = bodyResponse.body().string();//获取返回体的字符串
System.out.print(body);
} catch (IOException e) {
e.printStackTrace();
}
}
POST方式
public interface SimplePOST {
@POST("/androdi")
Call<ResponseBody> getResponse();
}
PATH 路径
path是可以动态替换的.
static class Contributor {
//一个pojo类(Plain Ordinary Java Object)简单的Java对象-->相比javaBean更简单. GsonConverter默认的转换器
String login;
int contributions;
}
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(@Path("owner") String owner,
@Path("repo") String repo);
}
public static void path_GitHub(){
String url="https://api.github.com";
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHub create=retrofit.create(GitHub.class);
/**
* 访问这个地址返回的是一个JsonArray,JsonArray的每一个元素都有login
* 和contributions这2个key和其对应的value.提取出来封装进POJO对象中.
*/
Call<List<Contributor>> call=create.contributors("square", "retrofit");
try {
Response<List<Contributor>> response=call.execute();
List<Contributor>list=response.body();
for (Contributor c:list) {
System.out.println(c.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
自定义的Converter(StringConverter)
Response可以获得输入流,我们可以把它转换成任何想要的格式.
自定义的StringConverter转换器
public class StringConverter implements Converter<ResponseBody,String>{
static final StringConverter.Factory FACTORY=new StringConverter.Factory(){
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
/*if (type==StringConverter.class)return new StringConverter();
else return null;*/
return new StringConverter();
}
};
@Override
public String convert(ResponseBody value) throws IOException {
//values.string 把服务器上请求的数据,转换成string格式
// String str=convertStream2String(value.byteStream());
return value.string();
}
private String convertStream2String(InputStream in) throws IOException {
//inputStream转换为String 要进行gbk或者utf-8转码,否则乱码
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "GBK"));
// BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder sb=new StringBuilder();
String line=null;
while((line=reader.readLine())!=null){
sb.append(line);
sb.append("\n");
}
return sb.toString();
}
}
public interface StringClient {
//方法的返回值是String,需要StringConverter转换器Converter把Response转换为String.
@GET("/")
Call<String> getString();
}
public static void Get_String(){
String url="http://tieba.baidu.com";
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(StringConverter.FACTORY)
.build();
final StringClient strClient=retrofit.create(StringClient.class);
Call<String>call=strClient.getString();
try {
Response<String> str=call.execute();
System.out.print(str.body());
} catch (IOException e) {
e.printStackTrace();
}
}
Query注解
public interface QueryGET {
@GET("/sheet")
Call<String> getString(@Query("name") String name,
@Query("age")int age,
@QueryMap(encoded=true)
Map<String, String> filters
);
}
public static void QueryGET(){
String url="http://tieba.baidu.com";
Map<String, String> map=new HashMap<>();
map.put("gender","male");
map.put("address","sz");
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(StringConverter.FACTORY)
.build();
QueryGET queryGET=retrofit.create(QueryGET.class);
Call<String> call=queryGET.getString("laiqurufeng", 22, map);
try {
Response<String>body=call.execute();
System.out.print(body.body());
} catch (IOException e) {
e.printStackTrace();
}
}
query 访问的参数会添加到路径(path)的后面.
实际访问的url是 http://tieba.baidu.com/sheet?name=laiqurufeng&age=22&gender=male&address=sz (模拟的访问)
encoded =true表示对url的query进行url编码,同理还有encodeValues. 这2个的值默认都是true的
如果上面的代码换成 map.put("性别","男") ,然后更改@QueryMap(encoded =false )
那么实际访问的url变成了 http://tieba.baidu.com/sheet?name=laiqurufeng&age=22&性别=%E7%94%B7&address=sz (可以看到key没有进行url编码,value进行了url编码).
Header注解
header分为key和value都固定,静态Header注解方法 和 动态Header注解方法
注意header不会相互覆盖.
静态Header
interface FixedHeader{
@Headers({ //静态Header
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("/")
Call<ResponseBody> getResponse();
}
动态Header
interface DynamicHeader{
@Headers("Cache-Control: max-age=640000") //动态Header
@GET("/")
Call<ResponseBody> getResponse(
@Header("header1")String header1,
@Header("header2")String header2);
//动态Header,其value值可以在调用这个方法时动态传入.
}
例子:
public class PhoneResult {
/**
* errNum : 0
* retMsg : success
* retData : {"phone":"15210011578","prefix":"1521001","supplier":"移动","province":"北京","city":"北京","suit":"152卡"}
*/
public int errNum;
public String retMsg;
/**
* phone : 15210011578
* prefix : 1521001
* supplier : 移动
* province : 北京
* city : 北京
* suit : 152卡
*/
public RetDataEntity retData;
public static class RetDataEntity {
public String phone;
public String prefix;
public String supplier;
public String province;
public String city;
public String suit;
@Override
public String toString() {
return "RetDataEntity{" +
"phone=‘" + phone + ‘\‘‘ +
", prefix=‘" + prefix + ‘\‘‘ +
", supplier=‘" + supplier + ‘\‘‘ +
", province=‘" + province + ‘\‘‘ +
", city=‘" + city + ‘\‘‘ +
", suit=‘" + suit + ‘\‘‘ +
‘}‘;
}
}
}
Service:
动态Header
public interface PhoneService {
@GET("/apistore/mobilenumber/mobilenumber")
Call<PhoneResult> getResult(
@Header("apikey")String apikey,
@Query("phone")String phone
);
}
静态Header
public interface PhoneServiceDynamic {
@Headers("apikey:8e13586b86e4b7f3758ba3bd6c9c9135")
@GET("/apistore/mobilenumber/mobilenumber")
Call<PhoneResult> getResult(
@Query("phone")String phone
);
}
调用
public static void phone_Query(String phone){
final String BASE_URL="http://apis.baidu.com";
final String API_KEY="8e13586b86e4b7f3758ba3bd6c9c9135";
//1.创建Retrofit对象
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
//2.创建访问API的请求
PhoneService service=retrofit.create(PhoneService.class);
Call<PhoneResult>call=service.getResult(API_KEY,phone);
//3.发送请求
try {
Response<PhoneResult>response=call.execute();
//4.处理结果
if (response.isSuccessful()) {
PhoneResult result=response.body();
if (result!=null) {
PhoneResult.RetDataEntity entity = result.getRetData();
System.out.print(entity.toString());
}
}
} catch (IOException e) {
e.printStackTrace();
}
/*异步调用
call.enqueue(new Callback<PhoneResult>() {
@Override
public void onResponse(Call<PhoneResult> call, Response<PhoneResult> response) {
//4.处理结果
if (response.isSuccessful()) {
PhoneResult result=response.body();
if (result!=null) {
PhoneResult.RetDataEntity entity = result.getRetData();
System.out.print(entity.toString());
}
}
}
@Override
public void onFailure(Call<PhoneResult> call, Throwable t) {
}
});*/
}
上传文件
public interface UploadServer {
@Headers({//静态Header
"User-Agent: androidphone"
})
@Multipart
@POST("/service.php?mod=avatar&type=big")
// upload is a post field
// without filename it didn‘t work! I use a constant name because server doesn‘t save file on original name
//@Part("filename=\"1\" ") RequestBody
//以表单的形式上传图片
Call<JsonObject> uploadImageM(@Part("file\";filename=\"1") RequestBody file);
// Call<ResponseBody> uploadImage(@Part("file\"; filename=\"image.png\"") RequestBody file);
/**
* 以二进制流的形式上传 图片
* @param file
* @return
*/
@Headers({//静态Header
"User-Agent:androidphone"
})
@POST("/service.php?mod=avatar&type=big")
Call<ResponseBody> uploadImage(@Body RequestBody file);
}
调用
public static void upload(String fpath) { // path to file like /mnt/sdcard/myfile.txt
String baseurl="http://dev.123go.net.cn";
File file = new File(fpath);
// please check you mime type, i‘m uploading only images
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
/*RequestBody rbody=new MultipartBody.Builder()
.addPart(requestBody).build();
RequestBody requestFile =
RequestBody.create(MediaType.parse("image/jpg"), file);
MultipartBody.Part body =
MultipartBody.Part.createFormData("image", file.getName(), requestFile);
*/
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(baseurl)
.addConverterFactory(GsonConverterFactory.create())
.client(getOkhttpClient())
.build();
// 添加描述
/*String descriptionString = "hello, 这是文件描述";
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), descriptionString);*/
UploadServer server=retrofit.create(UploadServer.class);
Call<ResponseBody> call = server.uploadImage(requestBody);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
ResponseBody jsonObject=response.body();
System.out.print(jsonObject.toString());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
private static OkHttpClient getOkhttpClient(){
final String cookie="your cookie";
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
// .addHeader("Content-Type", " application/x-www-form-urlencoded; charset=UTF-8")
// .addHeader("Accept-Encoding", "gzip, deflate")
// .addHeader("Connection", "keep-alive")
// .addHeader("Accept", "***")
.addHeader("Cookie", cookie)
.build();
return chain.proceed(request);
}
})
.build();
return httpClient;
}
标签:
原文地址:http://www.cnblogs.com/ut2016-progam/p/5687823.html