Repository: wzgiceman/RxjavaRetrofitDemo-string-master Branch: master Commit: 2da6db038824 Files: 83 Total size: 121.3 KB Directory structure: gitextract_jkr4_2v7/ ├── .gitignore ├── .idea/ │ ├── caches/ │ │ └── build_file_checksums.ser │ ├── codeStyles/ │ │ └── Project.xml │ ├── compiler.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── LICENSE ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ └── retrofit/ │ │ ├── HttpPostService.java │ │ ├── HttpUploadService.java │ │ ├── MyApplication.java │ │ ├── activity/ │ │ │ ├── CombinApiActivity.java │ │ │ ├── DownLaodActivity.java │ │ │ ├── MainActivity.java │ │ │ └── adapter/ │ │ │ ├── DownAdapter.java │ │ │ └── DownHolder.java │ │ └── entity/ │ │ ├── api/ │ │ │ ├── CombinApi.java │ │ │ ├── SubjectPostApi.java │ │ │ └── UploadApi.java │ │ └── resulte/ │ │ ├── BaseResultEntity.java │ │ ├── RetrofitEntity.java │ │ ├── SubjectResulte.java │ │ └── UploadResulte.java │ └── res/ │ ├── layout/ │ │ ├── activity_combin_api.xml │ │ ├── activity_down_laod.xml │ │ ├── activity_main.xml │ │ └── view_item_holder.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── build.gradle ├── butterniffe读取.html ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── rxretrofitlibrary/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── wzgiceman/ │ │ └── rxretrofitlibrary/ │ │ └── retrofit_rx/ │ │ ├── Api/ │ │ │ ├── BaseApi.java │ │ │ └── HttpManagerApi.java │ │ ├── RxRetrofitApp.java │ │ ├── downlaod/ │ │ │ ├── DownInfo.java │ │ │ ├── DownLoadListener/ │ │ │ │ ├── DownloadInterceptor.java │ │ │ │ ├── DownloadProgressListener.java │ │ │ │ └── DownloadResponseBody.java │ │ │ ├── DownState.java │ │ │ ├── HttpDownManager.java │ │ │ └── HttpDownService.java │ │ ├── exception/ │ │ │ ├── ApiException.java │ │ │ ├── CodeException.java │ │ │ ├── FactoryException.java │ │ │ ├── HttpTimeException.java │ │ │ └── RetryWhenNetworkException.java │ │ ├── http/ │ │ │ ├── HttpManager.java │ │ │ ├── cookie/ │ │ │ │ ├── CacheInterceptor.java │ │ │ │ └── CookieResulte.java │ │ │ └── func/ │ │ │ ├── ExceptionFunc.java │ │ │ └── ResulteFunc.java │ │ ├── listener/ │ │ │ ├── HttpDownOnNextListener.java │ │ │ ├── HttpOnNextListener.java │ │ │ ├── HttpOnNextSubListener.java │ │ │ └── upload/ │ │ │ ├── ProgressRequestBody.java │ │ │ └── UploadProgressListener.java │ │ ├── subscribers/ │ │ │ ├── ProgressDownSubscriber.java │ │ │ └── ProgressSubscriber.java │ │ └── utils/ │ │ ├── AppUtil.java │ │ ├── CookieDbUtil.java │ │ └── DbDwonUtil.java │ └── res/ │ └── values/ │ └── strings.xml └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures ================================================ FILE: .idea/codeStyles/Project.xml ================================================ ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/encodings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/runConfigurations.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 tough1985 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ## Rxjava+ReTrofit+okHttp深入浅出-终极封装特殊篇(替换Gson返回) ## 介绍 封装原理博客专栏: >[Rxjava+ReTrofit+okHttp深入浅出-终极封装](http://blog.csdn.net/column/details/13297.html) 介绍如何放弃GsonConverterFactory,直接返回String,灵活我们的封装! >[兄弟版本-Rxjava+ReTrofit+okHttp深入浅出-终极封装Gson方案](https://github.com/wzgiceman/RxjavaRetrofitDemo-master) ## 具备功能 1.Retrofit+Rxjava+okhttp基本使用方法 2.统一处理请求数据格式 3.统一的ProgressDialog和回调Subscriber处理 4.取消http请求 5.预处理http请求 6.返回数据的统一判断 7.失败后的retry处理 8.RxLifecycle管理生命周期,防止泄露 9.文件上传下载(支持多文件,断点续传) 10.Cache数据持久化和数据库(greenDao)两种缓存机制 11.异常统一处理 ## 效果 ![Preview](https://github.com/wzgiceman/RxjavaRetrofitDemo-string-master/blob/master/gif/rxretrofit.gif) ## 使用 ### 1.初始化 moudel导入工程 ```java compile project(':rxretrofitlibrary') ``` 在Application中初始化RxRetrofitApp ```java RxRetrofitApp.init(this); ``` ### 2.初始化HttpManager 需要传递一个回调HttpOnNextListener接口和activity生命周期 ```java HttpManager manager=new HttpManager(this,this); ``` ### 3.初始请求的数据和参数 ```java public class SubjectPostApi extends BaseApi { // 接口需要传入的参数 可自定义不同类型 private boolean all; /*任何你先要传递的参数*/ // String xxxxx; /** * 默认初始化需要给定回调和rx周期类 * 可以额外设置请求设置加载框显示,回调等(可扩展) */ public SubjectPostApi() { setShowProgress(true); setCancel(true); setCache(true); setMothed("AppFiftyToneGraph/videoLink"); setCookieNetWorkTime(60); setCookieNoNetWorkTime(24*60*60); } /** *通过自定义sercie得到Observable对象 *sercie可动态设置,方便扩展 */ @Override public Observable getObservable(Retrofit retrofit) { HttpPostService httpService = retrofit.create(HttpPostService.class); return httpService.getAllVedioBy(isAll()); } } ``` ### 4.请求后的统一处理 通过method参数判断接口,然后动态解析返回的数据 ```java @Override public void onNext(String resulte, String method) { /*post返回处理*/ if(method.equals(postEntity.getMothed())){ List subjectResulte= JSONObject.parseArray(resulte,SubjectResulte.class); tvMsg.setText("post返回:\n"+subjectResulte.toString() ); } /*上传返回处理*/ if(method.equals(uplaodApi.getMothed())){ UploadResulte uploadResulte=JSONObject.parseObject(resulte,UploadResulte.class); tvMsg.setText("上传成功返回:\n"+uploadResulte.getHeadImgUrl()); Glide.with(MainActivity.this).load(uploadResulte.getHeadImgUrl()).skipMemoryCache(true).into(img); } } @Override public void onError(Throwable e) { tvMsg.setText("失败:\n" + e.toString()); } ``` * 初始化一个请求数据的对象继承BaseApi对象设置请求需要的参数 * 通过httpmanger对象,触发请求 * 结果统一通过BaseApi中的fun1方法判断,最后返回HttpOnNextListener ## 优化迭代 根据反馈及时更新和优化的过程,如果在使用过程中有任何问题,欢迎反馈给我! ## 思路 详细思路可以可以参看我的博客: [Rxjava+ReTrofit+okHttp深入浅出-终极封装](http://blog.csdn.net/column/details/13297.html) ## QQ交流群 ![](https://github.com/wzgiceman/Rxbus/blob/master/gif/qq.png) ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 26 buildToolsVersion '27.0.3' defaultConfig { applicationId "com.example.retrofit" minSdkVersion 16 targetSdkVersion 26 versionCode 2 versionName "2.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile project(':rxretrofitlibrary') compile 'com.daimajia.numberprogressbar:library:1.2@aar' compile 'com.github.bumptech.glide:glide:3.6.1' compile 'com.jude:easyrecyclerview:4.2.6' compile 'com.android.support:recyclerview-v7:26.0.2' compile 'com.alibaba:fastjson:latest.integration' compile 'com.android.support:appcompat-v7:26.0.2' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/liukun/Developer/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/java/com/example/retrofit/HttpPostService.java ================================================ package com.example.retrofit; import retrofit2.http.GET; import retrofit2.http.Query; import rx.Observable; /** * 测试接口service-post相关 * Created by WZG on 2016/12/19. */ public interface HttpPostService { @GET("AppFiftyToneGraph/videoLink/{once_no}") Observable getAllVedioBy(@Query("once_no") boolean once_no); } ================================================ FILE: app/src/main/java/com/example/retrofit/HttpUploadService.java ================================================ package com.example.retrofit; import okhttp3.MultipartBody; import okhttp3.RequestBody; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.Part; import rx.Observable; /** * 测试接口service-上传相关 * Created by WZG on 2016/12/19. */ public interface HttpUploadService { /*上传文件*/ @Multipart @POST("AppYuFaKu/uploadHeadImg") Observable uploadImage(@Part("uid") RequestBody uid, @Part("auth_key") RequestBody auth_key, @Part MultipartBody.Part file); } ================================================ FILE: app/src/main/java/com/example/retrofit/MyApplication.java ================================================ package com.example.retrofit; import android.app.Application; import android.content.Context; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; /** * Created by WZG on 2016/10/25. */ public class MyApplication extends Application{ public static Context app; @Override public void onCreate() { super.onCreate(); app=getApplicationContext(); RxRetrofitApp.init(this,BuildConfig.DEBUG); } } ================================================ FILE: app/src/main/java/com/example/retrofit/activity/CombinApiActivity.java ================================================ package com.example.retrofit.activity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.example.retrofit.R; import com.example.retrofit.entity.api.CombinApi; import com.example.retrofit.entity.resulte.BaseResultEntity; import com.example.retrofit.entity.resulte.SubjectResulte; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.ApiException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import java.util.ArrayList; /** * 统一api类处理方案界面 * * @author wzg */ public class CombinApiActivity extends RxAppCompatActivity implements HttpOnNextListener { private TextView tvMsg; CombinApi api; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_combin_api); api = new CombinApi(this, this); tvMsg = (TextView) findViewById(R.id.tv_msg); findViewById(R.id.btn_rx_all).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { api.postApi(true); } }); findViewById(R.id.btn_rx_all_2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { api.postApiOther(true); } }); } @Override public void onNext(String resulte, String method) { BaseResultEntity> subjectResulte = JSONObject.parseObject(resulte, new TypeReference>>() { }); tvMsg.setText("统一post返回:\n" + subjectResulte.getData().toString()); } @Override public void onError(ApiException e, String method) { tvMsg.setText("失败:"+method+"\ncode=" + e.getCode() + "\nmsg:" + e.getDisplayMessage()); } } ================================================ FILE: app/src/main/java/com/example/retrofit/activity/DownLaodActivity.java ================================================ package com.example.retrofit.activity; import android.app.Activity; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import com.example.retrofit.R; import com.example.retrofit.activity.adapter.DownAdapter; import com.jude.easyrecyclerview.EasyRecyclerView; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfo; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.DbDwonUtil; import java.io.File; import java.util.List; /** * 多任務下載 */ public class DownLaodActivity extends AppCompatActivity { List listData; DbDwonUtil dbUtil; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_down_laod); verifyStoragePermissions(this); initResource(); initWidget(); } /*数据*/ private void initResource() { dbUtil = DbDwonUtil.getInstance(); listData = dbUtil.queryDownAll(); /*第一次模拟服务器返回数据掺入到数据库中*/ if (listData.isEmpty()) { String[] downUrl = new String[]{"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4", "http://clips.vorwaerts-gmbh" + ".de/big_buck_bunny.mp4"}; for (int i = 0; i < downUrl.length; i++) { File outputFile = new File(getExternalFilesDir(null), "tetst" + i + ".mp4"); DownInfo apkApi = new DownInfo(downUrl[i]); apkApi.setId(i); apkApi.setUpdateProgress(true); apkApi.setSavePath(outputFile.getAbsolutePath()); dbUtil.save(apkApi); } listData = dbUtil.queryDownAll(); } } /*加载控件*/ private void initWidget() { EasyRecyclerView recyclerView = (EasyRecyclerView) findViewById(R.id.rv); DownAdapter adapter = new DownAdapter(this); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); adapter.addAll(listData); } @Override protected void onDestroy() { super.onDestroy(); /*记录退出时下载任务的状态-复原用*/ for (DownInfo downInfo : listData) { dbUtil.update(downInfo); } } private final int REQUEST_EXTERNAL_STORAGE = 1; private String[] PERMISSIONS_STORAGE = { "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"}; /** * 申请权限 * @param activity */ public void verifyStoragePermissions(Activity activity) { try { //检测是否有写的权限 int permission = ActivityCompat.checkSelfPermission(activity, "android.permission.WRITE_EXTERNAL_STORAGE"); if (permission != PackageManager.PERMISSION_GRANTED) { // 没有写的权限,去申请写的权限,会弹出对话框 ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } catch (Exception e) { e.printStackTrace(); } } } ================================================ FILE: app/src/main/java/com/example/retrofit/activity/MainActivity.java ================================================ package com.example.retrofit.activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.bumptech.glide.Glide; import com.daimajia.numberprogressbar.NumberProgressBar; import com.example.retrofit.R; import com.example.retrofit.entity.api.SubjectPostApi; import com.example.retrofit.entity.api.UploadApi; import com.example.retrofit.entity.resulte.BaseResultEntity; import com.example.retrofit.entity.resulte.SubjectResulte; import com.example.retrofit.entity.resulte.UploadResulte; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.ApiException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.HttpManager; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.upload.ProgressRequestBody; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.upload.UploadProgressListener; import java.io.File; import java.util.ArrayList; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; public class MainActivity extends RxAppCompatActivity implements View.OnClickListener, HttpOnNextListener { private TextView tvMsg; private NumberProgressBar progressBar; private ImageView img; // 公用一个HttpManager private HttpManager manager; // post请求接口信息 private SubjectPostApi postEntity; // 上传接口信息 private UploadApi uplaodApi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvMsg = (TextView) findViewById(R.id.tv_msg); findViewById(R.id.btn_rx).setOnClickListener(this); findViewById(R.id.btn_rx_all).setOnClickListener(this); findViewById(R.id.btn_rx_mu_down).setOnClickListener(this); findViewById(R.id.btn_rx_uploade).setOnClickListener(this); img = (ImageView) findViewById(R.id.img); progressBar = (NumberProgressBar) findViewById(R.id.number_progress_bar); /*初始化数据*/ manager = new HttpManager(this, this); postEntity = new SubjectPostApi(); postEntity.setAll(true); /*上传接口内部接口有token验证,所以需要换成自己的接口测试,检查file文件是否手机存在*/ uplaodApi = new UploadApi(); File file = new File("/storage/emulated/0/Download/11.jpg"); RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), file); MultipartBody.Part part = MultipartBody.Part.createFormData("file_name", file.getName(), new ProgressRequestBody (requestBody, new UploadProgressListener() { @Override public void onProgress(final long currentBytesCount, final long totalBytesCount) { /*回到主线程中,可通过timer等延迟或者循环避免快速刷新数据*/ Observable.just(currentBytesCount).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1() { @Override public void call(Long aLong) { tvMsg.setText("提示:上传中"); progressBar.setMax((int) totalBytesCount); progressBar.setProgress((int) currentBytesCount); } }); } })); uplaodApi.setPart(part); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_rx_all: Intent intentC = new Intent(this, CombinApiActivity.class); startActivity(intentC); break; case R.id.btn_rx: manager.doHttpDeal(postEntity); break; case R.id.btn_rx_uploade: manager.doHttpDeal(uplaodApi); break; case R.id.btn_rx_mu_down: Intent intent = new Intent(this, DownLaodActivity.class); startActivity(intent); break; } } @Override public void onNext(String resulte, String mothead) { /*post返回处理*/ if (mothead.equals(postEntity.getMethod())) { BaseResultEntity> subjectResulte = JSONObject.parseObject(resulte, new TypeReference>>() { }); tvMsg.setText("post返回:\n" + subjectResulte.getData().toString()); } /*上传返回处理*/ if (mothead.equals(uplaodApi.getMethod())) { BaseResultEntity subjectResulte = JSONObject.parseObject(resulte, new TypeReference>() { }); UploadResulte uploadResulte = subjectResulte.getData(); tvMsg.setText("上传成功返回:\n" + uploadResulte.getHeadImgUrl()); Glide.with(MainActivity.this).load(uploadResulte.getHeadImgUrl()).skipMemoryCache(true).into(img); } } @Override public void onError(ApiException e, String method) { tvMsg.setText("失败:"+method+"\ncode=" + e.getCode() + "\nmsg:" + e.getDisplayMessage()); } } ================================================ FILE: app/src/main/java/com/example/retrofit/activity/adapter/DownAdapter.java ================================================ package com.example.retrofit.activity.adapter; import android.content.Context; import android.view.ViewGroup; import com.jude.easyrecyclerview.adapter.BaseViewHolder; import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfo; /** * Created by WZG on 2016/10/21. */ public class DownAdapter extends RecyclerArrayAdapter { public DownAdapter(Context context) { super(context); } @Override public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { return new DownHolder(parent); } } ================================================ FILE: app/src/main/java/com/example/retrofit/activity/adapter/DownHolder.java ================================================ package com.example.retrofit.activity.adapter; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.daimajia.numberprogressbar.NumberProgressBar; import com.example.retrofit.R; import com.jude.easyrecyclerview.adapter.BaseViewHolder; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfo; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownState; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.HttpDownManager; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpDownOnNextListener; /** * 下载item * Created by WZG on 2016/10/21. */ public class DownHolder extends BaseViewHolder implements View.OnClickListener { private TextView tvMsg; private NumberProgressBar progressBar; private DownInfo apkApi; private HttpDownManager manager; public DownHolder(ViewGroup parent) { super(parent, R.layout.view_item_holder); manager = HttpDownManager.getInstance(); $(R.id.btn_rx_down).setOnClickListener(this); $(R.id.btn_rx_pause).setOnClickListener(this); progressBar = $(R.id.number_progress_bar); tvMsg = $(R.id.tv_msg); } @Override public void setData(DownInfo data) { super.setData(data); data.setListener(httpProgressOnNextListener); apkApi = data; progressBar.setMax((int) apkApi.getCountLength()); progressBar.setProgress((int) apkApi.getReadLength()); /*第一次恢复 */ switch (apkApi.getState()) { case START: /*起始状态*/ break; case PAUSE: tvMsg.setText("暂停中"); break; case DOWN: manager.startDown(apkApi); break; case STOP: tvMsg.setText("下载停止"); break; case ERROR: tvMsg.setText("下載錯誤"); break; case FINISH: tvMsg.setText("下载完成"); break; } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_rx_down: if (apkApi.getState() != DownState.FINISH) { manager.startDown(apkApi); } break; case R.id.btn_rx_pause: manager.pause(apkApi); break; } } /*下载回调*/ HttpDownOnNextListener httpProgressOnNextListener = new HttpDownOnNextListener() { @Override public void onNext(DownInfo baseDownEntity) { tvMsg.setText("提示:下载完成->" + baseDownEntity.getSavePath()); } @Override public void onStart() { tvMsg.setText("提示:开始下载"); } @Override public void onComplete() { } @Override public void onError(Throwable e) { super.onError(e); tvMsg.setText("失败:" + e.toString()); } @Override public void onPuase() { super.onPuase(); tvMsg.setText("提示:暂停"); } @Override public void onStop() { super.onStop(); } @Override public void updateProgress(long readLength, long countLength) { Log.e("tag", countLength + "--->" + readLength); tvMsg.setText("提示:下载中"); progressBar.setMax((int) countLength); progressBar.setProgress((int) readLength); } }; } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/api/CombinApi.java ================================================ package com.example.retrofit.entity.api; import com.example.retrofit.HttpPostService; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api.HttpManagerApi; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextSubListener; /** * 多api共存方案 * Created by WZG on 2017/4/13. */ public class CombinApi extends HttpManagerApi { public CombinApi(HttpOnNextListener onNextListener, RxAppCompatActivity appCompatActivity) { super(onNextListener, appCompatActivity); /*统一设置*/ setCache(true); } public CombinApi(HttpOnNextSubListener onNextSubListener, RxAppCompatActivity appCompatActivity) { super(onNextSubListener, appCompatActivity); /*统一设置*/ setCache(true); } /** * post请求演示 * api-1 * * @param all 参数 */ public void postApi(final boolean all) { /*也可单独设置请求,会覆盖统一设置*/ setCache(false); setMethod("AppFiftyToneGraph/videoLink"); HttpPostService httpService = getRetrofit().create(HttpPostService.class); doHttpDeal(httpService.getAllVedioBy(all)); } /** * post请求演示 * api-2 * * @param all 参数 */ public void postApiOther(boolean all) { setCache(true); setMethod("AppFiftyToneGraph/videoLink"); HttpPostService httpService = getRetrofit().create(HttpPostService.class); doHttpDeal(httpService.getAllVedioBy(all)); } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/api/SubjectPostApi.java ================================================ package com.example.retrofit.entity.api; import com.example.retrofit.HttpPostService; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api.BaseApi; import retrofit2.Retrofit; import rx.Observable; /** * 测试数据 * Created by WZG on 2016/7/16. */ public class SubjectPostApi extends BaseApi { // 接口需要传入的参数 可自定义不同类型 private boolean all; /*任何你先要传递的参数*/ // String xxxxx; // String xxxxx; // String xxxxx; // String xxxxx; /** * 默认初始化需要给定初始设置 * 可以额外设置请求设置加载框显示,回调等(可扩展) * 设置可查看BaseApi */ public SubjectPostApi() { setCache(false); setMethod("AppFiftyToneGraph/videoLink"); } public boolean isAll() { return all; } public void setAll(boolean all) { this.all = all; } @Override public Observable getObservable(Retrofit retrofit) { HttpPostService httpService = retrofit.create(HttpPostService.class); return httpService.getAllVedioBy(isAll()); } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/api/UploadApi.java ================================================ package com.example.retrofit.entity.api; import com.example.retrofit.HttpUploadService; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api.BaseApi; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; import retrofit2.Retrofit; import rx.Observable; /** * 上传请求api * Created by WZG on 2016/10/20. */ public class UploadApi extends BaseApi { /*需要上传的文件*/ private MultipartBody.Part part; public UploadApi() { setShowProgress(true); setMethod("AppYuFaKu/uploadHeadImg"); setCache(false); } public MultipartBody.Part getPart() { return part; } public void setPart(MultipartBody.Part part) { this.part = part; } @Override public Observable getObservable(Retrofit retrofit) { HttpUploadService httpService = retrofit.create(HttpUploadService.class); RequestBody uid= RequestBody.create(MediaType.parse("text/plain"), "4811420"); RequestBody key = RequestBody.create(MediaType.parse("text/plain"), "2bd467f727cdf2138c1067127e057950"); return httpService.uploadImage(uid,key,getPart()); } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/resulte/BaseResultEntity.java ================================================ package com.example.retrofit.entity.resulte; /** * 回调信息统一封装类 * Created by WZG on 2016/7/16. */ public class BaseResultEntity{ // 判断标示 private int ret; // 提示信息 private String msg; //显示数据(用户需要关心的数据) private T data; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getRet() { return ret; } public void setRet(int ret) { this.ret = ret; } public T getData() { return data; } public void setData(T data) { this.data = data; } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/resulte/RetrofitEntity.java ================================================ package com.example.retrofit.entity.resulte; import java.util.List; /** * 直接请求返回数据格式 * Created by WZG on 2016/7/16. */ public class RetrofitEntity { private int ret; private String msg; private List data; public int getRet() { return ret; } public void setRet(int ret) { this.ret = ret; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public List getData() { return data; } public void setData(List data) { this.data = data; } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/resulte/SubjectResulte.java ================================================ package com.example.retrofit.entity.resulte; /** * 测试显示数据 * Created by WZG on 2016/7/16. */ public class SubjectResulte { private int id; private String name; private String title; @Override public String toString() { return "name->"+name+"\n"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } ================================================ FILE: app/src/main/java/com/example/retrofit/entity/resulte/UploadResulte.java ================================================ package com.example.retrofit.entity.resulte; /** * 上传回调结果 * Created by WZG on 2016/10/20. */ public class UploadResulte { /** * headImgUrl : http://www.izaodao.com/uc/data/avatar/004/81/14/20_avatar_middle.jpg?timestamp=1476943817 */ private String headImgUrl; public String getHeadImgUrl() { return headImgUrl; } public void setHeadImgUrl(String headImgUrl) { this.headImgUrl = headImgUrl; } } ================================================ FILE: app/src/main/res/layout/activity_combin_api.xml ================================================ ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Wed Apr 18 09:52:05 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip ================================================ FILE: gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: rxretrofitlibrary/.gitignore ================================================ /build ================================================ FILE: rxretrofitlibrary/build.gradle ================================================ apply plugin: 'com.android.library' apply plugin: 'org.greenrobot.greendao' android { compileSdkVersion 26 buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 14 targetSdkVersion 25 versionCode 2 versionName "2.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'org.greenrobot:greendao:3.2.0' /*rx-android-java*/ compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.trello:rxlifecycle:1.0' compile 'com.trello:rxlifecycle-components:1.0' /*rotrofit*/ compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-scalars:2.0.0' compile 'com.squareup.okhttp3:logging-interceptor:3.1.2' } ================================================ FILE: rxretrofitlibrary/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in G:\sdk\sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: rxretrofitlibrary/src/main/AndroidManifest.xml ================================================ ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/Api/BaseApi.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api; import retrofit2.Retrofit; import rx.Observable; /** * Describe:请求数据统一封装类 *

* Created by zhigang wei * on 2017/8/29. *

* Company :Sichuan Ziyan */ public abstract class BaseApi { /*是否能取消加载框*/ private transient boolean cancel = true; /*是否显示加载框*/ private transient boolean showProgress = true; /*是否需要缓存处理*/ protected transient boolean cache = false; /*固定基础url*/ public transient static final String BASE_URL = "http://ss.afr99.com/"; /*基础url*/ private transient static String baseUrl; /*方法-如果需要缓存必须设置这个参数;不需要不用設置*/ private transient String method = ""; /*超时时间-默认10秒*/ private transient int connectionTime = 15; /*有网情况下的本地缓存时间默xxx秒*/ private transient int cookieNetWorkTime = 60; /*无网络的情况下本地缓存时间默认30天*/ private transient int cookieNoNetWorkTime = 24 * 60 * 60 * 30; /* retry次数*/ private transient int retryCount = 0; /*retry延迟*/ private transient long retryDelay = 100; /*retry叠加延迟*/ private transient long retryIncreaseDelay = 100; /*缓存url*/ private transient String cacheUrl; /*常用服务器校验字段*/ private transient static String config; /*忽略结果判断*/ private transient boolean ignorJudge; /*忽略自带sub处理*/ private transient boolean noSub; /** * 设置参数 * * @param retrofit * @return */ public abstract Observable getObservable(Retrofit retrofit); public boolean isNoSub() { return noSub; } public void setNoSub(boolean noSub) { this.noSub = noSub; } public int getCookieNoNetWorkTime() { return cookieNoNetWorkTime; } public void setCookieNoNetWorkTime(int cookieNoNetWorkTime) { this.cookieNoNetWorkTime = cookieNoNetWorkTime; } public int getCookieNetWorkTime() { return cookieNetWorkTime; } public void setCookieNetWorkTime(int cookieNetWorkTime) { this.cookieNetWorkTime = cookieNetWorkTime; } public int getConnectionTime() { return connectionTime; } public void setConnectionTime(int connectionTime) { this.connectionTime = connectionTime; } public String getBaseUrl() { return isEmpty(baseUrl) ? BASE_URL : baseUrl; } public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; } public String getUrl() { return getBaseUrl() + getMethod(); } public boolean isCache() { return cache; } public void setCache(boolean cache) { this.cache = cache; } public boolean isShowProgress() { return showProgress; } public void setShowProgress(boolean showProgress) { this.showProgress = showProgress; } public boolean isCancel() { return cancel; } public void setCancel(boolean cancel) { this.cancel = cancel; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public int getRetryCount() { return retryCount; } public void setRetryCount(int retryCount) { this.retryCount = retryCount; } public long getRetryDelay() { return retryDelay; } public void setRetryDelay(long retryDelay) { this.retryDelay = retryDelay; } public long getRetryIncreaseDelay() { return retryIncreaseDelay; } public void setRetryIncreaseDelay(long retryIncreaseDelay) { this.retryIncreaseDelay = retryIncreaseDelay; } public boolean isIgnorJudge() { return ignorJudge; } public void setIgnorJudge(boolean ignorJudge) { this.ignorJudge = ignorJudge; } public String getCacheUrl() { if (isEmpty(cacheUrl)) { return getUrl(); } return cacheUrl; } public void setCacheUrl(String cacheUrl) { this.cacheUrl = cacheUrl; } private boolean isEmpty(String str) { return str == null || str.trim().length() == 0 || str.equals("null"); } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/Api/HttpManagerApi.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.HttpManager; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextSubListener; import retrofit2.Retrofit; import rx.Observable; /** * 请求数据统一封装类 * Created by WZG on 2016/7/16. */ public class HttpManagerApi extends BaseApi { private HttpManager manager; public HttpManagerApi(HttpOnNextListener onNextListener, RxAppCompatActivity appCompatActivity) { manager = new HttpManager(onNextListener, appCompatActivity); } public HttpManagerApi(HttpOnNextSubListener onNextSubListener, RxAppCompatActivity appCompatActivity) { manager = new HttpManager(onNextSubListener, appCompatActivity); } protected Retrofit getRetrofit() { return manager.getReTrofit(this); } protected void doHttpDeal(Retrofit retrofit) { manager.httpDeal(retrofit, this); } @Override public Observable getObservable(Retrofit retrofit) { return null; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/RxRetrofitApp.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx; import android.app.Application; /** * 全局app * Created by WZG on 2016/12/12. */ public class RxRetrofitApp { private static Application application; private static boolean debug; public static void init(Application app){ setApplication(app); setDebug(true); } public static void init(Application app,boolean debug){ setApplication(app); setDebug(debug); } public static Application getApplication() { return application; } private static void setApplication(Application application) { RxRetrofitApp.application = application; } public static boolean isDebug() { return debug; } public static void setDebug(boolean debug) { RxRetrofitApp.debug = debug; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/DownInfo.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpDownOnNextListener; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Keep; import org.greenrobot.greendao.annotation.Transient; import org.greenrobot.greendao.annotation.Generated; /** * apk下载请求数据基础类 * Created by WZG on 2016/10/20. */ @Entity public class DownInfo{ @Id private long id; /*存储位置*/ private String savePath; /*文件总长度*/ private long countLength; /*下载长度*/ private long readLength; /*下载唯一的HttpService*/ @Transient private HttpDownService service; /*回调监听*/ @Transient private HttpDownOnNextListener listener; /*超时设置*/ private int connectonTime=6; /*state状态数据库保存*/ private int stateInte; /*url*/ private String url; /*是否需要实时更新下载进度,避免线程的多次切换*/ private boolean updateProgress; public DownInfo(String url,HttpDownOnNextListener listener) { setUrl(url); setListener(listener); } public DownInfo(String url) { setUrl(url); } @Keep public DownInfo(long id, String savePath, long countLength, long readLength, int connectonTime, int stateInte, String url) { this.id = id; this.savePath = savePath; this.countLength = countLength; this.readLength = readLength; this.connectonTime = connectonTime; this.stateInte = stateInte; this.url = url; } public DownInfo() { readLength=0l; countLength=0l; stateInte=DownState.START.getState(); } @Generated(hash = 1860227052) public DownInfo(long id, String savePath, long countLength, long readLength, int connectonTime, int stateInte, String url, boolean updateProgress) { this.id = id; this.savePath = savePath; this.countLength = countLength; this.readLength = readLength; this.connectonTime = connectonTime; this.stateInte = stateInte; this.url = url; this.updateProgress = updateProgress; } public boolean isUpdateProgress() { return updateProgress; } public void setUpdateProgress(boolean updateProgress) { this.updateProgress = updateProgress; } public DownState getState() { switch (getStateInte()){ case 0: return DownState.START; case 1: return DownState.DOWN; case 2: return DownState.PAUSE; case 3: return DownState.STOP; case 4: return DownState.ERROR; case 5: default: return DownState.FINISH; } } public void setState(DownState state) { setStateInte(state.getState()); } public int getStateInte() { return stateInte; } public void setStateInte(int stateInte) { this.stateInte = stateInte; } public HttpDownOnNextListener getListener() { return listener; } public void setListener(HttpDownOnNextListener listener) { this.listener = listener; } public HttpDownService getService() { return service; } public void setService(HttpDownService service) { this.service = service; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } public long getCountLength() { return countLength; } public void setCountLength(long countLength) { this.countLength = countLength; } public long getReadLength() { return readLength; } public void setReadLength(long readLength) { this.readLength = readLength; } public long getId() { return this.id; } public void setId(long id) { this.id = id; } public int getConnectonTime() { return this.connectonTime; } public void setConnectonTime(int connectonTime) { this.connectonTime = connectonTime; } public boolean getUpdateProgress() { return this.updateProgress; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/DownLoadListener/DownloadInterceptor.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownLoadListener; import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Response; /** * 成功回调处理 * Created by WZG on 2016/10/20. */ public class DownloadInterceptor implements Interceptor { private DownloadProgressListener listener; public DownloadInterceptor(DownloadProgressListener listener) { this.listener = listener; } @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder() .body(new DownloadResponseBody(originalResponse.body(), listener)) .build(); } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/DownLoadListener/DownloadProgressListener.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownLoadListener; /** * 成功回调处理 * Created by WZG on 2016/10/20. */ public interface DownloadProgressListener { /** * 下载进度 * @param read * @param count * @param done */ void update(long read, long count, boolean done); } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/DownLoadListener/DownloadResponseBody.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownLoadListener; import java.io.IOException; import okhttp3.MediaType; import okhttp3.ResponseBody; import okio.Buffer; import okio.BufferedSource; import okio.ForwardingSource; import okio.Okio; import okio.Source; /** * 自定义精度的body * @author wzg */ public class DownloadResponseBody extends ResponseBody { private ResponseBody responseBody; private DownloadProgressListener progressListener; private BufferedSource bufferedSource; public DownloadResponseBody(ResponseBody responseBody, DownloadProgressListener progressListener) { this.responseBody = responseBody; this.progressListener = progressListener; } @Override public MediaType contentType() { return responseBody.contentType(); } @Override public long contentLength() { return responseBody.contentLength(); } @Override public BufferedSource source() { if (bufferedSource == null) { bufferedSource = Okio.buffer(source(responseBody.source())); } return bufferedSource; } private Source source(Source source) { return new ForwardingSource(source) { long totalBytesRead = 0L; @Override public long read(Buffer sink, long byteCount) throws IOException { long bytesRead = super.read(sink, byteCount); // read() returns the number of bytes read, or -1 if this source is exhausted. totalBytesRead += bytesRead != -1 ? bytesRead : 0; if (null != progressListener) { progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); } return bytesRead; } }; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/DownState.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod; /** * 下载状态 * Created by WZG on 2016/10/21. */ public enum DownState { START(0), DOWN(1), PAUSE(2), STOP(3), ERROR(4), FINISH(5); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; } DownState(int state) { this.state = state; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/HttpDownManager.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod; import android.os.Handler; import android.os.Looper; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownLoadListener.DownloadInterceptor; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.HttpTimeException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.RetryWhenNetworkException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.subscribers.ProgressDownSubscriber; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.DbDwonUtil; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.ResponseBody; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Func1; import rx.schedulers.Schedulers; import static com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.AppUtil.getBasUrl; /** * http下载处理类 * Created by WZG on 2016/7/16. */ public class HttpDownManager { /*记录下载数据*/ private Set downInfos; /*回调sub队列*/ private HashMap subMap; /*单利对象*/ private volatile static HttpDownManager INSTANCE; /*数据库类*/ private DbDwonUtil db; /*控制下载进度回掉到主线程*/ private Handler handler; private HttpDownManager() { downInfos = new HashSet<>(); subMap = new HashMap<>(); db = DbDwonUtil.getInstance(); handler = new Handler(Looper.getMainLooper()); } /** * 获取单例 * * @return */ public static HttpDownManager getInstance() { if (INSTANCE == null) { synchronized (HttpDownManager.class) { if (INSTANCE == null) { INSTANCE = new HttpDownManager(); } } } return INSTANCE; } /** * 开始下载 */ public void startDown(final DownInfo info) { /*正在下载不处理*/ if (info == null || subMap.get(info.getUrl()) != null) { subMap.get(info.getUrl()).setDownInfo(info); return; } /*添加回调处理类*/ ProgressDownSubscriber subscriber = new ProgressDownSubscriber(info, handler); /*记录回调sub*/ subMap.put(info.getUrl(), subscriber); /*获取service,多次请求公用一个sercie*/ HttpDownService httpService; if (downInfos.contains(info)) { httpService = info.getService(); } else { DownloadInterceptor interceptor = new DownloadInterceptor(subscriber); OkHttpClient.Builder builder = new OkHttpClient.Builder(); //手动创建一个OkHttpClient并设置超时时间 builder.connectTimeout(info.getConnectonTime(), TimeUnit.SECONDS); builder.addInterceptor(interceptor); Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .addConverterFactory(ScalarsConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(getBasUrl(info.getUrl())) .build(); httpService = retrofit.create(HttpDownService.class); info.setService(httpService); downInfos.add(info); } /*得到rx对象-上一次下載的位置開始下載*/ httpService.download("bytes=" + info.getReadLength() + "-", info.getUrl()) /*指定线程*/ .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) /*失败后的retry配置*/ .retryWhen(new RetryWhenNetworkException()) /*读取下载写入文件*/ .map(new Func1() { @Override public DownInfo call(ResponseBody responseBody) { writeCaches(responseBody, new File(info.getSavePath()), info); return info; } }) /*回调线程*/ .observeOn(AndroidSchedulers.mainThread()) /*数据回调*/ .subscribe(subscriber); } /** * 停止下载 */ public void stopDown(DownInfo info) { if (info == null) return; info.setState(DownState.STOP); info.getListener().onStop(); if (subMap.containsKey(info.getUrl())) { ProgressDownSubscriber subscriber = subMap.get(info.getUrl()); subscriber.unsubscribe(); subMap.remove(info.getUrl()); } /*保存数据库信息和本地文件*/ db.save(info); } /** * 暂停下载 * * @param info */ public void pause(DownInfo info) { if (info == null) return; info.setState(DownState.PAUSE); info.getListener().onPuase(); if (subMap.containsKey(info.getUrl())) { ProgressDownSubscriber subscriber = subMap.get(info.getUrl()); subscriber.unsubscribe(); subMap.remove(info.getUrl()); } /*这里需要讲info信息写入到数据中,可自由扩展,用自己项目的数据库*/ db.update(info); } /** * 停止全部下载 */ public void stopAllDown() { for (DownInfo downInfo : downInfos) { stopDown(downInfo); } subMap.clear(); downInfos.clear(); } /** * 暂停全部下载 */ public void pauseAll() { for (DownInfo downInfo : downInfos) { pause(downInfo); } subMap.clear(); downInfos.clear(); } /** * 返回全部正在下载的数据 * * @return */ public Set getDownInfos() { return downInfos; } /** * 移除下载数据 * * @param info */ public void remove(DownInfo info) { subMap.remove(info.getUrl()); downInfos.remove(info); } /** * 写入文件 * * @param file * @param info * @throws IOException */ public void writeCaches(ResponseBody responseBody, File file, DownInfo info) { try { RandomAccessFile randomAccessFile = null; FileChannel channelOut = null; InputStream inputStream = null; try { if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); long allLength = 0 == info.getCountLength() ? responseBody.contentLength() : info.getReadLength() + responseBody .contentLength(); inputStream = responseBody.byteStream(); randomAccessFile = new RandomAccessFile(file, "rwd"); channelOut = randomAccessFile.getChannel(); MappedByteBuffer mappedBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, info.getReadLength(), allLength - info.getReadLength()); byte[] buffer = new byte[1024 * 4]; int len; while ((len = inputStream.read(buffer)) != -1) { mappedBuffer.put(buffer, 0, len); } } catch (IOException e) { throw new HttpTimeException(HttpTimeException.HTTP_DOWN_WRITE, e.getMessage()); } finally { if (inputStream != null) { inputStream.close(); } if (channelOut != null) { channelOut.close(); } if (randomAccessFile != null) { randomAccessFile.close(); } } } catch (IOException e) { throw new HttpTimeException(HttpTimeException.HTTP_DOWN_WRITE,e.getMessage()); } } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/downlaod/HttpDownService.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod; import okhttp3.ResponseBody; import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.Streaming; import retrofit2.http.Url; import rx.Observable; /** * service-下载接口 * Created by WZG on 2016/7/16. */ public interface HttpDownService { /*断点续传下载接口*/ @Streaming/*大文件需要加入这个判断,防止下载过程中写入到内存中*/ @GET Observable download(@Header("RANGE") String start, @Url String url); } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/exception/ApiException.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception; /** * 回调统一请求异常 * Created by WZG on 2016/12/12. */ public class ApiException extends Exception{ /*错误码*/ private int code; /*显示的信息*/ private String displayMessage; public ApiException(Throwable e) { super(e); } public ApiException(Throwable cause, int code, String showMsg) { super(showMsg, cause); setCode(code); setDisplayMessage(showMsg); } public int getCode() { return code; } public void setCode( int code) { this.code = code; } public String getDisplayMessage() { return displayMessage; } public void setDisplayMessage(String displayMessage) { this.displayMessage = displayMessage; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/exception/CodeException.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception; import android.support.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * 自定义错误code类型:注解写法 *

* 可自由扩展 * Created by WZG on 2016/12/12. */ public class CodeException { /*网络错误*/ public static final int NETWORD_ERROR = 0x1; /*http_错误*/ public static final int HTTP_ERROR = 0x2; /*fastjson错误*/ public static final int JSON_ERROR = 0x3; /*未知错误*/ public static final int UNKNOWN_ERROR = 0x4; /*运行时异常-包含自定义异常*/ public static final int RUNTIME_ERROR = 0x5; /*无法解析该域名*/ public static final int UNKOWNHOST_ERROR = 0x6; @IntDef({NETWORD_ERROR, HTTP_ERROR, RUNTIME_ERROR, UNKNOWN_ERROR, JSON_ERROR, UNKOWNHOST_ERROR}) @Retention(RetentionPolicy.SOURCE) public @interface CodeEp { } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/exception/FactoryException.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception; import org.json.JSONException; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.text.ParseException; import retrofit2.adapter.rxjava.HttpException; /** * 异常处理工厂 * 主要是解析异常,输出自定义ApiException * Created by WZG on 2016/12/12. */ public class FactoryException { private static final String HttpException_MSG = "网络错误"; private static final String ConnectException_MSG = "连接失败"; private static final String JSONException_MSG = "fastjeson解析失败"; private static final String UnknownHostException_MSG = "无法解析该域名"; /** * 解析异常 * * @param e * @return */ public static ApiException analysisExcetpion(Throwable e) { ApiException apiException = new ApiException(e); if (e instanceof HttpException) { /*网络异常*/ apiException.setCode(CodeException.HTTP_ERROR); apiException.setDisplayMessage(HttpException_MSG); } else if (e instanceof HttpTimeException) { /*自定义运行时异常*/ HttpTimeException exception = (HttpTimeException) e; apiException.setCode(CodeException.RUNTIME_ERROR); apiException.setDisplayMessage(exception.getMessage()); } else if (e instanceof ConnectException||e instanceof SocketTimeoutException) { /*链接异常*/ apiException.setCode(CodeException.HTTP_ERROR); apiException.setDisplayMessage(ConnectException_MSG); } else if ( e instanceof JSONException || e instanceof ParseException) { apiException.setCode(CodeException.JSON_ERROR); apiException.setDisplayMessage(JSONException_MSG); }else if (e instanceof UnknownHostException){ /*无法解析该域名异常*/ apiException.setCode(CodeException.UNKOWNHOST_ERROR); apiException.setDisplayMessage(UnknownHostException_MSG); } else { /*未知异常*/ apiException.setCode(CodeException.UNKNOWN_ERROR); apiException.setDisplayMessage(e.getMessage()); } return apiException; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/exception/HttpTimeException.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception; /** * 运行时自定义错误信息 * 自由添加错误,需要自己扩展 * Created by WZG on 2016/7/16. */ public class HttpTimeException extends RuntimeException { /*未知错误*/ public static final int UNKNOWN_ERROR = 0x1002; /*本地无缓存错误*/ public static final int NO_CHACHE_ERROR = 0x1003; /*缓存过时错误*/ public static final int CHACHE_TIMEOUT_ERROR = 0x1004; /*断点下载错误*/ public static final int CHACHE_DOWN_ERROR = 0x1005; /*服务器down了,无返回数据*/ public static final int CHACHE_HTTP_ERROR = 0x1006; /*tokean过期,需要重新登录*/ public static final int CHACHE_TOKEAN_ERROR = 0x1007; /*http请求返回失败*/ public static final int CHACHE_HTTP_POST_ERROR = 0x1008; /*用户在其他设备登录*/ public static final int CHACHE_MORE_LOGIN_ERROR = 0x1009; /*交互取消*/ public static final int HTTP_CANCEL = 0x1010; /*交互取消*/ public static final int HTTP_DATA_NULL = 0x1011; /*获取tokean失败*/ public static final int HTTP_TOKEAN_ERROR = 0x10112; /*CONFIG失败*/ public static final int HTTP_CONFIG_ERROR = 0x10118; /*下周文件写入io错误*/ public static final int HTTP_DOWN_WRITE = 0x10119; /** * 服务器定义的错误code */ private int code; public HttpTimeException(int code, String detailMessage) { super(detailMessage); setCode(code); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/exception/RetryWhenNetworkException.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import rx.Observable; import rx.functions.Func1; import rx.functions.Func2; /** * retry条件 * Created by WZG on 2016/10/17. */ public class RetryWhenNetworkException implements Func1, Observable> { /* retry次数*/ private int count = 1; /*延迟*/ private long delay = 100; /*叠加延迟*/ private long increaseDelay = 100; public RetryWhenNetworkException() { } public RetryWhenNetworkException(int count, long delay) { this.count = count; this.delay = delay; } public RetryWhenNetworkException(int count, long delay, long increaseDelay) { this.count = count; this.delay = delay; this.increaseDelay = increaseDelay; } @Override public Observable call(Observable observable) { return observable .zipWith(Observable.range(1, count + 1), new Func2() { @Override public Wrapper call(Throwable throwable, Integer integer) { return new Wrapper(throwable, integer); } }).flatMap(new Func1>() { @Override public Observable call(Wrapper wrapper) { if ((wrapper.throwable instanceof ConnectException || wrapper.throwable instanceof SocketTimeoutException || wrapper.throwable instanceof TimeoutException) && wrapper.index < count + 1) { //如果超出重试次数也抛出错误,否则默认是会进入onCompleted return Observable.timer(delay + (wrapper.index - 1) * increaseDelay, TimeUnit.MILLISECONDS); } return Observable.error(wrapper.throwable); } }); } private class Wrapper { private int index; private Throwable throwable; public Wrapper(Throwable throwable, int index) { this.index = index; this.throwable = throwable; } } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/http/HttpManager.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.http; import android.util.Log; import com.trello.rxlifecycle.android.ActivityEvent; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api.BaseApi; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.RetryWhenNetworkException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.func.ExceptionFunc; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.func.ResulteFunc; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextSubListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.subscribers.ProgressSubscriber; import java.lang.ref.SoftReference; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; /** * http交互处理类 * Created by WZG on 2016/7/16.basePar */ public class HttpManager { /*软引用對象*/ private SoftReference onNextListener; private SoftReference onNextSubListener; private SoftReference appCompatActivity; public HttpManager(HttpOnNextListener onNextListener, RxAppCompatActivity appCompatActivity) { this.onNextListener = new SoftReference(onNextListener); this.appCompatActivity = new SoftReference(appCompatActivity); } public HttpManager(HttpOnNextSubListener onNextSubListener, RxAppCompatActivity appCompatActivity) { this.onNextSubListener = new SoftReference(onNextSubListener); this.appCompatActivity = new SoftReference(appCompatActivity); } public HttpManager(RxAppCompatActivity appCompatActivity) { this.appCompatActivity = new SoftReference(appCompatActivity); } public HttpManager() { } /** * 处理http请求 * * @param basePar 封装的请求数据 */ public Observable doHttpDeal(final BaseApi basePar) { return httpDeal(getReTrofit(basePar), basePar); } /** * 获取Retrofit对象 * * @param basePar * @return */ public Retrofit getReTrofit(final BaseApi basePar) { //手动创建一个OkHttpClient并设置超时时间缓存等设置 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(basePar.getConnectionTime(), TimeUnit.SECONDS); if (RxRetrofitApp.isDebug()) { builder.addInterceptor(getHttpLoggingInterceptor()); } /*创建retrofit对象*/ final Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .addConverterFactory(ScalarsConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(basePar.getBaseUrl()) .build(); return retrofit; } /** * RxRetrofit处理 * * @param basePar */ public Observable httpDeal(Retrofit retrofit, BaseApi basePar) { /*失败后的retry配置*/ Observable observable = basePar.getObservable(retrofit) /*失败后retry处理控制*/ .retryWhen(new RetryWhenNetworkException(basePar.getRetryCount(), basePar.getRetryDelay(), basePar.getRetryIncreaseDelay())) /*异常处理*/ .onErrorResumeNext(new ExceptionFunc()) /*tokean过期统一处理*/ // .flatMap(new TokeanFunc(basePar, retrofit)) /*返回数据统一判断*/ .map(new ResulteFunc()) /*http请求线程*/ .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) /*回调线程*/ .observeOn(AndroidSchedulers.mainThread()); /*生命周期管理*/ if (appCompatActivity != null) { observable.compose(appCompatActivity.get().bindUntilEvent(ActivityEvent.DESTROY)); } /*是否不需要处理sub对象*/ if (basePar.isNoSub()) { return observable; } /*ober回调,链接式返回*/ if (onNextSubListener != null && null != onNextSubListener.get()) { onNextSubListener.get().onNext(observable, basePar.getMethod()); } /*数据String回调*/ if (onNextListener != null && null != onNextListener.get()) { ProgressSubscriber subscriber = new ProgressSubscriber(basePar, onNextListener, appCompatActivity); observable.subscribe(subscriber); } return observable; } /** * 日志输出 * 自行判定是否添加 * * @return */ private HttpLoggingInterceptor getHttpLoggingInterceptor() { //日志显示级别 HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY; //新建log拦截器 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { Log.d("RxRetrofit", "Retrofit====Message:" + message); } }); loggingInterceptor.setLevel(level); return loggingInterceptor; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/http/cookie/CacheInterceptor.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.AppUtil; import java.io.IOException; import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; /** * get缓存方式拦截器 * Created by WZG on 2016/10/26. */ public class CacheInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) {//没网强制从缓存读取(必须得写,不然断网状态下,退出应用,或者等待一分钟后,就获取不到缓存) request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response response = chain.proceed(request); Response responseLatest; if (AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) { int maxAge = 60; //有网失效一分钟 responseLatest = response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 6; // 没网失效6小时 responseLatest= response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return responseLatest; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/http/cookie/CookieResulte.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Generated; /** * post請求緩存数据 * Created by WZG on 2016/10/26. */ @Entity public class CookieResulte { @Id private Long id; /*url*/ private String url; /*返回结果*/ private String resulte; /*时间*/ private long time; public CookieResulte(String url, String resulte, long time) { this.url = url; this.resulte = resulte; this.time = time; } @Generated(hash = 565593340) public CookieResulte(Long id, String url, String resulte, long time) { this.id = id; this.url = url; this.resulte = resulte; this.time = time; } @Generated(hash = 2104390000) public CookieResulte() { } public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } public String getResulte() { return this.resulte; } public void setResulte(String resulte) { this.resulte = resulte; } public long getTime() { return this.time; } public void setTime(long time) { this.time = time; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/http/func/ExceptionFunc.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.func; import android.util.Log; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.FactoryException; import rx.Observable; import rx.functions.Func1; /** * 异常处理 * Created by WZG on 2017/3/23. */ public class ExceptionFunc implements Func1 { @Override public Observable call(Throwable throwable) { Log.e("Tag","-------->"+throwable.getMessage()); return Observable.error(FactoryException.analysisExcetpion(throwable)); } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/http/func/ResulteFunc.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.func; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.HttpTimeException; import rx.functions.Func1; /** * 服务器返回数据判断 * Created by WZG on 2017/3/23. */ public class ResulteFunc implements Func1 { @Override public Object call(Object o) { if (o == null || "".equals(o.toString())) { throw new HttpTimeException(HttpTimeException.CHACHE_HTTP_POST_ERROR, "数据错误"); } return o; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/listener/HttpDownOnNextListener.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener; /** * 下载过程中的回调处理 * Created by WZG on 2016/10/20. */ public abstract class HttpDownOnNextListener { /** * 成功后回调方法 * @param t */ public abstract void onNext(T t); /** * 开始下载 */ public abstract void onStart(); /** * 完成下载 */ public abstract void onComplete(); /** * 下载进度 * @param readLength * @param countLength */ public abstract void updateProgress(long readLength, long countLength); /** * 失败或者错误方法 * 主动调用,更加灵活 * @param e */ public void onError(Throwable e){ } /** * 暂停下载 */ public void onPuase(){ } /** * 停止下载销毁 */ public void onStop(){ } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/listener/HttpOnNextListener.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.ApiException; /** * 成功回调处理 * Created by WZG on 2016/7/16. */ public interface HttpOnNextListener { /** * 成功后回调方法 * * @param resulte * @param method */ void onNext(String resulte, String method); /** * 失败 * 失败或者错误方法 * 自定义异常处理 * * @param e * @param method */ void onError(ApiException e, String method); } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/listener/HttpOnNextSubListener.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener; import rx.Observable; /** * 回调ober对象 * Created by WZG on 2016/12/12. */ public interface HttpOnNextSubListener { /** * ober成功回调 * @param observable * @param method */ void onNext(Observable observable,String method); } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/listener/upload/ProgressRequestBody.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.upload; import java.io.IOException; import okhttp3.MediaType; import okhttp3.RequestBody; import okio.Buffer; import okio.BufferedSink; import okio.ForwardingSink; import okio.Okio; import okio.Sink; /** * 自定义回调加载速度类RequestBody * Created by WZG on 2016/10/20. */ public class ProgressRequestBody extends RequestBody { //实际起作用的RequestBody private RequestBody delegate; //进度回调接口 private final UploadProgressListener progressListener; private CountingSink countingSink; public ProgressRequestBody(RequestBody requestBody, UploadProgressListener progressListener) { this.delegate = requestBody; this.progressListener = progressListener; } @Override public MediaType contentType() { return delegate.contentType(); } @Override public void writeTo(BufferedSink sink) throws IOException { countingSink = new CountingSink(sink); //将CountingSink转化为BufferedSink供writeTo()使用 BufferedSink bufferedSink = Okio.buffer(countingSink); delegate.writeTo(bufferedSink); bufferedSink.flush(); } protected final class CountingSink extends ForwardingSink{ private long byteWritten; public CountingSink(Sink delegate) { super(delegate); } /** * 上传时调用该方法,在其中调用回调函数将上传进度暴露出去,该方法提供了缓冲区的自己大小 * @param source * @param byteCount * @throws IOException */ @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); byteWritten += byteCount; progressListener.onProgress(byteWritten, contentLength()); } } /** * 返回文件总的字节大小 * 如果文件大小获取失败则返回-1 * @return */ @Override public long contentLength(){ try { return delegate.contentLength(); } catch (IOException e) { return -1; } } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/listener/upload/UploadProgressListener.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.upload; /** * 上传进度回调类 * Created by WZG on 2016/10/20. */ public interface UploadProgressListener { /** * 上传进度 * 手动回调到主线程中 * @param currentBytesCount * @param totalBytesCount */ void onProgress(long currentBytesCount, long totalBytesCount); } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/subscribers/ProgressDownSubscriber.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.subscribers; import android.os.Handler; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfo; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownLoadListener.DownloadProgressListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownState; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.HttpDownManager; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpDownOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.DbDwonUtil; import java.lang.ref.SoftReference; import rx.Subscriber; /** * 断点下载处理类Subscriber * 用于在Http请求开始时,自动显示一个ProgressDialog * 在Http请求结束是,关闭ProgressDialog * 调用者自己对请求数据进行处理 * Created by WZG on 2016/7/16. */ public class ProgressDownSubscriber extends Subscriber implements DownloadProgressListener { //弱引用结果回调 private SoftReference mSubscriberOnNextListener; /*下载数据*/ private DownInfo downInfo; private Handler handler; public ProgressDownSubscriber(DownInfo downInfo, Handler handler) { this.mSubscriberOnNextListener = new SoftReference<>(downInfo.getListener()); this.downInfo = downInfo; this.handler = handler; } public void setDownInfo(DownInfo downInfo) { this.mSubscriberOnNextListener = new SoftReference<>(downInfo.getListener()); this.downInfo = downInfo; } /** * 订阅开始时调用 * 显示ProgressDialog */ @Override public void onStart() { if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onStart(); } downInfo.setState(DownState.START); } /** * 完成,隐藏ProgressDialog */ @Override public void onCompleted() { if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onComplete(); } HttpDownManager.getInstance().remove(downInfo); downInfo.setState(DownState.FINISH); DbDwonUtil.getInstance().update(downInfo); } /** * 对错误进行统一处理 * 隐藏ProgressDialog * * @param e */ @Override public void onError(Throwable e) { if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onError(e); } HttpDownManager.getInstance().remove(downInfo); downInfo.setState(DownState.ERROR); DbDwonUtil.getInstance().update(downInfo); } /** * 将onNext方法中的返回结果交给Activity或Fragment自己处理 * * @param t 创建Subscriber时的泛型类型 */ @Override public void onNext(T t) { if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onNext(t); } } @Override public void update(long read, long count, boolean done) { if (downInfo.getCountLength() > count) { read = downInfo.getCountLength() - count + read; } else { downInfo.setCountLength(count); } downInfo.setReadLength(read); if (mSubscriberOnNextListener.get() == null || !downInfo.isUpdateProgress()) return; handler.post(new Runnable() { @Override public void run() { /*如果暂停或者停止状态延迟,不需要继续发送回调,影响显示*/ if (downInfo.getState() == DownState.PAUSE || downInfo.getState() == DownState.STOP) return; downInfo.setState(DownState.DOWN); mSubscriberOnNextListener.get().updateProgress(downInfo.getReadLength(), downInfo.getCountLength()); } }); } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/subscribers/ProgressSubscriber.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.subscribers; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.Api.BaseApi; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.ApiException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.exception.HttpTimeException; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.CookieResulte; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.listener.HttpOnNextListener; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.AppUtil; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils.CookieDbUtil; import java.lang.ref.SoftReference; import rx.Subscriber; /** * 用于在Http请求开始时,自动显示一个ProgressDialog * 在Http请求结束是,关闭ProgressDialog * 调用者自己对请求数据进行处理 * Created by WZG on 2016/7/16. */ public class ProgressSubscriber extends Subscriber { // 回调接口 private SoftReference mSubscriberOnNextListener; // 软引用反正内存泄露 private SoftReference mActivity; // 加载框可自己定义 private ProgressDialog pd; /*请求数据*/ private BaseApi api; /** * 构造 * * @param api */ public ProgressSubscriber(BaseApi api, SoftReference listenerSoftReference, SoftReference mActivity) { this.api = api; this.mSubscriberOnNextListener = listenerSoftReference; this.mActivity = mActivity; } /** * 订阅开始时调用 * 显示ProgressDialog */ @Override public void onStart() { /*缓存并且有网*/ if (api.isCache() && AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) { /*获取缓存数据*/ CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(api.getCacheUrl()); if (cookieResulte != null && mSubscriberOnNextListener.get() != null && (System.currentTimeMillis() - cookieResulte .getTime()) / 1000 < api.getCookieNetWorkTime()) { mSubscriberOnNextListener.get().onNext(cookieResulte.getResulte(), api.getMethod()); onCompleted(); unsubscribe(); return; } } if (api.isShowProgress()) { initProgressDialog(api.isCancel()); } } /** * 初始化加载框 */ private void initProgressDialog(boolean cancel) { if (!api.isShowProgress()) return; Context context = mActivity.get(); if (pd == null && context != null) { pd = new ProgressDialog(context); pd.setCancelable(cancel); if (cancel) { pd.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { onCancelProgress(); } }); } } pd.show(); } /** * 隐藏 */ private void dismissProgressDialog() { if (pd != null) { pd.dismiss(); } } /** * 完成,隐藏ProgressDialog */ @Override public void onCompleted() { dismissProgressDialog(); } /** * 对错误进行统一处理 * 隐藏ProgressDialog * * @param e */ @Override public void onError(Throwable e) { /*需要緩存并且本地有缓存才返回*/ if (api.isCache()) { getCache(e); } else { errorDo(e); } dismissProgressDialog(); } /** * 获取cache数据 */ private void getCache(Throwable te) { try { /*获取缓存数据*/ CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(api.getCacheUrl()); if (cookieResulte == null) { errorDo(te); return; } if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onNext(cookieResulte.getResulte(), api.getMethod()); } } catch (Exception e) { errorDo(te == null ? e : te); } } /** * 错误统一处理 * * @param e */ private void errorDo(Throwable e) { Context context = mActivity.get(); if (context == null) return; HttpOnNextListener httpOnNextListener = mSubscriberOnNextListener.get(); if (httpOnNextListener == null) return; ApiException apiException; if (e instanceof ApiException) { apiException = (ApiException) e; httpOnNextListener.onError(apiException, api.getMethod()); } else if (e instanceof HttpTimeException) { HttpTimeException exception = (HttpTimeException) e; apiException = new ApiException(exception, exception.getCode(), exception.getMessage()); httpOnNextListener.onError(apiException, api.getMethod()); } else { apiException = new ApiException(e, HttpTimeException.UNKNOWN_ERROR, e.getMessage()); httpOnNextListener.onError(apiException, api.getMethod()); } } /** * 将onNext方法中的返回结果交给Activity或Fragment自己处理 * * @param t 创建Subscriber时的泛型类型 */ @Override public void onNext(T t) { if (mSubscriberOnNextListener.get() != null) { mSubscriberOnNextListener.get().onNext((String) t, api.getMethod()); } /*缓存处理*/ CookieResulte resulte = CookieDbUtil.getInstance().queryCookieBy(api.getCacheUrl()); long time = System.currentTimeMillis(); if (resulte == null && api.isCache()) { resulte = new CookieResulte(api.getCacheUrl(), t.toString(), time); CookieDbUtil.getInstance().saveCookie(resulte); } if (resulte != null) { resulte.setResulte(t.toString()); resulte.setTime(time); CookieDbUtil.getInstance().updateCookie(resulte); } } /** * 取消ProgressDialog的时候,取消对observable的订阅,同时也取消了http请求 */ public void onCancelProgress() { if (!this.isUnsubscribed()) { this.unsubscribe(); if (api.isCache()) { getCache(null); } else { errorDo(new ApiException(new Throwable(), HttpTimeException.HTTP_CANCEL, "请求取消!")); } } } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/utils/AppUtil.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; /** * 方法工具类 * Created by WZG on 2016/10/31. */ public class AppUtil { /** * 描述:判断网络是否有效. * * @return true, if is network available */ public static boolean isNetworkAvailable(Context context) { try { ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo info = connectivity.getActiveNetworkInfo(); if (info != null && info.isConnected()) { if (info.getState() == NetworkInfo.State.CONNECTED) { return true; } } } } catch (Exception e) { e.printStackTrace(); return false; } return false; } /** * 读取baseurl * * @param url * @return */ public static String getBasUrl(String url) { String head = ""; int index = url.indexOf("://"); if (index != -1) { head = url.substring(0, index + 3); url = url.substring(index + 3); } index = url.indexOf("/"); if (index != -1) { url = url.substring(0, index + 1); } return head + url; } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/utils/CookieDbUtil.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.CookieResulte; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.CookieResulteDao; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.DaoMaster; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.DaoSession; import org.greenrobot.greendao.query.QueryBuilder; import java.util.List; /** * 数据缓存 * 数据库工具类-geendao运用 * Created by WZG on 2016/10/25. */ public class CookieDbUtil { private static CookieDbUtil db; private final static String dbName = "tests_db"; private DaoMaster.DevOpenHelper openHelper; private Context context; public CookieDbUtil() { context= RxRetrofitApp.getApplication(); openHelper = new DaoMaster.DevOpenHelper(context, dbName); } /** * 获取单例 * @return */ public static CookieDbUtil getInstance() { if (db == null) { synchronized (CookieDbUtil.class) { if (db == null) { db = new CookieDbUtil(); } } } return db; } /** * 获取可读数据库 */ private SQLiteDatabase getReadableDatabase() { if (openHelper == null) { openHelper = new DaoMaster.DevOpenHelper(context, dbName); } SQLiteDatabase db = openHelper.getReadableDatabase(); return db; } /** * 获取可写数据库 */ private SQLiteDatabase getWritableDatabase() { if (openHelper == null) { openHelper = new DaoMaster.DevOpenHelper(context, dbName); } SQLiteDatabase db = openHelper.getWritableDatabase(); return db; } public void saveCookie(CookieResulte info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); CookieResulteDao downInfoDao = daoSession.getCookieResulteDao(); downInfoDao.insert(info); } public void updateCookie(CookieResulte info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); CookieResulteDao downInfoDao = daoSession.getCookieResulteDao(); downInfoDao.update(info); } public void deleteCookie(CookieResulte info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); CookieResulteDao downInfoDao = daoSession.getCookieResulteDao(); downInfoDao.delete(info); } public CookieResulte queryCookieBy(String url) { DaoMaster daoMaster = new DaoMaster(getReadableDatabase()); DaoSession daoSession = daoMaster.newSession(); CookieResulteDao downInfoDao = daoSession.getCookieResulteDao(); QueryBuilder qb = downInfoDao.queryBuilder(); qb.where(CookieResulteDao.Properties.Url.eq(url)); List list = qb.list(); if(list.isEmpty()){ return null; }else{ return list.get(0); } } public List queryCookieAll() { DaoMaster daoMaster = new DaoMaster(getReadableDatabase()); DaoSession daoSession = daoMaster.newSession(); CookieResulteDao downInfoDao = daoSession.getCookieResulteDao(); QueryBuilder qb = downInfoDao.queryBuilder(); return qb.list(); } } ================================================ FILE: rxretrofitlibrary/src/main/java/com/wzgiceman/rxretrofitlibrary/retrofit_rx/utils/DbDwonUtil.java ================================================ package com.wzgiceman.rxretrofitlibrary.retrofit_rx.utils; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.RxRetrofitApp; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfo; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.downlaod.DownInfoDao; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.DaoMaster; import com.wzgiceman.rxretrofitlibrary.retrofit_rx.http.cookie.DaoSession; import org.greenrobot.greendao.query.QueryBuilder; import java.util.List; /** * 断点续传 * 数据库工具类-geendao运用 * Created by WZG on 2016/10/25. */ public class DbDwonUtil { private static DbDwonUtil db; private final static String dbName = "tests_db"; private DaoMaster.DevOpenHelper openHelper; private Context context; public DbDwonUtil() { context= RxRetrofitApp.getApplication(); openHelper = new DaoMaster.DevOpenHelper(context, dbName, null); } /** * 获取单例 * @return */ public static DbDwonUtil getInstance() { if (db == null) { synchronized (DbDwonUtil.class) { if (db == null) { db = new DbDwonUtil(); } } } return db; } /** * 获取可读数据库 */ private SQLiteDatabase getReadableDatabase() { if (openHelper == null) { openHelper = new DaoMaster.DevOpenHelper(context, dbName, null); } SQLiteDatabase db = openHelper.getReadableDatabase(); return db; } /** * 获取可写数据库 */ private SQLiteDatabase getWritableDatabase() { if (openHelper == null) { openHelper = new DaoMaster.DevOpenHelper(context, dbName, null); } SQLiteDatabase db = openHelper.getWritableDatabase(); return db; } public void save(DownInfo info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); DownInfoDao downInfoDao = daoSession.getDownInfoDao(); downInfoDao.insert(info); } public void update(DownInfo info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); DownInfoDao downInfoDao = daoSession.getDownInfoDao(); downInfoDao.update(info); } public void deleteDowninfo(DownInfo info){ DaoMaster daoMaster = new DaoMaster(getWritableDatabase()); DaoSession daoSession = daoMaster.newSession(); DownInfoDao downInfoDao = daoSession.getDownInfoDao(); downInfoDao.delete(info); } public DownInfo queryDownBy(long Id) { DaoMaster daoMaster = new DaoMaster(getReadableDatabase()); DaoSession daoSession = daoMaster.newSession(); DownInfoDao downInfoDao = daoSession.getDownInfoDao(); QueryBuilder qb = downInfoDao.queryBuilder(); qb.where(DownInfoDao.Properties.Id.eq(Id)); List list = qb.list(); if(list.isEmpty()){ return null; }else{ return list.get(0); } } public List queryDownAll() { DaoMaster daoMaster = new DaoMaster(getReadableDatabase()); DaoSession daoSession = daoMaster.newSession(); DownInfoDao downInfoDao = daoSession.getDownInfoDao(); QueryBuilder qb = downInfoDao.queryBuilder(); return qb.list(); } } ================================================ FILE: rxretrofitlibrary/src/main/res/values/strings.xml ================================================ RxRetrofitLibrary ================================================ FILE: settings.gradle ================================================ include ':app', ':rxretrofitlibrary'