ObservableRequest.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. package com.mylove.okhttp;
  2. import android.annotation.SuppressLint;
  3. import android.content.Context;
  4. import android.support.annotation.NonNull;
  5. import android.util.Log;
  6. import java.io.File;
  7. import java.io.IOException;
  8. import java.util.Map;
  9. import java.util.concurrent.TimeUnit;
  10. import io.reactivex.Observable;
  11. import io.reactivex.ObservableEmitter;
  12. import io.reactivex.ObservableOnSubscribe;
  13. import io.reactivex.Observer;
  14. import io.reactivex.android.schedulers.AndroidSchedulers;
  15. import io.reactivex.disposables.Disposable;
  16. import io.reactivex.schedulers.Schedulers;
  17. import okhttp3.Call;
  18. import okhttp3.Callback;
  19. import okhttp3.FormBody;
  20. import okhttp3.MediaType;
  21. import okhttp3.MultipartBody;
  22. import okhttp3.OkHttpClient;
  23. import okhttp3.Request;
  24. import okhttp3.RequestBody;
  25. import okhttp3.Response;
  26. /**
  27. * @author myLove
  28. */
  29. class ObservableRequest {
  30. @SuppressLint("StaticFieldLeak")
  31. private static ObservableRequest instance;
  32. @SuppressLint("StaticFieldLeak")
  33. private static Context mContext;
  34. private static RequestType requestType;
  35. private static CallType callType;
  36. private static OkHttpClient okHttpClient;
  37. private String mCacheUrl = "";
  38. static ObservableRequest getInstance(Context context, RequestType type1, CallType type2) {
  39. if (instance == null) {
  40. synchronized (ObservableRequest.class) {
  41. if (instance == null) {
  42. instance = new ObservableRequest();
  43. OkHttpClient httpClient = new OkHttpClient();
  44. okHttpClient = httpClient.newBuilder()
  45. .addNetworkInterceptor(new CacheInterceptor())
  46. .addInterceptor(Cache.HTTP_LOGGING_INTERCEPTOR)
  47. .cache(Cache.privateCache(context))
  48. .connectTimeout(30, TimeUnit.SECONDS)
  49. .readTimeout(30, TimeUnit.SECONDS)
  50. .build();
  51. }
  52. }
  53. }
  54. mContext = context;
  55. requestType = type1;
  56. callType = type2;
  57. return instance;
  58. }
  59. void request(String url, Map<Object, Object> oMap, final onOkHttpListener onOkHttpListener) {
  60. getObservable(url, oMap).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
  61. .serialize()//保证上游下游同一线程 ,防止不同线程下 onError 通知会跳到(并吞掉)原始Observable发射的数据项前面的错误行为
  62. .subscribe(new Observer<String>() {
  63. @Override
  64. public void onSubscribe(Disposable d) {
  65. }
  66. @Override
  67. public void onNext(String str) {
  68. onOkHttpListener.onSuccess(str);
  69. }
  70. @Override
  71. public void onError(Throwable e) {
  72. onOkHttpListener.onFailure(e);
  73. }
  74. @Override
  75. public void onComplete() {
  76. onOkHttpListener.onCompleted();
  77. }
  78. });
  79. }
  80. private Observable<String> getObservable(final String url, final Map<Object, Object> oMap) {
  81. return Observable.create(new ObservableOnSubscribe<String>() {
  82. @Override
  83. public void subscribe(ObservableEmitter<String> e) {
  84. send(url, oMap, e);
  85. }
  86. });
  87. }
  88. private void send(String url, Map<Object, Object> map, ObservableEmitter<String> subscriber) {
  89. if (FormatUtil.isMapNotEmpty(map)) {
  90. mCacheUrl = url + map.toString();
  91. } else {
  92. mCacheUrl = url;
  93. }
  94. InternetBean bean = Internet.ifInternet(mContext);
  95. if (bean.getStatus()) {
  96. Call call = okHttpClient.newCall(getRequest(url, map));
  97. sendCall(call, subscriber);
  98. } else {
  99. String json = CacheUtils.getInstance(mContext).getCacheToLocalJson(mCacheUrl);
  100. if (FormatUtil.isNotEmpty(json)) {
  101. subscriber.onNext(json);
  102. } else {
  103. subscriber.onError(new Error(bean.getMsg()));
  104. }
  105. subscriber.onComplete();
  106. }
  107. }
  108. /**
  109. * 请求
  110. */
  111. private void sendCall(Call call, ObservableEmitter<String> subscriber) {
  112. if (callType == CallType.SYNC) {
  113. sync(call, subscriber);
  114. } else if (callType == CallType.ASYNC) {
  115. async(call, subscriber);
  116. }
  117. }
  118. /**
  119. * 同步请求
  120. */
  121. private void sync(Call call, ObservableEmitter<String> subscriber) {
  122. try {
  123. Response execute = call.execute();
  124. if (execute.isSuccessful()) {
  125. String str = execute.body().string();
  126. if (OkHttpInfo.isLOG) {
  127. Log.v(OkHttpInfo.TAG, str);
  128. }
  129. if (!str.toUpperCase().contains("<!DOCTYPE HTML>")) {
  130. if (FormatUtil.isNotEmpty(mCacheUrl)) {
  131. CacheUtils.getInstance(mContext).setCacheToLocalJson(mCacheUrl, str);
  132. }
  133. }
  134. subscriber.onNext(str);
  135. subscriber.onComplete();
  136. } else {
  137. String json = CacheUtils.getInstance(mContext).getCacheToLocalJson(mCacheUrl);
  138. if (FormatUtil.isNotEmpty(json)) {
  139. subscriber.onNext(json);
  140. } else {
  141. subscriber.onError(new Exception("请求失败"));
  142. }
  143. subscriber.onComplete();
  144. }
  145. } catch (IOException e) {
  146. String json = CacheUtils.getInstance(mContext).getCacheToLocalJson(mCacheUrl);
  147. if (FormatUtil.isNotEmpty(json)) {
  148. subscriber.onNext(json);
  149. } else {
  150. subscriber.onError(e);
  151. }
  152. e.printStackTrace();
  153. subscriber.onComplete();
  154. }
  155. }
  156. /**
  157. * 异步请求
  158. */
  159. private void async(Call call, final ObservableEmitter<String> subscriber) {
  160. call.enqueue(new Callback() {
  161. @Override
  162. public void onFailure(@NonNull Call call, @NonNull IOException e) {
  163. String json = CacheUtils.getInstance(mContext).getCacheToLocalJson(mCacheUrl);
  164. if (FormatUtil.isNotEmpty(json)) {
  165. subscriber.onNext(json);
  166. } else {
  167. subscriber.onError(e);
  168. }
  169. e.printStackTrace();
  170. subscriber.onComplete();
  171. }
  172. @Override
  173. public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
  174. String str = response.body().string();
  175. if (OkHttpInfo.isLOG) {
  176. Log.v(OkHttpInfo.TAG, str);
  177. }
  178. if (!str.toUpperCase().contains("<!DOCTYPE HTML>")) {
  179. if (FormatUtil.isNotEmpty(mCacheUrl)) {
  180. CacheUtils.getInstance(mContext).setCacheToLocalJson(mCacheUrl, str);
  181. }
  182. }
  183. subscriber.onNext(str);
  184. subscriber.onComplete();
  185. }
  186. });
  187. }
  188. private Request request(String url, Map<Object, Object> map) {
  189. FormBody.Builder builder = new FormBody.Builder();
  190. if (FormatUtil.isMapNotEmpty(map)) {
  191. for (Map.Entry<Object, Object> entry : map.entrySet()) {
  192. builder.add(entry.getKey().toString(), entry.getValue().toString());
  193. }
  194. }
  195. FormBody build = builder.build();
  196. return new Request.Builder()
  197. .url(url)
  198. .post(build)
  199. .build();
  200. }
  201. /**
  202. * 判断请求方式
  203. *
  204. * @param url 地址
  205. * @param oMap 键值
  206. * @return request
  207. */
  208. private Request getRequest(String url, Map<Object, Object> oMap) {
  209. if (requestType == null) {
  210. requestType = RequestType.POST;
  211. }
  212. switch (requestType) {
  213. case GET:
  214. return get(url, oMap);
  215. case POST_XML_SOAP:
  216. return postXMLToSoap(url, oMap);
  217. case UP_FILE:
  218. return upFile(url, oMap);
  219. case ALL:
  220. return upAll(url, oMap);
  221. case POST:
  222. default:
  223. return post(url, oMap);
  224. }
  225. }
  226. private Request postXMLToSoap(String url, Map<Object, Object> oMap) {
  227. if (FormatUtil.isEmpty(OkHttpInfo.soapDataTopString)) {
  228. throw new NullPointerException("OkHttpInfo.soapDataTopString不能为空");
  229. }
  230. if (FormatUtil.isEmpty(OkHttpInfo.soapDataBottomString)) {
  231. throw new NullPointerException("OkHttpInfo.soapDataBottomString不能为空");
  232. }
  233. StringBuilder sb = new StringBuilder();
  234. if (FormatUtil.isMapNotEmpty(oMap)) {
  235. for (Map.Entry<Object, Object> entry : oMap.entrySet()) {
  236. String key = entry.getKey().toString();
  237. String value = entry.getValue().toString();
  238. sb.append("<").append(key).append(">").append(value).append("</").append(key).append(">");
  239. }
  240. }
  241. MediaType mediaType = MediaType.parse(OkHttpInfo.soapMediaType);
  242. String str = OkHttpInfo.soapDataTopString + sb + OkHttpInfo.soapDataBottomString;
  243. if (OkHttpInfo.isLOG) {
  244. Log.v(OkHttpInfo.TAG, str);
  245. }
  246. return new Request.Builder()
  247. .url(url)
  248. .post(RequestBody.create(mediaType, str))
  249. .build();
  250. }
  251. /**
  252. * 上传文件
  253. *
  254. * @param url 地址
  255. * @param oMap 键值
  256. * @return request
  257. */
  258. private Request upFile(String url, Map<Object, Object> oMap) {
  259. MultipartBody.Builder builder = new MultipartBody.Builder()
  260. .setType(MultipartBody.FORM);
  261. if (FormatUtil.isMapNotEmpty(oMap)) {
  262. for (Map.Entry<Object, Object> entry : oMap.entrySet()) {
  263. File file = new File(entry.getValue().toString());
  264. int indexOf = entry.getValue().toString().indexOf("/");
  265. RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
  266. String fileName = entry.getKey().toString().substring(indexOf + 1, entry.getKey().toString().length());
  267. builder.addFormDataPart(entry.getKey().toString(), fileName, requestBody);
  268. }
  269. }
  270. MultipartBody multipartBody = builder.build();
  271. return new Request.Builder()
  272. .url(url)
  273. .post(multipartBody)
  274. .build();
  275. }
  276. /**
  277. * 参数和文件一起上传
  278. *
  279. * @param url 地址
  280. * @param oMap 键值
  281. * @return request
  282. */
  283. private Request upAll(String url, Map<Object, Object> oMap) {
  284. MultipartBody.Builder builder = new MultipartBody.Builder()
  285. .setType(MultipartBody.ALTERNATIVE);
  286. if (FormatUtil.isMapNotEmpty(oMap)) {
  287. for (Map.Entry<Object, Object> entry : oMap.entrySet()) {
  288. int indexOf = entry.getValue().toString().lastIndexOf("/");
  289. int indexOf1 = entry.getValue().toString().lastIndexOf(".");
  290. if (indexOf > 0 && indexOf1 > 0) {
  291. File file = new File(entry.getValue().toString());
  292. RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
  293. String fileName = entry.getKey().toString().substring(indexOf + 1, entry.getKey().toString().length());
  294. builder.addFormDataPart(entry.getKey().toString(), fileName, requestBody);
  295. } else {
  296. builder.addFormDataPart(entry.getKey().toString(), entry.getValue().toString());
  297. }
  298. }
  299. }
  300. MultipartBody multipartBody = builder.build();
  301. return new Request.Builder()
  302. .url(url)
  303. .post(multipartBody)
  304. .build();
  305. }
  306. /**
  307. * get上传参数
  308. *
  309. * @param url 地址
  310. * @param oMap 键值
  311. * @return request
  312. */
  313. private Request get(String url, Map<Object, Object> oMap) {
  314. StringBuilder str = new StringBuilder(url);
  315. if (FormatUtil.isMapNotEmpty(oMap)) {
  316. str.append("?");
  317. for (Map.Entry<Object, Object> entry : oMap.entrySet()) {
  318. str.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
  319. }
  320. str = new StringBuilder(str.substring(0, str.length() - 1));
  321. }
  322. if (OkHttpInfo.isLOG) {
  323. Log.v(OkHttpInfo.TAG, str.toString());
  324. }
  325. return new Request.Builder()
  326. .url(str.toString())
  327. .get()
  328. .build();
  329. }
  330. /**
  331. * post上传参数
  332. *
  333. * @param url 地址
  334. * @param oMap 键值
  335. * @return request
  336. */
  337. private Request post(String url, Map<Object, Object> oMap) {
  338. FormBody.Builder builder = new FormBody.Builder();
  339. if (FormatUtil.isMapNotEmpty(oMap)) {
  340. for (Map.Entry<Object, Object> entry : oMap.entrySet()) {
  341. builder.add(entry.getKey().toString(), entry.getValue().toString());
  342. }
  343. }
  344. FormBody build = builder.build();
  345. return new Request.Builder()
  346. .url(url)
  347. .post(build)
  348. .build();
  349. }
  350. }