Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

OkHttp

okhttp

官网

文档

API

You'll also need Okio , which OkHttp uses for fast I/O and resizable调整 buffers。

Okio的API文档

compile 'com.squareup.okhttp3:okhttp:3.8.0'
compile 'com.squareup.okio:okio:1.13.0'

okhttp-3.9.0.jar

okio-1.13.0.jar

简介

Android下的网络框架:

  • 官方集成的网络框架包含:HttpUrlConnection、HttpClient、Volley。
  • Volley是android开发团队在2013年Google I/O大会上推出了一个新的网络通信框架。目前Volley中部分代码仍然借助于HttpClient中部分功能,然而HttpClient在Android 6.0中已经被剔除掉了,如果想要使用Volley还必须使用一个第三方的jai包。
  • Volley是针对数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。
  • 如果使用HttpUrlConnection则要从头开始封装对应的操作。

OkHttp是一个 Java 的 HTTP+SPDY 客户端开发包,同时也支持 Android,需要 Android 2.3 以上,同时还需要一个okio包。

  • OKHttp是Android(Java)版Http客户端,非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存
  • 默认情况下,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题
  • 如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其网络层请求
  • 从Android4.4开始,HttpURLConnection的底层实现采用的是okHttp

PS:

SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。

SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。

新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。

谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。

官方 Overview

HTTP is the way modern applications network. It's how we exchange data & media. Doing HTTP efficiently makes your stuff材料、塞满 load faster and saves bandwidth带宽.

OkHttp is an HTTP client that's efficient by default:

  • HTTP/2 support allows all requests to the same host to share a socket.
  • Connection pooling连接池 reduces使变弱 request latency延迟 (if HTTP/2 isn't available).
  • Transparent GZIP透明的GZIP压缩 shrinks减少 download sizes.
  • Response caching avoids the network completely for repeat重复 requests.

OkHttp perseveres坚忍 when the network is troublesome: it will silently沉默的 recover from common connection problems. If your service has multiple IP addresses, OkHttp will attempt alternate轮流、交替 addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant冗余的、多余的 data centers. OkHttp initiates开始 new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.

Using OkHttp is easy. Its request/response API is designed with fluent流畅的 builders and immutability不变的. It supports both synchronous blocking calls and async calls with callbacks.

OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.

Works with OkHttp

Here’s some libraries that work nicely with OkHttp.

  • Glide: An image loading and caching library for Android focused on smooth scrolling. 专注于平滑滚动的Android图像加载和缓存库。
  • Okio: A modern I/O API for Java. Java的现代I/O API。
  • Retrofit: Type-safe HTTP client for Android and Java by Square. Square公司出的适用于Android和Java的类型安全的HTTP客户端。
  • Chuck: An in-app HTTP inspector for Android OkHttp clients. 适用于Android OkHttp客户端的应用内HTTP检查器。
  • Communicator: An OkHttp wrapper for Scala built with Android in mind. 安装了Android的Scala的OkHttp包装器。
  • CWAC-NetSecurity: Simplifying Secure Internet Access. 简化安全Internet访问。
  • Fresco: An Android library for managing images and the memory they use. 用于管理图像和他们使用的内存的Android库。
  • GoogleAppEngineOkHttp: An OkHttp Call that works on Google App Engine. 适用于Google App Engine的OkHttp调用。
  • ModernHttpClient: Xamarin HTTP API that uses native implementations. 使用本地实现的Xamarin HTTP API。
  • Moshi: A modern JSON library for Android and Java. Android和Java的现代JSON库。
  • Ok2Curl: Convert OkHttp requests into curl logs. 将OkHttp请求转换为curl日志。
  • okhttp-digest: A digest authenticator for OkHttp. OkHttp的摘要验证器。
  • OkHttp Idling Resource: An Espresso IdlingResource for OkHttp. OkHttp的浓咖啡空转资源。
  • okhttp-signpost: OAuth signing with signpost and OkHttp. OAuth签署路标和OkHttp。
  • okhttp-stats: Get stats like average network speed. 获取平均网络速度的统计信息。
  • OkHttp-Xamarin: Xamarin bindings for OkHttp. 用于OkHttp的Xamarin绑定。
  • OkLog: Response logging interceptor for OkHttp. Logs a URL link with URL-encoded response for every OkHttp call. OkHttp的响应记录拦截器。记录每个OkHttp调用的URL编码响应的URL链接。
  • OkSocial A curl-like client for social networks and other APIs. 社交网络和其他API的curl-like客户端。
  • PersistentCookieJar: A persistent CookieJar. 一个持久的CookieJar。
  • Picasso: A powerful image downloading and caching library for Android. 一个功能强大的Android图像下载和缓存库。
  • Smash: A Volley-inspired networking library. 一个受Volley启发的网络库。
  • Stetho: Stetho is a debug bridge for Android applications. Stetho是Android应用程序的调试桥。
  • Thrifty: An implementation of Apache Thrift for Android. 在Android上Apache Thrift的一个实现。
  • Volley-OkHttp-Android: A fork of Volley with changes to work with OkHttp. 使用OkHttp进行更改的fork自Volley的一个库。

  • Wire: Clean, lightweight protocol buffers for Android and Java. 适用于Android和Java的清洁、轻便的protocol buffers。

示例代码

get和post示例

public class MainActivity extends ListActivity {
private User mUser;
private String mBaseUrl = "http://api.95xiu.com/";
private OkHttpClient client; private TextView mTv; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] array = {"post方式提交键值对数据", "get方式提交键值对数据",};
mTv = new TextView(this);
getListView().addFooterView(mTv);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array)); client=new OkHttpClient.Builder().build();
} @Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
postWithParams(); //post方式提交键值对数据
break;
case 1:
getWithParams(); //get方式提交键值对数据
break;
}
} private void postWithParams() {
String url = mBaseUrl + "user/loginv2.php";
FormBody formBody = new FormBody.Builder()
.add("user", "103468")
.add("pass", "103468")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
client.newCall(request)
.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
} @Override
public void onResponse(Call call, Response response) throws IOException {
final String responseString = response.body().string();//响应的内容
Log.i("bqt", "【body】" + decodeUnicodeToString(responseString));//{"result":0,"msg":"用户不存在"} mUser = new Gson().fromJson(responseString, User.class);//类型转换
runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString)));//线程切换
}
});
} private void getWithParams() {
String url = mBaseUrl + "app/news/index.php"
+ "?session_id=" + mUser.getMsg().getSession_id()
+ "&uid=" + mUser.getMsg().getId();
Request request = new Request.Builder().url(url).get().build();
client.newCall(request)
.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
} @Override
public void onResponse(Call call, Response response) throws IOException {
final String responseString = response.body().string();
runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString)));
}
});
} //将Unicode编码解析成字符串形式(如汉字)
public static String decodeUnicodeToString(String uString) {
StringBuilder sb = new StringBuilder();
int i = -1, pos = 0;
while ((i = uString.indexOf("\\u", pos)) != -1) {
sb.append(uString.substring(pos, i));
if (i + 5 < uString.length()) {
pos = i + 6;
sb.append((char) Integer.parseInt(uString.substring(i + 2, i + 6), 16));
}
}
sb.append(uString.substring(pos));
return sb.toString();
}
}

拦截器和证书示例

public class OkHttp_Activity extends ListActivity {

    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] array = {"应用程序拦截器",
"网络拦截器",
"Rewriting Requests,重写请求",
"Rewriting Responses,重写响应",};
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
} @Override
protected void onListItemClick(ListView l, View v, int position, long id) {
new Thread(() -> {//里面用的都是同步请求,所以必须在一个子线程中调用
try {//线程里面的异常不能在线程外面捕获或throws
switch (position) {
case 0:
loggingInterceptor(true, new LoggingInterceptor());//应用程序拦截器
break;
case 1:
loggingInterceptor(false, new LoggingInterceptor());//网络拦截器
break;
case 2:
loggingInterceptor(new Random().nextBoolean(), new GzipRequestInterceptor());//重写请求
break;
case 3:
loggingInterceptor(new Random().nextBoolean(), new ReWriteCacheControlInterceptor());//重写响应
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
} private void loggingInterceptor(boolean isApplicationInterceptor, Interceptor interceptor) throws IOException {
OkHttpClient client;
if (isApplicationInterceptor) client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
else client = new OkHttpClient.Builder().addNetworkInterceptor(interceptor).build(); Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.header("User-Agent", "OkHttp Example")
.build(); Response response = client.newCall(request).execute(); //同步执行
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println("【响应url】" + response.request().url());
response.body().close();
} //使用一个自定义的TLS版本和密码组来构建你自己的连接规范
private void connectionSpecs() {
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build(); OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
} //Certificate Pinning,证书锁定
public void certificatePinner() throws Exception {
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.build(); OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build(); Request request = new Request.Builder()
.url("https://publicobject.com/robots.txt")
.build(); Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); for (java.security.cert.Certificate certificate : response.handshake().peerCertificates()) {
System.out.println("【】" + CertificatePinner.pin(certificate));
}
} //拦截器
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();//发出的请求
long t1 = System.nanoTime();
System.out.println("【请求】" + String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request);//生成与请求对应的响应。这里是所有HTTP工作发生的地方
long t2 = System.nanoTime();
System.out.println("【响应】" + String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response;
}
} //This interceptor compresses the HTTP request body. Many webservers can't handle this!
class GzipRequestInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);//生成与请求对应的响应
} RequestBody compressedRequestBody = new RequestBody() {
@Override
public MediaType contentType() {
return originalRequest.body().contentType();
} @Override
public long contentLength() {
return -1; // We don't know the compressed length in advance(提前)!
} @Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
originalRequest.body().writeTo(gzipSink);
gzipSink.close();
}
}; Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")//添加、删除或者替换请求头
.method(originalRequest.method(), compressedRequestBody)//改变请求体
.build();
return chain.proceed(compressedRequest);//重新生成与请求对应的响应
}
} //Dangerous interceptor that rewrites the server's cache-control header.
class ReWriteCacheControlInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.header("Cache-Control", "max-age=60")//重写响应头
.build();
}
}
}

retrofit okhttp RxJava 综合示例

依赖

//【retrofit2】
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' //【okhttp】
compile 'com.squareup.okhttp3:okhttp:3.8.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
compile 'com.squareup.okio:okio:1.13.0' //【butterknife】
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' //【rxjava】
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.6'

网络请求接口定义

public interface GitHubApi {

    @GET("repos/{owner}/{repo}/contributors")
Call<ResponseBody> contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo); @GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributorsByAddConverterGetCall(@Path("owner") String owner, @Path("repo") String repo); @Headers({"Accept: application/vnd.github.v3.full+json", "User-Agent: RetrofitBean-Sample-App", "name:ljd"})
@GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributorsAndAddHeader(@Path("owner") String owner, @Path("repo") String repo); @GET("search/repositories")
Call<RetrofitBean> queryRetrofitByGetCall(@Query("q") String owner, @Query("since") String time, @Query("page") int page, @Query("per_page") int per_Page); @GET("search/repositories")
Call<RetrofitBean> queryRetrofitByGetCallMap(@QueryMap Map<String, String> map); @GET("repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributorsByRxJava(@Path("owner") String owner, @Path("repo") String repo); @GET("users/{user}")
Observable<User> userByRxJava(@Path("user") String user); @GET("/mobilesafe/shouji360/360safesis/360MobileSafe_6.2.3.1060.apk")
Call<ResponseBody> retrofitDownload();
}

Activity

public class MainActivity extends ListActivity {
private TextView tv;
private static final String baseUrl = "https://api.github.com/";
private static final String mUserName = "square";//哪个公司【square】
private static final String mRepo = "retrofit";//哪个项目【retrofit】
private CompositeSubscription mSubscriptions = new CompositeSubscription(); protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] array = {"1、简单完整演示retrofit的使用",
"2、添加Gson转换器",
"3、添加okHttp的日志拦截器Interceptor",
"4、使用自己封装的API,演示@Headers",
"5、演示同步请求",
"6、演示@Query",
"7、演示@QueryMap",
"8、最简单、完整的retrofit+rxJava示例",
"9、rxJava+retrofit增强",
"10、演示文件下载",};
tv = new TextView(this);
tv.setTextColor(Color.BLUE);
getListView().addFooterView(tv);
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
} @Override
protected void onDestroy() {
if (mSubscriptions != null) mSubscriptions.unsubscribe();
super.onDestroy();
} @Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position + 1) {
case 1://简单完整演示retrofit的使用
requestGitHubContributorsSimple();
break;
case 2://添加Gson转换器
requestGitHubContributorsByConverter();
break;
case 3://添加okHttp的日志拦截器Interceptor
requestGitHubContributorsAddOkHttpLog();
break;
case 4://使用自己封装的API,演示@Headers
requestGitHubContributorsAddHeader();
break;
case 5://演示同步请求
requestGitHubContributorsBySync();
break;
case 6://演示@Query
requestQueryRetrofitByGet(false);
break;
case 7://演示@QueryMap
requestQueryRetrofitByGet(true);
break;
case 8://最简单、完整的retrofit+rxJava示例
requestGitHubContributorsByRxJava();
break;
case 9://rxJava+retrofit增强
requestGitHubContributorsWithFullUserInfo();
break;
case 10://演示文件下载
retrofitDownload();
break;
}
} //1、简单示例
private void requestGitHubContributorsSimple() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.build();
GitHubApi repo = retrofit.create(GitHubApi.class);
Call<ResponseBody> call = repo.contributorsBySimpleGetCall(mUserName, mRepo);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
String result = null;
try {
result = response.body().string();
if (result == null) return;
} catch (IOException e) {
e.printStackTrace();
}
tv.setText("GitHub上对项目的贡献-1:\n");
ArrayList<Contributor> list = new Gson().fromJson(result, new TypeToken<List<Contributor>>() {
}.getType());
if (list == null || list.size() == 0) return;
for (Contributor contributor : list) {
tv.append(contributor.login + " " + contributor.contributions + "\n");
}
} @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} //2、添加Gson转换器
private void requestGitHubContributorsByConverter() {
new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())//转换器
.build()
.create(GitHubApi.class)
.contributorsByAddConverterGetCall(mUserName, mRepo)
.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<Contributor>> response) {
List<Contributor> list = response.body();
tv.setText("GitHub上对项目的贡献-2:\n");
if (list == null || list.size() == 0) return;
for (Contributor contributor : list) {
tv.append(contributor.login + " " + contributor.contributions + "\n");
}
} @Override
public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} //3、添加okHttp的日志拦截器Interceptor
private void requestGitHubContributorsAddOkHttpLog() {
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient.Builder().addInterceptor(logInterceptor).build())
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build(); retrofit.create(GitHubApi.class)
.contributorsByAddConverterGetCall(mUserName, mRepo)
.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt
.retrofit.bean.Contributor>> response) {
List<Contributor> list = response.body();
tv.setText("GitHub上对项目的贡献-3:\n");
if (list == null || list.size() == 0) return;
for (Contributor contributor : list) {
tv.append(contributor.login + " " + contributor.contributions + "\n");
}
} @Override
public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} //4、使用自己封装的API,演示@Headers
private void requestGitHubContributorsAddHeader() {
createRetrofitService(GitHubApi.class)
.contributorsAndAddHeader(mUserName, mRepo)
.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt
.retrofit.bean.Contributor>> response) {
List<Contributor> list = response.body();
tv.setText("GitHub上对项目的贡献-4:\n");
if (list == null || list.size() == 0) return;
for (Contributor contributor : list) {
tv.append(contributor.login + " " + contributor.contributions + "\n");
}
} @Override
public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
}
});
} //5、演示同步请求
private void requestGitHubContributorsBySync() {
final Call<List<Contributor>> call = createRetrofitService(GitHubApi.class)
.contributorsByAddConverterGetCall(mUserName, mRepo);
new Thread(() -> {
try {
Response<List<Contributor>> response = call.execute();//在子线程中请求网络
final List<Contributor> list = response.body();
runOnUiThread(() -> {
tv.setText("GitHub上对项目的贡献-5:\n");
for (Contributor contributor : list) {
tv.append(contributor.login + " " + contributor.contributions + "\n");
}
});
} catch (IOException e) {
e.printStackTrace();
}
}).start();
} //6和7、演示@Query和@QueryMap
private void requestQueryRetrofitByGet(boolean isQueryMap) {
GitHubApi mGitHubService = createRetrofitService(GitHubApi.class);
Call<RetrofitBean> call;
if (!isQueryMap) call = mGitHubService.queryRetrofitByGetCall("retrofit", "2016-03-29", 1, 3);
else {
Map<String, String> queryMap = new HashMap<>();
queryMap.put("q", "retrofit");
queryMap.put("since", "2016-03-29");
queryMap.put("page", "1");
queryMap.put("per_page", "3");
call = mGitHubService.queryRetrofitByGetCallMap(queryMap);
} call.enqueue(new Callback<RetrofitBean>() {
@Override
public void onResponse(@NonNull Call<RetrofitBean> call, @NonNull Response<RetrofitBean> response) {
RetrofitBean retrofitBean = response.body();
if (retrofitBean == null) return;
List<Item> list = retrofitBean.getItems();
if (list == null || list.size() == 0) return; tv.setText(new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS", Locale.getDefault()).format(new Date()));
tv.append("\ntotal:" + retrofitBean.getTotalCount() + "\nincompleteResults:" + retrofitBean.getIncompleteResults());
for (Item item : list) {
tv.append("\n\n【name】" + item.name);
tv.append("\n【full_name】" + item.full_name);
tv.append("\n【 description】" + item.description);
}
} @Override
public void onFailure(@NonNull Call<RetrofitBean> call, @NonNull Throwable t) {
}
});
} //8、最简单、完整的retrofit+rxJava示例
private void requestGitHubContributorsByRxJava() {
createRetrofitService(GitHubApi.class)
.contributorsByRxJava(mUserName, mRepo)//
.subscribeOn(Schedulers.io())//
.observeOn(AndroidSchedulers.mainThread())//
.subscribe(...);
} //9、rxJava+retrofit增强
private void requestGitHubContributorsWithFullUserInfo() {
Subscription subscription = createRetrofitService(GitHubApi.class)
.contributorsByRxJava(mUserName, mRepo)//
.flatMap(...)
.flatMap(...)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...;
mSubscriptions.add(subscription);
} //10、演示文件下载
public void retrofitDownload() {
//监听下载进度
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setProgressNumberFormat("%1d KB/%2d KB");
dialog.setTitle("下载");
dialog.setMessage("正在下载,请稍后...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.show(); ProgressHelper.setProgressHandler(new DownloadProgressHandler() {
@Override
protected void onProgress(long bytesRead, long contentLength, boolean done) {
//在主线程中运行
dialog.setMax((int) (contentLength / 1024));
dialog.setProgress((int) (bytesRead / 1024));
if (done) dialog.dismiss();
}
}); Retrofit retrofit = new Retrofit.Builder()//
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//
.addConverterFactory(GsonConverterFactory.create())//
.baseUrl("http://msoftdl.360.cn")
.client(ProgressHelper.addProgress(null).build())
.build(); retrofit.create(GitHubApi.class).retrofitDownload()
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
try {
InputStream is = response.body().byteStream();
File file = new File(Environment.getExternalStorageDirectory(), "12345.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
fos.flush();
}
fos.close();
bis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
}
});
} public static <T> T createRetrofitService(final Class<T> service) {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor);
Retrofit retrofit = new Retrofit.Builder()//
.client(ProgressHelper.addProgress(builder).build())//
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//
.addConverterFactory(GsonConverterFactory.create())//
.baseUrl("https://api.github.com/")//
.build();
return retrofit.create(service);
}
}

综合配置

请求参数封装:

public interface BqtService {
@GET("User")
Observable<BqtRes<User>> getUser(); @FormUrlEncoded
@POST("BuyInfo/buyRecord")
Observable<BqtRes<ArrayList<MyClassBean>>> getHistory(@Field("user_id") int uid, @Field("page") int page);
}

调用示例:

H.h().getUser()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> L.i("onNext " + response.data.toString());//这里response.data的类型即是User

retrofit、okhttp、RxJava、Gson、拦截器、Header等配置

public class H {
private static Interceptor buildInterceptor() {
final String token = AccountManager.getInstance().getToken();
PackageInfo packInfo = null;
try {
packInfo = App.app.getPackageManager().getPackageInfo(App.app.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
final int version = packInfo == null ? 1 : packInfo.versionCode;
return 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", "*/*")
//****************************************自定义Header
.addHeader("version", version + "")//app版本号
.addHeader("token", token == null ? "" : token)//登录后返回的token
.addHeader("mobile", "1")// 0-PC,1-Android,2-IOS,3-web
.build();
return chain.proceed(request);
}
};
} private static Interceptor buildLogInterceptor() {
return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
L.d(message);//这里会打印出大量的日志出来,所以不要和手动打印的日志混在一起
}
}).setLevel(HttpLoggingInterceptor.Level.BODY);//日志显示级别
} private static OkHttpClient buildOkHttp() {
return new OkHttpClient.Builder()
.addInterceptor(buildHeaderInterceptor())//自定义Header
.addInterceptor(buildLogInterceptor())//日志拦截
.connectTimeout(5, TimeUnit.SECONDS)
.build();
} private static Gson buildGson() {
return new GsonBuilder()//配置你的Gson
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.setPrettyPrinting()
.serializeNulls()
.create();
} private static String buildBaseUrl() {
switch (UrlHelper.getEnv()) {
case 0: // baseUlr 必须以 / 结束,不然会抛出一个IllegalArgumentException
return "http://test.talk.99cj.com.cn/";
case 1:
return "http://wechat.99cj.com.cn/";
default:
return "http://wechat.99cj.com.cn/";
}
} private static Retrofit buildRetrofit(OkHttpClient client, Converter.Factory converterFactory, CallAdapter.Factory callAdapterFactory) {
return new Retrofit.Builder()
.baseUrl(buildBaseUrl())
.client(client)
.addConverterFactory(converterFactory)//可以接收自定义的Gson,当然也可以不传
.addCallAdapterFactory(callAdapterFactory)
.build();
} private static <T> T createRetrofitService(final Class<T> service) {
Retrofit retrofit = buildRetrofit(buildOkHttp(), //
GsonConverterFactory.create(buildGson()),//
RxJavaCallAdapterFactory.create());//
return retrofit.create(service);
} public static BqtService h() {
return createRetrofitService(BqtService.class);
}
}

添加上述【HttpLoggingInterceptor】拦截器后会打印如下日志

2017-06-20

Okhttp【简介】应用 示例的更多相关文章

  1. Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  2. IdentityServer4 中文文档 -6- (简介)示例服务器和测试

    IdentityServer4 中文文档 -6- (简介)示例服务器和测试 原文:http://docs.identityserver.io/en/release/intro/test.html 目 ...

  3. Ruby简介,附带示例程序

    Ruby语言是日本人松本行弘于1993年器开始着手研发,经历2年时间,发布了Ruby语言的第一个版本:0.95版.     Ruby是一种非常简介的解释性语言,一种纯粹的面向对象编程语言,甚至比Jav ...

  4. IText简介及示例

    一.iText简介 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文 ...

  5. Unity 3(一):简介与示例

    本文关注以下方面(环境为VS2012..Net Framework 4.5以及Unity 3): Ioc/DI简介: Unity简单示例 一.Ioc/DI简介 IoC 即 Inversion of C ...

  6. OkHttp简介

    什么是OKHttp 一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理.比如可以使用http客户端与第三方服务(如SSO服 ...

  7. JavaScript简介及示例

    JavaScript简介及使用 一.简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛 ...

  8. Lambda表达式 简介 语法 示例

    Lambda 表达式也称为闭包,是匿名类的简短形式.Lambda 表达式简化了[单一抽象方法声明接口]的使用,因此 lambda 表达式也称为功能接口. 在 Java SE 7 中,单一方法接口可使用 ...

  9. Spring IO Platform简介及示例

    什么是Spring IO Platform Spring IO Platform,简单的可以认为是一个依赖维护平台,该平台将相关依赖汇聚到一起,针对每个依赖,都提供了一个版本号: 这些版本对应的依赖都 ...

  10. Lambda表达式 简介 语法 示例 匿名内部类

    在AS中使用 Lambda 表达式 Demo地址:https://github.com/baiqiantao/MultiTypeTest.git Gradle(Project级别)中添加classpa ...

随机推荐

  1. h5行情k线开发

    前言         由于公司项目需要,要做港股行情的H5版本,经过分析需求,大致有两块难点: 一是行情的推送接收,二是行情K线的生成及相关操作.本文章主要分析行情K线的相关实现,由于我们前端团队之前 ...

  2. 让ORM支持多结果集

    在现有的ORM框架中,都支持查询单个结果集.比如查询用户表,传入语句,返回一个用户对象的集合.虽然一次性查询多个结果集的情况不多,而且也可以通过多次查询得到,但是从写框架的角度来说,我们并不清楚客户( ...

  3. Python 编程:从入门到实战 读书笔记

    1..title()  每个单词首字母大写     .upper()  所有字母大写     .lower()  所有字母小写 2. \t 空白   转义字符只能用在""内     ...

  4. Kolla O版本部署

    Kolla O版部署和之前的版本还是有些区别的,环境还是all-in-one 基本准备: 关闭Selina和firewalld [root@kolla ~]# cat /etc/redhat-rele ...

  5. Python处理海量数据的实战研究

    最近看了July的一些关于Java处理海量数据的问题研究,深有感触,链接:http://blog.csdn.net/v_july_v/article/details/6685962 感谢July ^_ ...

  6. Java与GIS的联系

    Java与GIS的联系 地理信息系统是70年代初发展起来的一门新兴的边缘学科.    由于GIS在数据采集与输入.空间数据管理.地图提取.自动制图.数字地形分析.数据输出等方面具有强大而又独特的功能  ...

  7. [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)

    https://blog.csdn.net/xyz32768/article/details/83217209 不难找到DP方程与辅助DP方程,发现DP方程具有后效性,于是高斯消元即可. 但朴素消元显 ...

  8. [java][jboss]改变jboss部署目录(虚拟目录)

    原文: [java][jboss]改变jboss部署目录(虚拟目录) 在开发过程中,有时候我们希望将程序放在我们的源代码目录中,比如d:\code下,而不是放在jboss的deploy下,怎么办? 我 ...

  9. codevs 1052 地鼠游戏 优先队列

    1052 地鼠游戏 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1052/ Descriptio ...

  10. 和程序有关的一个游戏<<mu complex>> 攻略

    最速打法: 1 - login, brucedayton 2 - login, allomoto 3 - login, m3g4pa55word 4 - unlock, 03/18/34 5 - ss ...