├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lp │ │ └── mvp_network │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lp │ │ │ └── mvp_network │ │ │ ├── App.java │ │ │ ├── activity │ │ │ ├── MainActivity.java │ │ │ ├── MainBean.java │ │ │ ├── MainPresenter.java │ │ │ ├── MainView.java │ │ │ ├── MvcActivity.java │ │ │ └── file │ │ │ │ ├── FileActivity.java │ │ │ │ ├── FilePresenter.java │ │ │ │ └── FileView.java │ │ │ ├── api │ │ │ ├── ApiDns.java │ │ │ ├── ApiRetrofit.java │ │ │ └── ApiServer.java │ │ │ ├── base │ │ │ ├── ApiException.java │ │ │ ├── BaseActivity.java │ │ │ ├── BaseContent.java │ │ │ ├── BaseFragment.java │ │ │ ├── convert │ │ │ │ ├── MyGsonConverterFactory.java │ │ │ │ ├── MyGsonRequestBodyConverter.java │ │ │ │ └── MyGsonResponseBodyConverter.java │ │ │ ├── cookie │ │ │ │ ├── CookieManger.java │ │ │ │ ├── OkHttpCookies.java │ │ │ │ └── PersistentCookieStore.java │ │ │ ├── file │ │ │ │ ├── FileObserver.java │ │ │ │ ├── FileUtil.java │ │ │ │ ├── ProgressRequestBody.java │ │ │ │ └── ProgressResponseBody.java │ │ │ ├── gson │ │ │ │ ├── DoubleDefaultAdapter.java │ │ │ │ ├── IntegerDefaultAdapter.java │ │ │ │ ├── LongDefaultAdapter.java │ │ │ │ └── StringNullAdapter.java │ │ │ └── mvp │ │ │ │ ├── BaseModel.java │ │ │ │ ├── BaseObserver.java │ │ │ │ ├── BaseObserverFlowable.java │ │ │ │ ├── BasePresenter.java │ │ │ │ ├── BasePresenterFlowable.java │ │ │ │ └── BaseView.java │ │ │ ├── bean │ │ │ └── TextBean.java │ │ │ ├── second2demo │ │ │ ├── BaseActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── activity │ │ │ │ ├── SecondActivity.java │ │ │ │ ├── SecondPresenter.java │ │ │ │ └── SecondView.java │ │ │ ├── api │ │ │ │ └── ApiRetrofit.java │ │ │ ├── bean │ │ │ │ ├── Bean1.java │ │ │ │ ├── Bean2.java │ │ │ │ └── Bean3.java │ │ │ └── mvp │ │ │ │ ├── BaseModel.java │ │ │ │ ├── BaseObserver.java │ │ │ │ ├── BasePresenter.java │ │ │ │ └── BaseView.java │ │ │ ├── utils │ │ │ ├── KeyBoardUtils.java │ │ │ ├── L.java │ │ │ ├── NetWorkUtils.java │ │ │ ├── RetrofitUtil.java │ │ │ └── StatusBarUtil.java │ │ │ └── view │ │ │ ├── LoadingDialog.java │ │ │ └── ProgressDialog.java │ └── res │ │ ├── anim │ │ ├── dialog_enter.xml │ │ └── dialog_exit.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── loading_bg.9.png │ │ ├── logo.jpg │ │ └── progressbar_round.xml │ │ ├── layout │ │ ├── activity_file.xml │ │ ├── activity_main.xml │ │ ├── app_title.xml │ │ ├── dialog_loading.xml │ │ ├── dialog_msg.xml │ │ └── progress_uptade.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lp │ └── mvp_network │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LPTim/MVP-Retrofit2-okhttp3-Rxjava2/e5fd2ed4b6c797124882a0657b62bb26472564af/README.md -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.lp.mvp_network" 7 | minSdkVersion 16 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | repositories { 22 | maven { url 'https://jitpack.io' } 23 | jcenter() 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation 'com.android.support:appcompat-v7:27.1.1' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 33 | 34 | //网络请求 35 | implementation 'com.squareup.okhttp3:okhttp:3.11.0' 36 | implementation 'com.squareup.retrofit2:retrofit:2.4.0' 37 | //ConverterFactory的Gson依赖包 38 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0' 39 | //CallAdapterFactory的Rx依赖包 40 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' 41 | 42 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 43 | //cookie管理 44 | implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1' 45 | //日志 46 | implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' 47 | 48 | //日志 49 | implementation 'com.orhanobut:logger:2.2.0' 50 | //toast 51 | implementation 'com.hjq:toast:5.8' 52 | 53 | //水波纹 54 | implementation 'com.scwang.wave:MultiWaveHeader:1.0.0-alpha-1' 55 | //权限申请 56 | implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar' 57 | //下载动画 58 | implementation 'com.github.Ajian-studio:GADownloading:v1.0.2' 59 | //工具类 60 | implementation 'com.blankj:utilcode:1.23.7' 61 | } 62 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lp/mvp_network/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lp.mvp_network", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 33 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/App.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.hjq.toast.ToastUtils; 7 | import com.orhanobut.logger.AndroidLogAdapter; 8 | import com.orhanobut.logger.FormatStrategy; 9 | import com.orhanobut.logger.Logger; 10 | import com.orhanobut.logger.PrettyFormatStrategy; 11 | 12 | /** 13 | * File descripition: 运用此项目时,修改地方如下 14 | *

15 | * 1.BaseContent 中 baseUrl修改 16 | * 2.BaseContent 中 basecode修改 17 | * 3.BaseModel 中 各字段参数名 修改为接口对应 18 | * 备注:(接口如果复杂,自己修改不了,可以联系我) 19 | * 20 | * 21 | * @author lp 22 | * @date 2018/10/11 23 | */ 24 | 25 | public class App extends Application { 26 | private static Context mContext; 27 | 28 | @Override 29 | public void onCreate() { 30 | super.onCreate(); 31 | 32 | // 在 Application 中初始化 33 | ToastUtils.init(this); 34 | 35 | mContext = this; 36 | initLogger(); 37 | } 38 | 39 | public static Context getContext() { 40 | return mContext; 41 | } 42 | 43 | private void initLogger() { 44 | FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 45 | .showThreadInfo(false) // 是否显示线程信息 默认显示 上图Thread Infrom的位置 46 | .methodCount(0) // 展示方法的行数 默认是2 上图Method的行数 47 | .methodOffset(7) // 内部方法调用向上偏移的行数 默认是0 48 | // .logStrategy(customLog) // 改变log打印的策略一种是写本地,一种是logcat显示 默认是后者(当然也可以自己定义) 49 | .tag("mvp_network_tag") // 自定义全局tag 默认:PRETTY_LOGGER 50 | .build(); 51 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) { 52 | @Override 53 | public boolean isLoggable(int priority, String tag) { 54 | return true; 55 | } 56 | }); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.lp.mvp_network.R; 7 | import com.lp.mvp_network.activity.file.FileActivity; 8 | import com.lp.mvp_network.base.BaseActivity; 9 | import com.lp.mvp_network.base.BaseContent; 10 | import com.lp.mvp_network.base.mvp.BaseModel; 11 | import com.lp.mvp_network.bean.TextBean; 12 | import com.lp.mvp_network.utils.L; 13 | import com.lp.mvp_network.utils.RetrofitUtil; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public class MainActivity extends BaseActivity implements MainView, View.OnClickListener { 19 | private TextView mTvText; 20 | 21 | private List mainBeans; 22 | 23 | @Override 24 | protected MainPresenter createPresenter() { 25 | return new MainPresenter(this); 26 | } 27 | 28 | @Override 29 | protected int getLayoutId() { 30 | return R.layout.activity_main; 31 | } 32 | 33 | 34 | @Override 35 | public void onErrorCode(BaseModel model) { 36 | // super.onErrorCode(model); 37 | //我要自定义 38 | //实现自己的逻辑 39 | } 40 | 41 | 42 | @Override 43 | public void showError(String msg) { 44 | if (msg.contains("重新登录")) { 45 | //处理自己定制逻辑 46 | } else { 47 | super.showError(msg); 48 | } 49 | 50 | } 51 | 52 | 53 | @Override 54 | protected void initData() { 55 | findViewById(R.id.btn_first).setOnClickListener(this); 56 | findViewById(R.id.btn_second).setOnClickListener(this); 57 | findViewById(R.id.btn_second_2).setOnClickListener(this); 58 | findViewById(R.id.btn_third).setOnClickListener(this); 59 | findViewById(R.id.btn_forth).setOnClickListener(this); 60 | findViewById(R.id.btn_fifth).setOnClickListener(this); 61 | findViewById(R.id.btn_six).setOnClickListener(this); 62 | findViewById(R.id.btn_down).setOnClickListener(this); 63 | mTvText = findViewById(R.id.tv_text); 64 | 65 | mainBeans = new ArrayList<>(); 66 | 67 | 68 | } 69 | 70 | @Override 71 | public void onMainSuccess(BaseModel> o) { 72 | // Log.e(o.getErrmsg(), ""); 73 | // Log.e(o.getErrcode() + "", ""); 74 | // mainBeans.addAll(o.getData()); 75 | // Log.e("sm", mainBeans.toString() + ""); 76 | // mTvText.setText(o.getData().toString()); 77 | } 78 | 79 | @Override 80 | public void onTextSuccess(BaseModel o) { 81 | mTvText.setText(o.getResult().getData().toString()); 82 | } 83 | 84 | @Override 85 | public void onClick(View v) { 86 | switch (v.getId()) { 87 | //默认请求 88 | case R.id.btn_first: 89 | mPresenter.getTextApi(); 90 | break; 91 | //上传图片 92 | case R.id.btn_second: 93 | showToast("添加本地图片url,再进行测试"); 94 | // upLoadImage(); 95 | break; 96 | //上传文件进度测试 97 | case R.id.btn_second_2: 98 | mPresenter.upLoadVideoApi(BaseContent.baseFileName+"ceshi.mp4"); 99 | break; 100 | //mvc测试 101 | case R.id.btn_third: 102 | startActivity(MvcActivity.class); 103 | break; 104 | //多基类测试 105 | case R.id.btn_forth: 106 | mPresenter.getTableListApi(); 107 | break; 108 | //多基类测试 109 | case R.id.btn_fifth: 110 | mPresenter.getRestrictionsApi(); 111 | break; 112 | //多基类测试 113 | case R.id.btn_six: 114 | mPresenter.getCheShiApi(); 115 | break; 116 | //文件上传测试 117 | case R.id.btn_down: 118 | startActivity(FileActivity.class); 119 | break; 120 | } 121 | } 122 | 123 | private void upLoadImage() { 124 | /** 125 | * 俩个参数 一个是图片集合路径 一个是和后台约定的Key,如果后台不需要,随便写都行 126 | */ 127 | List strings = new ArrayList<>(); 128 | for (int i = 0; i < 10; i++) { 129 | strings.add("tupian.lujing"); 130 | } 131 | mPresenter.upLoadImgApi( 132 | "title", 133 | "content", 134 | RetrofitUtil.filesToMultipartBodyParts(RetrofitUtil.initImages(strings), "tupian.key")); 135 | 136 | } 137 | 138 | @Override 139 | public void onUpLoadImgSuccess(BaseModel o) { 140 | L.e("文件视频路径==" + o.getResult()); 141 | } 142 | 143 | /** 144 | * 测试多基类 145 | * 146 | * @param o 147 | */ 148 | @Override 149 | public void onTableListSuccess(BaseModel o) { 150 | L.e("测试多基类1=" + o.getResult()); 151 | } 152 | 153 | /** 154 | * 测试多基类 155 | * 156 | * @param o 157 | */ 158 | @Override 159 | public void onRestrictionsSuccess(BaseModel o) { 160 | L.e("测试多基类2=" + o.getResult()); 161 | } 162 | 163 | @Override 164 | public void onCheShiSuccess(BaseModel o) { 165 | L.e("测试多基类3=" + o.getResult()); 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/MainBean.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity; 2 | 3 | /** 4 | * File descripition: 5 | * 6 | * @author lp 7 | * @date 2018/9/19 8 | */ 9 | 10 | public class MainBean { 11 | /** 12 | * id : 11 13 | * act_logo : http://www.energy-link.com.cn/upload/admin/20180828/s_29a692567d0f0d84d515eb5cf5be98d0.jpg 14 | * play_time : 2018-06-10 15 | * name : 中国生物质能源产业联盟会员代表大会 16 | * province : 北京市 17 | * city : 西城区 18 | */ 19 | 20 | private int id; 21 | private String act_logo; 22 | private String play_time; 23 | private String name; 24 | private String province; 25 | private String city; 26 | 27 | public int getId() { 28 | return id; 29 | } 30 | 31 | public void setId(int id) { 32 | this.id = id; 33 | } 34 | 35 | public String getAct_logo() { 36 | return act_logo; 37 | } 38 | 39 | public void setAct_logo(String act_logo) { 40 | this.act_logo = act_logo; 41 | } 42 | 43 | public String getPlay_time() { 44 | return play_time; 45 | } 46 | 47 | public void setPlay_time(String play_time) { 48 | this.play_time = play_time; 49 | } 50 | 51 | public String getName() { 52 | return name; 53 | } 54 | 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | 59 | public String getProvince() { 60 | return province; 61 | } 62 | 63 | public void setProvince(String province) { 64 | this.province = province; 65 | } 66 | 67 | public String getCity() { 68 | return city; 69 | } 70 | 71 | public void setCity(String city) { 72 | this.city = city; 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "MainBean{" + 78 | "id=" + id + 79 | ", act_logo='" + act_logo + '\'' + 80 | ", play_time='" + play_time + '\'' + 81 | ", name='" + name + '\'' + 82 | ", province='" + province + '\'' + 83 | ", city='" + city + '\'' + 84 | '}'; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity; 2 | 3 | 4 | import com.lp.mvp_network.api.ApiRetrofit; 5 | import com.lp.mvp_network.api.ApiServer; 6 | import com.lp.mvp_network.base.file.FileObserver; 7 | import com.lp.mvp_network.base.file.ProgressRequestBody; 8 | import com.lp.mvp_network.base.mvp.BaseModel; 9 | import com.lp.mvp_network.base.mvp.BaseObserver; 10 | import com.lp.mvp_network.base.mvp.BasePresenter; 11 | import com.lp.mvp_network.bean.TextBean; 12 | import com.lp.mvp_network.utils.RetrofitUtil; 13 | 14 | import java.io.File; 15 | import java.util.HashMap; 16 | import java.util.List; 17 | 18 | import okhttp3.MultipartBody; 19 | import okhttp3.RequestBody; 20 | 21 | /** 22 | * File descripition: 23 | * 24 | * @author lp 25 | * @date 2018/6/19 26 | */ 27 | 28 | public class MainPresenter extends BasePresenter { 29 | public MainPresenter(MainView baseView) { 30 | super(baseView); 31 | } 32 | 33 | 34 | /** 35 | * 客户标签的筛选项 36 | */ 37 | public void getTableListApi() { 38 | HashMap params = new HashMap<>(); 39 | params.put("token", "032cc080947549c83c3296026b5963a2"); 40 | ApiServer apiServer = ApiRetrofit.getBaseUrlInstance("http://selfec.qhzx.online/").getApiService(); 41 | addDisposable(apiServer.getTableList(params), new BaseObserver(baseView) { 42 | @Override 43 | public void onSuccess(BaseModel o) { 44 | baseView.onTableListSuccess((BaseModel) o); 45 | } 46 | 47 | @Override 48 | public void onError(String msg) { 49 | if (baseView != null) { 50 | baseView.showError(msg); 51 | } 52 | } 53 | }); 54 | } 55 | 56 | /** 57 | * 当前城市限行 58 | */ 59 | public void getRestrictionsApi() { 60 | HashMap params = new HashMap<>(); 61 | params.put("city_code", "131"); 62 | params.put("day", "20190802"); 63 | ApiServer apiServer = ApiRetrofit.getBaseUrlInstance("http://www.qichexiaobaomu.com/").getApiService(); 64 | addDisposable(apiServer.getRestrictions(params), new BaseObserver(baseView) { 65 | @Override 66 | public void onSuccess(BaseModel o) { 67 | baseView.onRestrictionsSuccess((BaseModel) o); 68 | } 69 | 70 | @Override 71 | public void onError(String msg) { 72 | if (baseView != null) { 73 | baseView.showError(msg); 74 | } 75 | } 76 | }); 77 | } 78 | 79 | /** 80 | * 测试 81 | */ 82 | public void getCheShiApi() { 83 | HashMap params = new HashMap<>(); 84 | params.put("type", "1"); 85 | ApiServer apiServer = ApiRetrofit.getBaseUrlInstance("http://www.energy-link.com.cn/").getApiService(); 86 | addDisposable(apiServer.getCeShi(params), new BaseObserver(baseView) { 87 | @Override 88 | public void onSuccess(BaseModel o) { 89 | baseView.onCheShiSuccess((BaseModel) o); 90 | } 91 | 92 | @Override 93 | public void onError(String msg) { 94 | if (baseView != null) { 95 | baseView.showError(msg); 96 | } 97 | } 98 | }); 99 | } 100 | 101 | 102 | /** 103 | * 写法好多种 怎么顺手怎么来 104 | */ 105 | public void getManApi() { 106 | addDisposable(apiServer.getMain("year"), new BaseObserver(baseView) { 107 | @Override 108 | public void onSuccess(BaseModel o) { 109 | baseView.onMainSuccess((BaseModel>) o); 110 | } 111 | 112 | @Override 113 | public void onError(String msg) { 114 | if (baseView != null) { 115 | baseView.showError(msg); 116 | } 117 | } 118 | }); 119 | } 120 | 121 | /** 122 | * 写法好多种 怎么顺手怎么来 123 | */ 124 | public void getMan2Api() { 125 | addDisposable(apiServer.getMain2("year"), new BaseObserver(baseView) { 126 | @Override 127 | public void onSuccess(BaseModel o) { 128 | baseView.onMainSuccess((BaseModel>) o); 129 | } 130 | 131 | @Override 132 | public void onError(String msg) { 133 | if (baseView != null) { 134 | baseView.showError(msg); 135 | } 136 | } 137 | }); 138 | } 139 | 140 | /** 141 | * 写法好多种 怎么顺手怎么来 142 | */ 143 | public void getMan3Api() { 144 | HashMap params = new HashMap<>(); 145 | params.put("time", "year"); 146 | addDisposable(apiServer.getMain3(params), new BaseObserver(baseView) { 147 | 148 | @Override 149 | public void onSuccess(BaseModel o) { 150 | baseView.onMainSuccess((BaseModel>) o); 151 | } 152 | 153 | @Override 154 | public void onError(String msg) { 155 | if (baseView != null) { 156 | baseView.showError(msg); 157 | } 158 | } 159 | }); 160 | } 161 | 162 | /** 163 | * 写法好多种 怎么顺手怎么来 164 | */ 165 | public void getTextApi() { 166 | HashMap params = new HashMap<>(); 167 | params.put("type", "junshi"); 168 | params.put("key", "2c1cb93f8c7430a754bc3ad62e0fac06"); 169 | addDisposable(apiServer.getText(params), new BaseObserver(baseView) { 170 | 171 | @Override 172 | public void onSuccess(BaseModel o) { 173 | baseView.onTextSuccess((BaseModel) o); 174 | } 175 | 176 | @Override 177 | public void onError(String msg) { 178 | if (baseView != null) { 179 | baseView.showError(msg); 180 | } 181 | } 182 | }); 183 | } 184 | 185 | 186 | /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 图片上传 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ 187 | 188 | /** 189 | * 演示单图上传 190 | * 191 | * @param parts 192 | */ 193 | public void upLoadImgApi(MultipartBody.Part parts) { 194 | addDisposable(apiServer.upLoadImg(parts), new BaseObserver(baseView) { 195 | 196 | @Override 197 | public void onSuccess(BaseModel o) { 198 | baseView.onUpLoadImgSuccess((BaseModel) o); 199 | } 200 | 201 | @Override 202 | public void onError(String msg) { 203 | if (baseView != null) { 204 | baseView.showError(msg); 205 | } 206 | } 207 | }); 208 | } 209 | 210 | 211 | /** 212 | * 演示多图上传 213 | * 214 | * @param parts 215 | */ 216 | public void upLoadImgApi(List parts) { 217 | addDisposable(apiServer.upHeadImg(parts), new BaseObserver(baseView) { 218 | @Override 219 | public void onSuccess(BaseModel o) { 220 | baseView.onUpLoadImgSuccess((BaseModel) o); 221 | } 222 | 223 | @Override 224 | public void onError(String msg) { 225 | if (baseView != null) { 226 | baseView.showError(msg); 227 | } 228 | } 229 | }); 230 | } 231 | 232 | /** 233 | * 演示 图片和字段一起上传 234 | * 235 | * @param title 236 | * @param content 237 | * @param parts 238 | */ 239 | public void upLoadImgApi(String title, String content, List parts) { 240 | HashMap params = new HashMap<>(); 241 | params.put("title", RetrofitUtil.convertToRequestBody(title)); 242 | params.put("content", RetrofitUtil.convertToRequestBody(content)); 243 | addDisposable(apiServer.expressAdd(params, parts), new BaseObserver(baseView) { 244 | @Override 245 | public void onSuccess(BaseModel o) { 246 | baseView.onUpLoadImgSuccess((BaseModel) o); 247 | } 248 | 249 | @Override 250 | public void onError(String msg) { 251 | if (baseView != null) { 252 | baseView.showError(msg); 253 | } 254 | } 255 | }); 256 | } 257 | 258 | /** 259 | * 演示 文件上传进度监听 260 | * 261 | * @param url 262 | */ 263 | public void upLoadVideoApi(String url) { 264 | HashMap params = new HashMap<>(); 265 | params.put("fileType", RetrofitUtil.convertToRequestBody("video")); 266 | 267 | MultipartBody.Part parts = MultipartBody.Part.createFormData("file", new File(url).getName(), new ProgressRequestBody(new File(url),"video/mpeg", baseView)); 268 | 269 | ApiServer apiServer = ApiRetrofit.getBaseUrlInstance("https://bjlzbt.com/").getApiService(); 270 | addFileDisposable(apiServer.getUpload(params, parts), new FileObserver(baseView) { 271 | @Override 272 | public void onSuccess(Object o) { 273 | baseView.onUpLoadImgSuccess((BaseModel) o); 274 | } 275 | 276 | @Override 277 | public void onError(String msg) { 278 | if (baseView != null) { 279 | baseView.showError(msg); 280 | } 281 | } 282 | }); 283 | } 284 | 285 | /** 286 | * 单个文件上传 287 | * 288 | * @param parts 文件流 289 | * @return 290 | */ 291 | public void getUploadApi(HashMap params, MultipartBody.Part parts) { 292 | ApiServer apiServer = ApiRetrofit.getBaseUrlInstance("https://bjlzbt.com/").getApiService(); 293 | addDisposable(apiServer.getUpload(params, parts), new BaseObserver(baseView) { 294 | @Override 295 | public void onSuccess(BaseModel o) { 296 | baseView.onUpLoadImgSuccess((BaseModel) o); 297 | } 298 | 299 | @Override 300 | public void onError(String msg) { 301 | if (baseView != null) { 302 | baseView.showError(msg); 303 | } 304 | } 305 | }); 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/MainView.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity; 2 | 3 | 4 | import com.lp.mvp_network.base.mvp.BaseModel; 5 | import com.lp.mvp_network.base.mvp.BaseView; 6 | import com.lp.mvp_network.bean.TextBean; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * File descripition: 12 | * 13 | * @author lp 14 | * @date 2018/6/19 15 | */ 16 | 17 | public interface MainView extends BaseView { 18 | void onMainSuccess(BaseModel> o); 19 | void onTextSuccess(BaseModel o); 20 | 21 | void onUpLoadImgSuccess(BaseModel o); 22 | void onTableListSuccess(BaseModel o); 23 | void onRestrictionsSuccess(BaseModel o); 24 | void onCheShiSuccess(BaseModel o); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/MvcActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.lp.mvp_network.R; 8 | import com.lp.mvp_network.api.ApiRetrofit; 9 | import com.lp.mvp_network.base.BaseActivity; 10 | import com.lp.mvp_network.base.mvp.BaseModel; 11 | import com.lp.mvp_network.base.mvp.BasePresenter; 12 | import com.lp.mvp_network.bean.TextBean; 13 | 14 | import java.util.HashMap; 15 | 16 | import io.reactivex.android.schedulers.AndroidSchedulers; 17 | import io.reactivex.functions.Consumer; 18 | import io.reactivex.functions.Function; 19 | import io.reactivex.schedulers.Schedulers; 20 | 21 | /** 22 | * File descripition: mvc演示 23 | * 24 | * @author lp 25 | * @date 2019/8/9 26 | */ 27 | public class MvcActivity extends BaseActivity implements View.OnClickListener { 28 | private TextView mTvText; 29 | 30 | @Override 31 | protected BasePresenter createPresenter() { 32 | return null; 33 | } 34 | 35 | @Override 36 | protected int getLayoutId() { 37 | return R.layout.activity_main; 38 | } 39 | 40 | @Override 41 | protected void initData() { 42 | mTvText = findViewById(R.id.tv_text); 43 | findViewById(R.id.btn_first).setOnClickListener(this); 44 | findViewById(R.id.btn_second).setVisibility(View.GONE); 45 | findViewById(R.id.btn_second_2).setVisibility(View.GONE); 46 | findViewById(R.id.btn_third).setVisibility(View.GONE); 47 | findViewById(R.id.btn_forth).setVisibility(View.GONE); 48 | findViewById(R.id.btn_fifth).setVisibility(View.GONE); 49 | findViewById(R.id.btn_six).setVisibility(View.GONE); 50 | findViewById(R.id.btn_down).setVisibility(View.GONE); 51 | } 52 | 53 | @Override 54 | public void onClick(View v) { 55 | getDataApi(); 56 | } 57 | 58 | @SuppressLint("CheckResult") 59 | private void getDataApi() { 60 | HashMap params = new HashMap<>(); 61 | params.put("type", "junshi"); 62 | params.put("key", "2c1cb93f8c7430a754bc3ad62e0fac06"); 63 | ApiRetrofit.getInstance().getApiService() 64 | .getText(params) 65 | .subscribeOn(Schedulers.io()) 66 | .unsubscribeOn(Schedulers.io()) 67 | .observeOn(AndroidSchedulers.mainThread()) 68 | .map(new Function, BaseModel>() { 69 | @Override 70 | public BaseModel apply(BaseModel objectBaseModel) throws Exception { 71 | return objectBaseModel; 72 | } 73 | }).subscribe(new Consumer>() { 74 | @Override 75 | public void accept(BaseModel o) throws Exception { 76 | mTvText.setText(o.getResult().getData().toString()); 77 | } 78 | }, new Consumer() { 79 | @Override 80 | public void accept(Throwable throwable) throws Exception { 81 | throwable.printStackTrace(); 82 | } 83 | }); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/file/FileActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity.file; 2 | 3 | import android.Manifest; 4 | import android.annotation.SuppressLint; 5 | import android.view.View; 6 | 7 | import com.blankj.utilcode.util.FileUtils; 8 | import com.lp.mvp_network.R; 9 | import com.lp.mvp_network.base.BaseActivity; 10 | import com.lp.mvp_network.base.BaseContent; 11 | import com.lp.mvp_network.utils.L; 12 | import com.tbruyelle.rxpermissions2.RxPermissions; 13 | 14 | import java.io.File; 15 | 16 | import io.reactivex.annotations.NonNull; 17 | import io.reactivex.functions.Consumer; 18 | 19 | /** 20 | * File descripition: 21 | * 22 | * @author lp 23 | * @date 2019/8/6 24 | */ 25 | public class FileActivity extends BaseActivity implements FileView, View.OnClickListener { 26 | 27 | @Override 28 | protected FilePresenter createPresenter() { 29 | return new FilePresenter(this); 30 | } 31 | 32 | @Override 33 | protected int getLayoutId() { 34 | return R.layout.activity_file; 35 | } 36 | 37 | @Override 38 | protected void initData() { 39 | findViewById(R.id.btn_download).setOnClickListener(this); 40 | } 41 | 42 | @Override 43 | public void onFileSuccess(File file) { 44 | L.e("下载成功, 保存路径=" + file.getAbsolutePath()); 45 | } 46 | 47 | @Override 48 | public void onClick(View v) { 49 | switch (v.getId()) { 50 | //下载 51 | case R.id.btn_download: 52 | //初始化权限相关 53 | initPermission(); 54 | break; 55 | } 56 | } 57 | 58 | /** 59 | * 初始化权限相关 60 | */ 61 | @SuppressLint("CheckResult") 62 | private void initPermission() { 63 | RxPermissions rxPermissions = new RxPermissions(this); 64 | rxPermissions.request( 65 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 66 | Manifest.permission.READ_EXTERNAL_STORAGE 67 | ).subscribe(new Consumer() { 68 | @Override 69 | public void accept(@NonNull Boolean granted) throws Exception { 70 | if (granted) { 71 | String url = "https://bjlzbt.com/upload/default//20190725//c13948258c6ef6a36cbe2d3322b98f5c.mp4"; 72 | if (FileUtils.createOrExistsDir(BaseContent.baseFileName)) { 73 | mPresenter.downFile(url, BaseContent.baseFileName, "ceshi.mp4"); 74 | } 75 | } else { 76 | showToast("部分权限未获取!!"); 77 | } 78 | } 79 | }); 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/file/FilePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity.file; 2 | 3 | import com.lp.mvp_network.api.ApiRetrofit; 4 | import com.lp.mvp_network.api.ApiServer; 5 | import com.lp.mvp_network.base.file.FileUtil; 6 | import com.lp.mvp_network.base.file.FileObserver; 7 | import com.lp.mvp_network.base.mvp.BasePresenter; 8 | 9 | import java.io.File; 10 | 11 | import io.reactivex.Observable; 12 | import io.reactivex.functions.Function; 13 | import okhttp3.ResponseBody; 14 | 15 | /** 16 | * File descripition: 17 | * 18 | * @author lp 19 | * @date 2019/8/6 20 | */ 21 | public class FilePresenter extends BasePresenter { 22 | 23 | public FilePresenter(FileView baseView) { 24 | super(baseView); 25 | } 26 | 27 | public void downFile(String url, final String destFileDir, final String destFileName) { 28 | ApiServer apiServer = ApiRetrofit.getFileInstance(baseView).getApiService(); 29 | Observable observable = apiServer.downloadFile(url).map(new Function() { 30 | @Override 31 | public String apply(ResponseBody body) throws Exception { 32 | File file = FileUtil.saveFile(destFileDir+destFileName, body); 33 | return file.getPath(); 34 | } 35 | }); 36 | addFileDisposable(observable, new FileObserver(baseView) { 37 | @Override 38 | public void onSuccess(Object o) { 39 | baseView.onFileSuccess(new File(o.toString())); 40 | } 41 | 42 | @Override 43 | public void onError(String msg) { 44 | if (baseView != null) { 45 | baseView.showError(msg); 46 | } 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/activity/file/FileView.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.activity.file; 2 | 3 | import com.lp.mvp_network.base.mvp.BaseView; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * File descripition: 9 | * 10 | * @author lp 11 | * @date 2019/8/6 12 | */ 13 | public interface FileView extends BaseView { 14 | void onFileSuccess(File file); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/api/ApiDns.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.api; 2 | 3 | import java.net.Inet4Address; 4 | import java.net.InetAddress; 5 | import java.net.UnknownHostException; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import okhttp3.Dns; 10 | 11 | /** 12 | * File descripition: ipv6和ipv4换位 处理部分手机网络请求慢问题 13 | * 14 | * @author lp 15 | * @date 2019/4/16 16 | */ 17 | 18 | public class ApiDns implements Dns { 19 | @Override 20 | public List lookup(String hostname) throws UnknownHostException { 21 | if (hostname == null) { 22 | throw new UnknownHostException("hostname == null"); 23 | } else { 24 | try { 25 | List mInetAddressesList = new ArrayList<>(); 26 | InetAddress[] mInetAddresses = InetAddress.getAllByName(hostname); 27 | for (InetAddress address : mInetAddresses) { 28 | if (address instanceof Inet4Address) { 29 | mInetAddressesList.add(0, address); 30 | } else { 31 | mInetAddressesList.add(address); 32 | } 33 | } 34 | return mInetAddressesList; 35 | } catch (NullPointerException var4) { 36 | UnknownHostException unknownHostException = new UnknownHostException("Broken system behaviour"); 37 | unknownHostException.initCause(var4); 38 | throw unknownHostException; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/api/ApiServer.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.api; 2 | 3 | 4 | import com.lp.mvp_network.activity.MainBean; 5 | import com.lp.mvp_network.base.mvp.BaseModel; 6 | import com.lp.mvp_network.bean.TextBean; 7 | import com.lp.mvp_network.second2demo.bean.Bean1; 8 | import com.lp.mvp_network.second2demo.bean.Bean2; 9 | import com.lp.mvp_network.second2demo.bean.Bean3; 10 | 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import io.reactivex.Observable; 16 | import okhttp3.MultipartBody; 17 | import okhttp3.RequestBody; 18 | import okhttp3.ResponseBody; 19 | import retrofit2.http.Field; 20 | import retrofit2.http.FieldMap; 21 | import retrofit2.http.FormUrlEncoded; 22 | import retrofit2.http.GET; 23 | import retrofit2.http.Multipart; 24 | import retrofit2.http.POST; 25 | import retrofit2.http.Part; 26 | import retrofit2.http.PartMap; 27 | import retrofit2.http.Query; 28 | import retrofit2.http.Streaming; 29 | import retrofit2.http.Url; 30 | 31 | /** 32 | * File descripition: 33 | * 34 | * @author lp 35 | * @date 2018/6/19 36 | */ 37 | 38 | public interface ApiServer { 39 | 40 | /** 41 | * 大文件官方建议用 @Streaming 来进行注解,不然会出现IO异常,小文件可以忽略不注入 42 | */ 43 | @Streaming 44 | @GET 45 | Observable downloadFile(@Url String fileUrl); 46 | 47 | 48 | /** 49 | * 客户标签的筛选项 50 | * 51 | * @param params 52 | * @return 53 | */ 54 | @FormUrlEncoded 55 | @POST("/api/table_list/") 56 | Observable> getTableList(@FieldMap HashMap params); 57 | /** 58 | * 当前城市限行 59 | * 60 | * @param params 61 | * @return 62 | */ 63 | @FormUrlEncoded 64 | @POST("/restrictions/") 65 | Observable> getRestrictions(@FieldMap HashMap params); 66 | /** 67 | * 当前城市限行 68 | * 69 | * @param params 70 | * @return 71 | */ 72 | @FormUrlEncoded 73 | @POST("/api/public/banners") 74 | Observable> getCeShi(@FieldMap HashMap params); 75 | 76 | 77 | /** 78 | * 第一种写法 79 | * 80 | * @param requestType 81 | * @return 82 | */ 83 | @POST("api/Activity/get_activities?") 84 | Observable>> getMain(@Query("time") String requestType); 85 | 86 | /** 87 | * 第二种写法 88 | * 89 | * @param requestType 90 | * @return 91 | */ 92 | @FormUrlEncoded 93 | @POST("api/Activity/get_activities?") 94 | Observable>> getMain2(@Field("time") String requestType); 95 | 96 | /** 97 | * 第三种写法 98 | * 99 | * @param params 100 | * @return 101 | */ 102 | @FormUrlEncoded 103 | @POST("api/Activity/get_activities?") 104 | Observable>> getMain3(@FieldMap HashMap params); 105 | 106 | /** 107 | * text 108 | * 109 | * @param params 110 | * @return 111 | */ 112 | @FormUrlEncoded 113 | @POST("index?") 114 | Observable> getText(@FieldMap HashMap params); 115 | 116 | /** 117 | * 演示 单图上传 118 | * 119 | * @param parts 120 | * @return 121 | */ 122 | @Multipart 123 | @POST("api/Company/register") 124 | Observable> upLoadImg(@Part MultipartBody.Part parts); 125 | 126 | /** 127 | * 演示 多图上传 128 | * 129 | * @param parts 130 | * @return 131 | */ 132 | @Multipart 133 | @POST("api/user_info/update_headimg") 134 | Observable> upHeadImg(@Part List parts); 135 | 136 | /** 137 | * 演示 图片字段一起上传 138 | * 139 | * @param parts 140 | * @return 141 | */ 142 | @Multipart 143 | @POST("api/Express/add") 144 | Observable> expressAdd(@PartMap Map map, 145 | @Part List parts); 146 | 147 | /** 148 | * 上传图片/视频 149 | *

150 | * // * @param token 用户登录的token 151 | * // * @param file 文件流 152 | * 153 | * @return 154 | */ 155 | @Multipart 156 | @POST("/wxapp/public/upload") 157 | Observable> getUpload(@PartMap Map map, 158 | @Part MultipartBody.Part parts 159 | ); 160 | 161 | 162 | /** 163 | * 演示特殊结构写法 164 | * 165 | * @param requestType 166 | * @return 167 | */ 168 | @POST("api/Activity/get_activities?") 169 | Observable, Bean2, List>> getMain2Demo(@Query("time") String requestType); 170 | 171 | /** 172 | * 演示特殊结构写法 173 | * 174 | * @return 175 | */ 176 | @FormUrlEncoded 177 | @POST("api/Activity/get_activities?") 178 | Observable, Bean2, List>> getMain3Demo(@FieldMap HashMap params); 179 | 180 | } 181 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base; 2 | 3 | /** 4 | * File descripition: 异常处理基类 5 | * 6 | * @author lp 7 | * @date 2018/8/24 8 | */ 9 | 10 | public class ApiException extends RuntimeException { 11 | private int errorCode; 12 | 13 | public ApiException(int code, String msg) { 14 | super(msg); 15 | this.errorCode = code; 16 | } 17 | 18 | public int getErrorCode() { 19 | return errorCode; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.widget.EditText; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import com.gastudio.downloadloadding.library.GADownloadingView; 16 | import com.hjq.toast.ToastUtils; 17 | import com.lp.mvp_network.R; 18 | import com.lp.mvp_network.base.mvp.BaseModel; 19 | import com.lp.mvp_network.base.mvp.BasePresenter; 20 | import com.lp.mvp_network.base.mvp.BaseView; 21 | import com.lp.mvp_network.utils.KeyBoardUtils; 22 | import com.lp.mvp_network.utils.StatusBarUtil; 23 | import com.lp.mvp_network.view.LoadingDialog; 24 | import com.lp.mvp_network.view.ProgressDialog; 25 | 26 | /** 27 | * File descripition: activity基类 28 | *

29 | * 30 | * @author lp 31 | * @date 2018/5/16 32 | */ 33 | public abstract class BaseActivity

extends AppCompatActivity implements BaseView { 34 | protected final String TAG = this.getClass().getSimpleName(); 35 | public Context mContext; 36 | protected P mPresenter; 37 | 38 | protected abstract P createPresenter(); 39 | 40 | private LoadingDialog loadingDialog; 41 | private ProgressDialog progressDialog; 42 | 43 | @Override 44 | protected void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | mContext = this; 47 | setContentView(getLayoutId()); 48 | mPresenter = createPresenter(); 49 | setStatusBar(); 50 | 51 | this.initData(); 52 | } 53 | 54 | /** 55 | * 获取布局ID 56 | * 57 | * @return 58 | */ 59 | protected abstract int getLayoutId(); 60 | 61 | /** 62 | * 数据初始化操作 63 | */ 64 | protected abstract void initData(); 65 | 66 | /** 67 | * 此处设置沉浸式地方 68 | */ 69 | protected void setStatusBar() { 70 | StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null); 71 | } 72 | 73 | /** 74 | * 封装toast方法(自行定制实现) 75 | * 76 | * @param str 77 | */ 78 | public void showToast(String str) { 79 | ToastUtils.show(str); 80 | } 81 | 82 | public void showLongToast(String str) { 83 | ToastUtils.show(str); 84 | } 85 | 86 | @Override 87 | public void showError(String msg) { 88 | showToast(msg); 89 | } 90 | 91 | /** 92 | * 返回所有状态 除去指定的值 可设置所有(根据需求) 93 | * 94 | * @param model 95 | */ 96 | @Override 97 | public void onErrorCode(BaseModel model) { 98 | if (model.getError_code() == 10000000) { 99 | //处理些后续逻辑 如果某个页面不想实现 子类重写这个方法 将super去掉 自定义方法 100 | // App.put(); 101 | // startActivity(LoginActivity.class); 102 | } 103 | } 104 | 105 | @Override 106 | public void showLoading() { 107 | showLoadingDialog(); 108 | } 109 | 110 | @Override 111 | public void hideLoading() { 112 | dissMissDialog(); 113 | } 114 | 115 | public void showLoadingDialog() { 116 | showLoadingDialog("加载中..."); 117 | } 118 | 119 | /** 120 | * 加载 黑框... 121 | */ 122 | public void showLoadingDialog(String msg) { 123 | if (loadingDialog == null) { 124 | loadingDialog = new LoadingDialog(this); 125 | } 126 | loadingDialog.setMessage(msg); 127 | if (!loadingDialog.isShowing()) { 128 | loadingDialog.show(); 129 | } 130 | } 131 | 132 | /** 133 | * 消失 黑框... 134 | */ 135 | public void dissMissDialog() { 136 | if (loadingDialog != null) { 137 | loadingDialog.dismiss(); 138 | } 139 | } 140 | 141 | @Override 142 | protected void onDestroy() { 143 | super.onDestroy(); 144 | if (mPresenter != null) { 145 | mPresenter.detachView(); 146 | } 147 | if (loadingDialog != null) { 148 | loadingDialog.dismiss(); 149 | } 150 | if (progressDialog != null) { 151 | progressDialog.dismiss(); 152 | } 153 | if (mPresenter != null) { 154 | mPresenter.detachView(); 155 | } 156 | } 157 | 158 | 159 | @Override 160 | public void showProgress() { 161 | if (progressDialog == null) { 162 | progressDialog = new ProgressDialog(this); 163 | } 164 | progressDialog.getProgressBar().performAnimation(); 165 | if (!progressDialog.isShowing()) { 166 | progressDialog.show(); 167 | } 168 | } 169 | 170 | @Override 171 | public void hideProgress() { 172 | if (progressDialog != null) { 173 | progressDialog.getProgressBar().releaseAnimation(); 174 | progressDialog.dismiss(); 175 | } 176 | } 177 | 178 | @Override 179 | public void onProgress(int progress) { 180 | if (progressDialog != null) { 181 | progressDialog.updateProgress(progress); 182 | } 183 | } 184 | 185 | /** 186 | * [页面跳转] 187 | * 188 | * @param clz 189 | */ 190 | public void startActivity(Class clz) { 191 | startActivity(clz, null); 192 | } 193 | 194 | 195 | /** 196 | * [携带数据的页面跳转] 197 | * 198 | * @param clz 199 | * @param bundle 200 | */ 201 | public void startActivity(Class clz, Bundle bundle) { 202 | Intent intent = new Intent(); 203 | intent.setClass(this, clz); 204 | if (bundle != null) { 205 | intent.putExtras(bundle); 206 | } 207 | startActivity(intent); 208 | } 209 | 210 | /** 211 | * [含有Bundle通过Class打开编辑界面] 212 | * 213 | * @param cls 214 | * @param bundle 215 | * @param requestCode 216 | */ 217 | public void startActivityForResult(Class cls, Bundle bundle, int requestCode) { 218 | Intent intent = new Intent(); 219 | intent.setClass(this, cls); 220 | if (bundle != null) { 221 | intent.putExtras(bundle); 222 | } 223 | startActivityForResult(intent, requestCode); 224 | } 225 | 226 | /** 227 | * 以下是关于软键盘的处理 228 | */ 229 | 230 | /** 231 | * 清除editText的焦点 232 | * 233 | * @param v 焦点所在View 234 | * @param ids 输入框 235 | */ 236 | public void clearViewFocus(View v, int... ids) { 237 | if (null != v && null != ids && ids.length > 0) { 238 | for (int id : ids) { 239 | if (v.getId() == id) { 240 | v.clearFocus(); 241 | break; 242 | } 243 | } 244 | } 245 | } 246 | 247 | /** 248 | * 隐藏键盘 249 | * 250 | * @param v 焦点所在View 251 | * @param ids 输入框 252 | * @return true代表焦点在edit上 253 | */ 254 | public boolean isFocusEditText(View v, int... ids) { 255 | if (v instanceof EditText) { 256 | EditText et = (EditText) v; 257 | for (int id : ids) { 258 | if (et.getId() == id) { 259 | return true; 260 | } 261 | } 262 | } 263 | return false; 264 | } 265 | 266 | //是否触摸在指定view上面,对某个控件过滤 267 | public boolean isTouchView(View[] views, MotionEvent ev) { 268 | if (views == null || views.length == 0) { 269 | return false; 270 | } 271 | int[] location = new int[2]; 272 | for (View view : views) { 273 | view.getLocationOnScreen(location); 274 | int x = location[0]; 275 | int y = location[1]; 276 | if (ev.getX() > x && ev.getX() < (x + view.getWidth()) 277 | && ev.getY() > y && ev.getY() < (y + view.getHeight())) { 278 | return true; 279 | } 280 | } 281 | return false; 282 | } 283 | 284 | @Override 285 | public boolean dispatchTouchEvent(MotionEvent ev) { 286 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 287 | if (isTouchView(filterViewByIds(), ev)) { 288 | return super.dispatchTouchEvent(ev); 289 | } 290 | if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) { 291 | return super.dispatchTouchEvent(ev); 292 | } 293 | View v = getCurrentFocus(); 294 | if (isFocusEditText(v, hideSoftByEditViewIds())) { 295 | KeyBoardUtils.hideInputForce(this); 296 | clearViewFocus(v, hideSoftByEditViewIds()); 297 | } 298 | } 299 | return super.dispatchTouchEvent(ev); 300 | } 301 | 302 | 303 | /** 304 | * 传入EditText的Id 305 | * 没有传入的EditText不做处理 306 | * 307 | * @return id 数组 308 | */ 309 | public int[] hideSoftByEditViewIds() { 310 | return null; 311 | } 312 | 313 | /** 314 | * 传入要过滤的View 315 | * 过滤之后点击将不会有隐藏软键盘的操作 316 | * 317 | * @return id 数组 318 | */ 319 | public View[] filterViewByIds() { 320 | return null; 321 | } 322 | 323 | 324 | /*实现案例===============================================================================================*/ 325 | /* 326 | 327 | @Override 328 | public int[] hideSoftByEditViewIds() { 329 | int[] ids = {R.id.et_company_name, R.id.et_address}; 330 | return ids; 331 | } 332 | 333 | @Override 334 | public View[] filterViewByIds() { 335 | View[] views = {mEtCompanyName, mEtAddress}; 336 | return views; 337 | } 338 | 339 | */ 340 | } 341 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/BaseContent.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base; 2 | 3 | import android.os.Environment; 4 | 5 | /** 6 | * File descripition: 7 | * 8 | * @author lp 9 | * @date 2018/6/19 10 | */ 11 | 12 | public class BaseContent { 13 | //base Ip 14 | public static String baseUrl = "http://v.juhe.cn/toutiao/"; 15 | //视频文件存储路径 16 | public static String baseFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "mvp_network/"; 17 | //服务器返回成功的 cdoe 18 | public static int basecode = 0; 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.lp.mvp_network.base.mvp.BaseModel; 13 | import com.lp.mvp_network.base.mvp.BasePresenter; 14 | import com.lp.mvp_network.base.mvp.BaseView; 15 | 16 | 17 | /** 18 | * File descripition: ftagment 基类 19 | * 20 | * @author lp 21 | * @date 2018/6/19 22 | */ 23 | 24 | public abstract class BaseFragment

extends Fragment implements BaseView { 25 | public View view; 26 | 27 | public Context mContext; 28 | protected P mPresenter; 29 | 30 | protected abstract P createPresenter(); 31 | 32 | @Nullable 33 | @Override 34 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 35 | view = inflater.inflate(getLayoutId(), container, false); 36 | 37 | mContext = getActivity(); 38 | mPresenter = createPresenter(); 39 | 40 | this.initToolbar(savedInstanceState); 41 | this.initData(); 42 | 43 | return view; 44 | } 45 | 46 | /** 47 | * 获取布局ID 48 | * 49 | * @return 50 | */ 51 | protected abstract int getLayoutId(); 52 | 53 | /** 54 | * 处理顶部title 55 | * 56 | * @param savedInstanceState 57 | */ 58 | protected abstract void initToolbar(Bundle savedInstanceState); 59 | 60 | 61 | /** 62 | * 数据初始化操作 63 | */ 64 | protected abstract void initData(); 65 | 66 | public void showToast(String str) { 67 | } 68 | 69 | public void showLongToast(String str) { 70 | } 71 | 72 | @Override 73 | public void showError(String msg) { 74 | showToast(msg); 75 | } 76 | 77 | @Override 78 | public void onErrorCode(BaseModel model) { 79 | } 80 | 81 | @Override 82 | public void showLoading() { 83 | } 84 | 85 | @Override 86 | public void hideLoading() { 87 | } 88 | 89 | 90 | @Override 91 | public void onDestroy() { 92 | super.onDestroy(); 93 | this.view = null; 94 | if (mPresenter != null) { 95 | mPresenter.detachView(); 96 | } 97 | } 98 | 99 | @Override 100 | public void onDestroyView() { 101 | super.onDestroyView(); 102 | } 103 | 104 | /** 105 | * [页面跳转] 106 | * 107 | * @param clz 108 | */ 109 | public void startActivity(Class clz) { 110 | startActivity(clz, null); 111 | } 112 | 113 | 114 | /** 115 | * [携带数据的页面跳转] 116 | * 117 | * @param clz 118 | * @param bundle 119 | */ 120 | public void startActivity(Class clz, Bundle bundle) { 121 | Intent intent = new Intent(); 122 | intent.setClass(getActivity(), clz); 123 | if (bundle != null) { 124 | intent.putExtras(bundle); 125 | } 126 | startActivity(intent); 127 | } 128 | 129 | /** 130 | * [含有Bundle通过Class打开编辑界面] 131 | * 132 | * @param cls 133 | * @param bundle 134 | * @param requestCode 135 | */ 136 | public void startActivityForResult(Class cls, Bundle bundle, 137 | int requestCode) { 138 | Intent intent = new Intent(); 139 | intent.setClass(getActivity(), cls); 140 | if (bundle != null) { 141 | intent.putExtras(bundle); 142 | } 143 | startActivityForResult(intent, requestCode); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/convert/MyGsonConverterFactory.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.convert; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import java.lang.annotation.Annotation; 8 | import java.lang.reflect.Type; 9 | 10 | import okhttp3.RequestBody; 11 | import okhttp3.ResponseBody; 12 | import retrofit2.Converter; 13 | import retrofit2.Retrofit; 14 | 15 | /** 16 | * File descripition: 重写gson 判断返回值 状态划分 17 | * 18 | * @author lp 19 | * @date 2018/8/24 20 | */ 21 | 22 | /** 23 | * A {@linkplain Converter.Factory converter} which uses Gson for JSON. 24 | *

25 | * Because Gson is so flexible in the types it supports, this converter assumes that it can handle 26 | * all types. If you are mixing JSON serialization with something else (such as protocol buffers), 27 | * you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this instance} 28 | * last to allow the other converters a chance to see their types. 29 | */ 30 | public final class MyGsonConverterFactory extends Converter.Factory { 31 | /** 32 | * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and 33 | * decoding from JSON (when no charset is specified by a header) will use UTF-8. 34 | */ 35 | public static MyGsonConverterFactory create() { 36 | return create(new Gson()); 37 | } 38 | 39 | /** 40 | * Create an instance using {@code gson} for conversion. Encoding to JSON and 41 | * decoding from JSON (when no charset is specified by a header) will use UTF-8. 42 | */ 43 | @SuppressWarnings("ConstantConditions") // Guarding public API nullability. 44 | public static MyGsonConverterFactory create(Gson gson) { 45 | if (gson == null) throw new NullPointerException("gson == null"); 46 | return new MyGsonConverterFactory(gson); 47 | } 48 | 49 | private final Gson gson; 50 | 51 | private MyGsonConverterFactory(Gson gson) { 52 | this.gson = gson; 53 | } 54 | 55 | @Override 56 | public Converter responseBodyConverter(Type type, Annotation[] annotations, 57 | Retrofit retrofit) { 58 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); 59 | return new MyGsonResponseBodyConverter<>(gson, adapter); 60 | } 61 | 62 | @Override 63 | public Converter requestBodyConverter(Type type, 64 | Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 65 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); 66 | return new MyGsonRequestBodyConverter<>(gson, adapter); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/convert/MyGsonRequestBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.convert; 2 | 3 | 4 | import com.google.gson.Gson; 5 | import com.google.gson.TypeAdapter; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | import java.io.OutputStreamWriter; 10 | import java.io.Writer; 11 | import java.nio.charset.Charset; 12 | 13 | import okhttp3.MediaType; 14 | import okhttp3.RequestBody; 15 | import okio.Buffer; 16 | import retrofit2.Converter; 17 | 18 | /** 19 | * File descripition: 重写gson 判断返回值 状态划分 20 | * 21 | * @author lp 22 | * @date 2018/8/24 23 | */ 24 | 25 | final class MyGsonRequestBodyConverter implements Converter { 26 | private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); 27 | private static final Charset UTF_8 = Charset.forName("UTF-8"); 28 | 29 | private final Gson gson; 30 | private final TypeAdapter adapter; 31 | 32 | MyGsonRequestBodyConverter(Gson gson, TypeAdapter adapter) { 33 | this.gson = gson; 34 | this.adapter = adapter; 35 | } 36 | 37 | @Override 38 | public RequestBody convert(T value) throws IOException { 39 | Buffer buffer = new Buffer(); 40 | Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); 41 | JsonWriter jsonWriter = gson.newJsonWriter(writer); 42 | adapter.write(jsonWriter, value); 43 | jsonWriter.close(); 44 | return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/convert/MyGsonResponseBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.convert; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.stream.JsonReader; 6 | import com.lp.mvp_network.base.ApiException; 7 | import com.lp.mvp_network.base.BaseContent; 8 | import com.lp.mvp_network.base.mvp.BaseModel; 9 | 10 | import java.io.ByteArrayInputStream; 11 | import java.io.IOException; 12 | import java.io.InputStreamReader; 13 | import java.nio.charset.Charset; 14 | 15 | import okhttp3.MediaType; 16 | import okhttp3.ResponseBody; 17 | import retrofit2.Converter; 18 | 19 | import static okhttp3.internal.Util.UTF_8; 20 | 21 | 22 | /** 23 | * File descripition: 重写gson 判断返回值 状态划分 24 | *

25 | * 此处很重要 26 | * 为何这样写:因为开发中有这样的需求 当服务器返回假如0是正常 1是不正常 0我们gson 或 fastJson解析数据 27 | * 1我们不想解析(可能返回值出现以前是对象 数据为空变成了数组等等,于是在不改后台代码的情况下 我们前端需要处理) 28 | * 但是用了插件之后没有很有效的方法控制解析 所以处理方式为 当服务器返回不等于0时候 其他状态都抛出异常 然后提示 29 | *

30 | *

31 | * 此处为如果在解析这一步拦截 可采取这种方式 32 | * 33 | * @author lp 34 | * @date 2018/8/24 35 | */ 36 | 37 | final class MyGsonResponseBodyConverter implements Converter { 38 | private final Gson gson; 39 | private final TypeAdapter adapter; 40 | 41 | MyGsonResponseBodyConverter(Gson gson, TypeAdapter adapter) { 42 | this.gson = gson; 43 | this.adapter = adapter; 44 | } 45 | 46 | @Override 47 | public T convert(ResponseBody value) throws IOException { 48 | String response = value.string(); 49 | BaseModel re = gson.fromJson(response, BaseModel.class); 50 | //关注的重点,自定义响应码中非0的情况,一律抛出ApiException异常。 51 | //这样,我们就成功的将该异常交给onError()去处理了。 52 | /* if (re.getErrcode() != BaseContent.basecode) { 53 | value.close(); 54 | throw new ApiException(re.getErrcode(), re.getErrmsg()); 55 | }*/ 56 | 57 | MediaType mediaType = value.contentType(); 58 | Charset charset = mediaType != null ? mediaType.charset(UTF_8) : UTF_8; 59 | ByteArrayInputStream bis = new ByteArrayInputStream(response.getBytes()); 60 | InputStreamReader reader = new InputStreamReader(bis, charset); 61 | JsonReader jsonReader = gson.newJsonReader(reader); 62 | try { 63 | return adapter.read(jsonReader); 64 | } finally { 65 | value.close(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/cookie/CookieManger.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.cookie; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.util.Log; 6 | 7 | 8 | import java.util.List; 9 | 10 | import okhttp3.Cookie; 11 | import okhttp3.CookieJar; 12 | import okhttp3.HttpUrl; 13 | 14 | /** 15 | * File descripition: cookie 处理 16 | * 17 | * @author lp 18 | * @date 2018/7/2 19 | */ 20 | 21 | public class CookieManger implements CookieJar { 22 | private static Context mContext; 23 | 24 | private static PersistentCookieStore cookieStore; 25 | 26 | public CookieManger(Context context) { 27 | mContext = context; 28 | if (cookieStore == null) { 29 | cookieStore = new PersistentCookieStore(mContext); 30 | } 31 | } 32 | 33 | @Override 34 | public void saveFromResponse(HttpUrl url, List cookies) { 35 | if (cookies != null && cookies.size() > 0) { 36 | for (Cookie item : cookies) { 37 | cookieStore.add(url, item); 38 | if (item.name() != null && !TextUtils.isEmpty(item.name()) && 39 | item.value() != null && !TextUtils.isEmpty(item.value())) { 40 | /*保存cookie到sp地方 可能会用到 */ 41 | // PrefUtils.setString(mContext, "cookie_name", item.name()); 42 | // PrefUtils.setString(mContext, "cookie_value", item.value()); 43 | } 44 | } 45 | } 46 | } 47 | 48 | @Override 49 | public List loadForRequest(HttpUrl url) { 50 | List cookies = cookieStore.get(url); 51 | for (int i = 0; i < cookies.size(); i++) { 52 | Log.e("", "拿出来的cookies name()==" + cookies.get(i).name()); 53 | Log.e("", "拿出来的cookies value()==" + cookies.get(i).value()); 54 | } 55 | return cookies; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/cookie/OkHttpCookies.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.cookie; 2 | 3 | import java.io.IOException; 4 | import java.io.ObjectInputStream; 5 | import java.io.ObjectOutputStream; 6 | import java.io.Serializable; 7 | 8 | import okhttp3.Cookie; 9 | 10 | /** 11 | * File descripition: cookie 处理 12 | * 13 | * @author lp 14 | * @date 2018/7/2 15 | */ 16 | 17 | public class OkHttpCookies implements Serializable { 18 | private transient final Cookie cookies; 19 | private transient Cookie clientCookies; 20 | 21 | public OkHttpCookies(Cookie cookies) { 22 | this.cookies = cookies; 23 | } 24 | 25 | public Cookie getCookies() { 26 | Cookie bestCookies = cookies; 27 | if (clientCookies != null) { 28 | bestCookies = clientCookies; 29 | } 30 | return bestCookies; 31 | } 32 | 33 | private void writeObject(ObjectOutputStream out) throws IOException { 34 | out.writeObject(cookies.name()); 35 | out.writeObject(cookies.value()); 36 | out.writeLong(cookies.expiresAt()); 37 | out.writeObject(cookies.domain()); 38 | out.writeObject(cookies.path()); 39 | out.writeBoolean(cookies.secure()); 40 | out.writeBoolean(cookies.httpOnly()); 41 | out.writeBoolean(cookies.hostOnly()); 42 | out.writeBoolean(cookies.persistent()); 43 | } 44 | 45 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 46 | String name = (String) in.readObject(); 47 | String value = (String) in.readObject(); 48 | long expiresAt = in.readLong(); 49 | String domain = (String) in.readObject(); 50 | String path = (String) in.readObject(); 51 | boolean secure = in.readBoolean(); 52 | boolean httpOnly = in.readBoolean(); 53 | boolean hostOnly = in.readBoolean(); 54 | boolean persistent = in.readBoolean(); 55 | Cookie.Builder builder = new Cookie.Builder(); 56 | builder = builder.name(name); 57 | builder = builder.value(value); 58 | builder = builder.expiresAt(expiresAt); 59 | builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain); 60 | builder = builder.path(path); 61 | builder = secure ? builder.secure() : builder; 62 | builder = httpOnly ? builder.httpOnly() : builder; 63 | clientCookies =builder.build(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/cookie/PersistentCookieStore.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.cookie; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.text.TextUtils; 6 | import android.util.Log; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | import java.io.ObjectInputStream; 12 | import java.io.ObjectOutputStream; 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Locale; 17 | import java.util.Map; 18 | import java.util.concurrent.ConcurrentHashMap; 19 | 20 | import okhttp3.Cookie; 21 | import okhttp3.HttpUrl; 22 | 23 | /** 24 | * File descripition: cookie 处理 25 | * 26 | * @author lp 27 | * @date 2018/7/2 28 | */ 29 | 30 | public class PersistentCookieStore { 31 | private static final String LOG_TAG = "PersistentCookieStore"; 32 | private static final String COOKIE_PREFS = "Cookies_Prefs"; 33 | 34 | private final Map> cookies; 35 | private final SharedPreferences cookiePrefs; 36 | 37 | 38 | public PersistentCookieStore(Context context) { 39 | cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0); 40 | cookies = new HashMap<>(); 41 | 42 | //将持久化的cookies缓存到内存中 即map cookies 43 | Map prefsMap = cookiePrefs.getAll(); 44 | for (Map.Entry entry : prefsMap.entrySet()) { 45 | String[] cookieNames = TextUtils.split((String) entry.getValue(), ","); 46 | for (String name : cookieNames) { 47 | String encodedCookie = cookiePrefs.getString(name, null); 48 | if (encodedCookie != null) { 49 | Cookie decodedCookie = decodeCookie(encodedCookie); 50 | if (decodedCookie != null) { 51 | if (!cookies.containsKey(entry.getKey())) { 52 | cookies.put(entry.getKey(), new ConcurrentHashMap()); 53 | } 54 | cookies.get(entry.getKey()).put(name, decodedCookie); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | protected String getCookieToken(Cookie cookie) { 62 | return cookie.name() + "@" + cookie.domain(); 63 | } 64 | 65 | public void add(HttpUrl url, Cookie cookie) { 66 | String name = getCookieToken(cookie); 67 | 68 | //将cookies缓存到内存中 如果缓存过期 就重置此cookie 69 | if (!cookie.persistent()) { 70 | if (!cookies.containsKey(url.host())) { 71 | cookies.put(url.host(), new ConcurrentHashMap()); 72 | } 73 | cookies.get(url.host()).put(name, cookie); 74 | } else { 75 | if (cookies.containsKey(url.host())) { 76 | cookies.get(url.host()).remove(name); 77 | } 78 | } 79 | 80 | //讲cookies持久化到本地 81 | SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); 82 | prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet())); 83 | prefsWriter.putString(name, encodeCookie(new OkHttpCookies(cookie))); 84 | prefsWriter.apply(); 85 | } 86 | 87 | public List get(HttpUrl url) { 88 | ArrayList ret = new ArrayList<>(); 89 | if (cookies.containsKey(url.host())) { 90 | ret.addAll(cookies.get(url.host()).values()); 91 | } 92 | return ret; 93 | } 94 | 95 | public boolean removeAll() { 96 | SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); 97 | prefsWriter.clear(); 98 | prefsWriter.apply(); 99 | cookies.clear(); 100 | return true; 101 | } 102 | 103 | public boolean remove(HttpUrl url, Cookie cookie) { 104 | String name = getCookieToken(cookie); 105 | 106 | if (cookies.containsKey(url.host()) && cookies.get(url.host()).containsKey(name)) { 107 | cookies.get(url.host()).remove(name); 108 | 109 | SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); 110 | if (cookiePrefs.contains(name)) { 111 | prefsWriter.remove(name); 112 | } 113 | prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet())); 114 | prefsWriter.apply(); 115 | 116 | return true; 117 | } else { 118 | return false; 119 | } 120 | } 121 | 122 | public List getCookies() { 123 | ArrayList ret = new ArrayList<>(); 124 | for (String key : cookies.keySet()) { 125 | ret.addAll(cookies.get(key).values()); 126 | } 127 | 128 | return ret; 129 | } 130 | 131 | /** 132 | * cookies 序列化成 string 133 | * 134 | * @param cookie 要序列化的cookie 135 | * @return 序列化之后的string 136 | */ 137 | protected String encodeCookie(OkHttpCookies cookie) { 138 | if (cookie == null) { 139 | return null; 140 | } 141 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 142 | try { 143 | ObjectOutputStream outputStream = new ObjectOutputStream(os); 144 | outputStream.writeObject(cookie); 145 | } catch (IOException e) { 146 | Log.d(LOG_TAG, "IOException in encodeCookie", e); 147 | return null; 148 | } 149 | 150 | return byteArrayToHexString(os.toByteArray()); 151 | } 152 | 153 | /** 154 | * 将字符串反序列化成cookies 155 | * 156 | * @param cookieString cookies string 157 | * @return cookie object 158 | */ 159 | protected Cookie decodeCookie(String cookieString) { 160 | byte[] bytes = hexStringToByteArray(cookieString); 161 | ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); 162 | Cookie cookie = null; 163 | try { 164 | ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); 165 | cookie = ((OkHttpCookies) objectInputStream.readObject()).getCookies(); 166 | } catch (IOException e) { 167 | Log.d(LOG_TAG, "IOException in decodeCookie", e); 168 | } catch (ClassNotFoundException e) { 169 | Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e); 170 | } 171 | 172 | return cookie; 173 | } 174 | 175 | /** 176 | * 二进制数组转十六进制字符串 177 | * 178 | * @param bytes byte array to be converted 179 | * @return string containing hex values 180 | */ 181 | protected String byteArrayToHexString(byte[] bytes) { 182 | StringBuilder sb = new StringBuilder(bytes.length * 2); 183 | for (byte element : bytes) { 184 | int v = element & 0xff; 185 | if (v < 16) { 186 | sb.append('0'); 187 | } 188 | sb.append(Integer.toHexString(v)); 189 | } 190 | return sb.toString().toUpperCase(Locale.US); 191 | } 192 | 193 | /** 194 | * 十六进制字符串转二进制数组 195 | * 196 | * @param hexString string of hex-encoded values 197 | * @return decoded byte array 198 | */ 199 | protected byte[] hexStringToByteArray(String hexString) { 200 | int len = hexString.length(); 201 | byte[] data = new byte[len / 2]; 202 | for (int i = 0; i < len; i += 2) { 203 | data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16)); 204 | } 205 | return data; 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/file/FileObserver.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.file; 2 | 3 | import com.google.gson.JsonParseException; 4 | import com.lp.mvp_network.base.mvp.BaseView; 5 | 6 | import org.json.JSONException; 7 | 8 | import java.io.InterruptedIOException; 9 | import java.net.ConnectException; 10 | import java.net.UnknownHostException; 11 | import java.text.ParseException; 12 | 13 | import io.reactivex.observers.DisposableObserver; 14 | import retrofit2.HttpException; 15 | 16 | /** 17 | * File descripition: 18 | * 19 | * @author lp 20 | * @date 2019/8/6 21 | */ 22 | public abstract class FileObserver extends DisposableObserver { 23 | protected BaseView view; 24 | 25 | /** 26 | * 网络连接失败 无网 27 | */ 28 | public static final int NETWORK_ERROR = 100000; 29 | /** 30 | * 解析数据失败 31 | */ 32 | public static final int PARSE_ERROR = 1008; 33 | /** 34 | * 网络问题 35 | */ 36 | public static final int BAD_NETWORK = 1007; 37 | /** 38 | * 连接错误 39 | */ 40 | public static final int CONNECT_ERROR = 1006; 41 | /** 42 | * 连接超时 43 | */ 44 | public static final int CONNECT_TIMEOUT = 1005; 45 | 46 | /** 47 | * 其他所有情况 48 | */ 49 | public static final int NOT_TRUE_OVER = 1004; 50 | 51 | public FileObserver(BaseView view) { 52 | this.view = view; 53 | } 54 | 55 | @Override 56 | protected void onStart() { 57 | if (view != null) { 58 | view.showProgress(); 59 | } 60 | } 61 | 62 | @Override 63 | public void onNext(T t) { 64 | onSuccess(t); 65 | } 66 | 67 | @Override 68 | public void onError(Throwable e) { 69 | if (view != null) { 70 | view.hideProgress(); 71 | } 72 | if (view != null) { 73 | view.hideLoading(); 74 | } 75 | if (e instanceof HttpException) { 76 | // HTTP错误 77 | onException(BAD_NETWORK, ""); 78 | } else if (e instanceof ConnectException 79 | || e instanceof UnknownHostException) { 80 | // 连接错误 81 | onException(CONNECT_ERROR, ""); 82 | } else if (e instanceof InterruptedIOException) { 83 | // 连接超时 84 | onException(CONNECT_TIMEOUT, ""); 85 | } else if (e instanceof JsonParseException 86 | || e instanceof JSONException 87 | || e instanceof ParseException) { 88 | // 解析错误 89 | onException(PARSE_ERROR, ""); 90 | e.printStackTrace(); 91 | } else { 92 | if (e != null) { 93 | onError(e.toString()); 94 | } else { 95 | onError("未知错误"); 96 | } 97 | } 98 | } 99 | 100 | private void onException(int unknownError, String message) { 101 | switch (unknownError) { 102 | case CONNECT_ERROR: 103 | onError("连接错误"); 104 | break; 105 | case CONNECT_TIMEOUT: 106 | onError("连接超时"); 107 | break; 108 | case BAD_NETWORK: 109 | onError("网络超时"); 110 | break; 111 | case PARSE_ERROR: 112 | onError("数据解析失败"); 113 | break; 114 | //非true的所有情况 115 | case NOT_TRUE_OVER: 116 | onError(message); 117 | break; 118 | default: 119 | break; 120 | } 121 | } 122 | 123 | @Override 124 | public void onComplete() { 125 | if (view != null) { 126 | view.hideProgress(); 127 | } 128 | } 129 | 130 | public abstract void onSuccess(T o); 131 | 132 | public abstract void onError(String msg); 133 | 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/file/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.file; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Build; 7 | import android.support.v4.content.FileProvider; 8 | 9 | import com.lp.mvp_network.base.mvp.BaseView; 10 | import com.lp.mvp_network.utils.L; 11 | 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.OutputStream; 18 | import java.io.RandomAccessFile; 19 | 20 | import okhttp3.ResponseBody; 21 | 22 | /** 23 | * file util 24 | * 25 | * @author ch 26 | */ 27 | public class FileUtil { 28 | 29 | /** 30 | * @param body 31 | * @param destFileDir 下载的文件储存目录 32 | * @param destFileName 下载文件名称 33 | * @return 34 | */ 35 | public static File saveFile2(ResponseBody body, String destFileDir, String destFileName, BaseView baseView) { 36 | InputStream is = null; 37 | byte[] buf = new byte[2048]; 38 | int len = 0; 39 | FileOutputStream fos = null; 40 | // 储存下载文件的目录 41 | File dir = new File(destFileDir); 42 | if (!dir.exists()) { 43 | dir.mkdirs(); 44 | } 45 | File file = new File(dir, destFileName); 46 | try { 47 | is = body.byteStream(); 48 | int total = (int) body.contentLength(); 49 | if (total < 10000) { 50 | total = 18500000; 51 | } 52 | fos = new FileOutputStream(file); 53 | int sum = 0; 54 | while ((len = is.read(buf)) != -1) { 55 | fos.write(buf, 0, len); 56 | sum += len; 57 | 58 | L.e("总长度==" + total); 59 | L.e("当前进度==" + sum); 60 | int progress = (int) (sum * 1.0f / total * 100); 61 | } 62 | fos.flush(); 63 | // 下载完成 64 | return file; 65 | // listener.onDownloadSuccess(file); 66 | } catch (Exception e) { 67 | // listener.onDownloadFailed(e); 68 | } finally { 69 | try { 70 | if (is != null) 71 | is.close(); 72 | } catch (IOException e) { 73 | } 74 | try { 75 | if (fos != null) 76 | fos.close(); 77 | } catch (IOException e) { 78 | } 79 | } 80 | return file; 81 | } 82 | 83 | public static File saveFile(String filePath, ResponseBody body) { 84 | InputStream inputStream = null; 85 | OutputStream outputStream = null; 86 | File file = null; 87 | try { 88 | if (filePath == null) { 89 | return null; 90 | } 91 | file = new File(filePath); 92 | if (file == null || !file.exists()) { 93 | file.createNewFile(); 94 | } 95 | 96 | 97 | long fileSize = body.contentLength(); 98 | long fileSizeDownloaded = 0; 99 | byte[] fileReader = new byte[4096]; 100 | 101 | inputStream = body.byteStream(); 102 | outputStream = new FileOutputStream(file); 103 | 104 | while (true) { 105 | int read = inputStream.read(fileReader); 106 | if (read == -1) { 107 | break; 108 | } 109 | outputStream.write(fileReader, 0, read); 110 | fileSizeDownloaded += read; 111 | 112 | } 113 | 114 | outputStream.flush(); 115 | 116 | 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } finally { 120 | if (inputStream != null) { 121 | try { 122 | inputStream.close(); 123 | } catch (IOException e) { 124 | e.printStackTrace(); 125 | } 126 | } 127 | 128 | if (outputStream != null) { 129 | try { 130 | outputStream.close(); 131 | } catch (IOException e) { 132 | e.printStackTrace(); 133 | } 134 | } 135 | } 136 | 137 | return file; 138 | } 139 | 140 | /** 141 | * @param filePath 142 | * @param start 起始位置 143 | * @param body 144 | */ 145 | public static File saveFile(String filePath, long start, ResponseBody body) { 146 | InputStream inputStream = null; 147 | RandomAccessFile raf = null; 148 | File file = null; 149 | try { 150 | file = new File(filePath); 151 | 152 | raf = new RandomAccessFile(filePath, "rw"); 153 | inputStream = body.byteStream(); 154 | byte[] fileReader = new byte[4096]; 155 | 156 | raf.seek(start); 157 | 158 | while (true) { 159 | int read = inputStream.read(fileReader); 160 | if (read == -1) { 161 | break; 162 | } 163 | raf.write(fileReader, 0, read); 164 | } 165 | 166 | 167 | } catch (FileNotFoundException e) { 168 | e.printStackTrace(); 169 | } catch (IOException e) { 170 | e.printStackTrace(); 171 | } finally { 172 | if (inputStream != null) { 173 | try { 174 | inputStream.close(); 175 | } catch (IOException e) { 176 | e.printStackTrace(); 177 | } 178 | } 179 | 180 | if (raf != null) { 181 | try { 182 | raf.close(); 183 | } catch (IOException e) { 184 | e.printStackTrace(); 185 | } 186 | } 187 | } 188 | 189 | return file; 190 | 191 | } 192 | 193 | /** 194 | * 打开apk 195 | * 196 | * @param context 197 | * @param pathName 文件路径 198 | */ 199 | public static void openFile(Context context, String pathName, String authority) { 200 | if (pathName == null) { 201 | return; 202 | } 203 | File file = new File(pathName); 204 | if (file == null || !file.exists()) { 205 | return; 206 | } 207 | Intent intent = new Intent(Intent.ACTION_VIEW); 208 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 209 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 210 | intent.setDataAndType(FileProvider.getUriForFile(context, authority, file), "application/vnd.android.package-archive"); 211 | } else { 212 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 213 | } 214 | context.startActivity(intent); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/file/ProgressRequestBody.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.file; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.lp.mvp_network.base.mvp.BaseView; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.IOException; 11 | 12 | import okhttp3.MediaType; 13 | import okhttp3.RequestBody; 14 | import okio.BufferedSink; 15 | 16 | /** 17 | * File descripition: 文件上传 18 | * 19 | * @author lp 20 | * @date 2019/8/10 21 | */ 22 | public class ProgressRequestBody extends RequestBody { 23 | private File mFile; 24 | private String mPath; 25 | private String mMediaType; 26 | private BaseView mListener; 27 | 28 | private int mEachBufferSize = 1024; 29 | 30 | public ProgressRequestBody(final File file, String mediaType, BaseView baseView) { 31 | mFile = file; 32 | mMediaType = mediaType; 33 | mListener = baseView; 34 | } 35 | 36 | public ProgressRequestBody(final File file, String mediaType, int eachBufferSize, BaseView baseView) { 37 | mFile = file; 38 | mMediaType = mediaType; 39 | mEachBufferSize = eachBufferSize; 40 | mListener = baseView; 41 | } 42 | 43 | @Override 44 | public MediaType contentType() { 45 | // i want to upload only images 46 | return MediaType.parse(mMediaType); 47 | } 48 | 49 | @Override 50 | public void writeTo(BufferedSink sink) throws IOException { 51 | long fileLength = mFile.length(); 52 | byte[] buffer = new byte[mEachBufferSize]; 53 | FileInputStream in = new FileInputStream(mFile); 54 | long uploaded = 0; 55 | 56 | try { 57 | int read; 58 | Handler handler = new Handler(Looper.getMainLooper()); 59 | while ((read = in.read(buffer)) != -1) { 60 | // update progress on UI thread 61 | handler.post(new ProgressUpdater(uploaded, fileLength)); 62 | uploaded += read; 63 | sink.write(buffer, 0, read); 64 | 65 | } 66 | } finally { 67 | in.close(); 68 | } 69 | } 70 | 71 | private class ProgressUpdater implements Runnable { 72 | private long mUploaded; 73 | private long mTotal; 74 | 75 | public ProgressUpdater(long uploaded, long total) { 76 | mUploaded = uploaded; 77 | mTotal = total; 78 | } 79 | 80 | @Override 81 | public void run() { 82 | mListener.onProgress((int) (100 * mUploaded / mTotal)); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/file/ProgressResponseBody.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.file; 2 | 3 | import java.io.IOException; 4 | 5 | import io.reactivex.annotations.Nullable; 6 | import okhttp3.MediaType; 7 | import okhttp3.ResponseBody; 8 | import okio.Buffer; 9 | import okio.BufferedSource; 10 | import okio.ForwardingSource; 11 | import okio.Okio; 12 | import okio.Source; 13 | 14 | /** 15 | * File descripition: 文件下载 16 | * 17 | * @author lp 18 | * @date 2019/8/10 19 | */ 20 | public class ProgressResponseBody extends ResponseBody { 21 | private ResponseBody responseBody; 22 | private BufferedSource bufferedSource; 23 | private ProgressListener progressListener; 24 | 25 | public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { 26 | this.responseBody = responseBody; 27 | this.progressListener = progressListener; 28 | } 29 | 30 | 31 | @Nullable 32 | @Override 33 | public MediaType contentType() { 34 | return responseBody.contentType(); 35 | } 36 | 37 | @Override 38 | public long contentLength() { 39 | return responseBody.contentLength(); 40 | } 41 | 42 | @Override 43 | public BufferedSource source() { 44 | if (bufferedSource == null) { 45 | bufferedSource = Okio.buffer(source(responseBody.source())); 46 | } 47 | return bufferedSource; 48 | } 49 | 50 | private Source source(Source source) { 51 | return new ForwardingSource(source) { 52 | long totalBytesRead = 0L; 53 | 54 | @Override 55 | public long read(Buffer sink, long byteCount) throws IOException { 56 | long bytesRead = super.read(sink, byteCount); 57 | totalBytesRead += bytesRead; 58 | progressListener.onProgress(responseBody.contentLength(), totalBytesRead); 59 | return bytesRead; 60 | } 61 | }; 62 | } 63 | 64 | public interface ProgressListener { 65 | void onProgress(long totalSize, long downSize); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/gson/DoubleDefaultAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.gson; 2 | 3 | import com.google.gson.JsonDeserializationContext; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonPrimitive; 8 | import com.google.gson.JsonSerializationContext; 9 | import com.google.gson.JsonSerializer; 10 | import com.google.gson.JsonSyntaxException; 11 | 12 | import java.lang.reflect.Type; 13 | 14 | /** 15 | * File descripition: 对返回值为空处理 16 | * 17 | * @author Administrator 18 | * @date 2018/5/21 19 | */ 20 | 21 | public class DoubleDefaultAdapter implements JsonSerializer, JsonDeserializer { 22 | @Override 23 | public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 24 | try { 25 | if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为double类型,如果后台返回""或者null,则返回0.00 26 | return 0.00; 27 | } 28 | } catch (Exception ignore) { 29 | } 30 | try { 31 | return json.getAsDouble(); 32 | } catch (NumberFormatException e) { 33 | throw new JsonSyntaxException(e); 34 | } 35 | } 36 | 37 | @Override 38 | public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) { 39 | return new JsonPrimitive(src); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/gson/IntegerDefaultAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.gson; 2 | 3 | import com.google.gson.JsonDeserializationContext; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonPrimitive; 8 | import com.google.gson.JsonSerializationContext; 9 | import com.google.gson.JsonSerializer; 10 | import com.google.gson.JsonSyntaxException; 11 | 12 | import java.lang.reflect.Type; 13 | 14 | /** 15 | * File descripition:double=> 16 | * 17 | * @author Administrator 对返回值为空处理 18 | * @date 2018/5/21 19 | */ 20 | 21 | public class IntegerDefaultAdapter implements JsonSerializer, JsonDeserializer { 22 | @Override 23 | public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 24 | throws JsonParseException { 25 | try { 26 | if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为int类型,如果后台返回""或者null,则返回0 27 | return 0; 28 | } 29 | } catch (Exception ignore) { 30 | } 31 | try { 32 | return json.getAsInt(); 33 | } catch (NumberFormatException e) { 34 | throw new JsonSyntaxException(e); 35 | } 36 | } 37 | 38 | @Override 39 | public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) { 40 | return new JsonPrimitive(src); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/gson/LongDefaultAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.gson; 2 | 3 | import com.google.gson.JsonDeserializationContext; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonPrimitive; 8 | import com.google.gson.JsonSerializationContext; 9 | import com.google.gson.JsonSerializer; 10 | import com.google.gson.JsonSyntaxException; 11 | 12 | import java.lang.reflect.Type; 13 | 14 | /** 15 | * File descripition:long=> 16 | * 17 | * @author Administrator 对返回值为空处理 18 | * @date 2018/5/21 19 | */ 20 | 21 | public class LongDefaultAdapter implements JsonSerializer, JsonDeserializer { 22 | @Override 23 | public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 24 | throws JsonParseException { 25 | try { 26 | if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为long类型,如果后台返回""或者null,则返回0 27 | return 0l; 28 | } 29 | } catch (Exception ignore) { 30 | } 31 | try { 32 | return json.getAsLong(); 33 | } catch (NumberFormatException e) { 34 | throw new JsonSyntaxException(e); 35 | } 36 | } 37 | 38 | @Override 39 | public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) { 40 | return new JsonPrimitive(src); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/gson/StringNullAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.gson; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonToken; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * File descripition: 自定义TypeAdapter ,null对象将被解析成空字符串 12 | * 13 | * @author lp 14 | * @date 2019/1/21 15 | */ 16 | 17 | public class StringNullAdapter extends TypeAdapter { 18 | @Override 19 | public String read(JsonReader reader) throws IOException { 20 | if (reader.peek() == JsonToken.NULL) { 21 | reader.nextNull(); 22 | return "";//原先是返回Null,这里改为返回空字符串 23 | } 24 | 25 | String jsonStr = reader.nextString(); 26 | if(jsonStr.equals("null")) { 27 | return ""; 28 | }else { 29 | return jsonStr; 30 | } 31 | } 32 | 33 | @Override 34 | public void write(JsonWriter writer, String value) throws IOException { 35 | if (value == null) { 36 | writer.nullValue(); 37 | return; 38 | } 39 | writer.value(value); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * File descripition: mode基类 7 | * 8 | * @author lp 9 | * @date 2018/6/19 10 | */ 11 | public class BaseModel implements Serializable { 12 | private String reason; 13 | private int error_code; 14 | private T result; 15 | 16 | public BaseModel(String reason, int error_code) { 17 | this.reason = reason; 18 | this.error_code = error_code; 19 | } 20 | 21 | public String getReason() { 22 | return reason; 23 | } 24 | 25 | public void setReason(String reason) { 26 | this.reason = reason; 27 | } 28 | 29 | public int getError_code() { 30 | return error_code; 31 | } 32 | 33 | public void setError_code(int error_code) { 34 | this.error_code = error_code; 35 | } 36 | 37 | public T getResult() { 38 | return result; 39 | } 40 | 41 | public void setResult(T result) { 42 | this.result = result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BaseObserver.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | import com.google.gson.JsonParseException; 4 | import com.lp.mvp_network.base.BaseContent; 5 | 6 | import org.json.JSONException; 7 | 8 | import java.io.InterruptedIOException; 9 | import java.net.ConnectException; 10 | import java.net.UnknownHostException; 11 | import java.text.ParseException; 12 | 13 | import io.reactivex.observers.DisposableObserver; 14 | import retrofit2.HttpException; 15 | 16 | /** 17 | * File descripition: 数据处理基类 18 | * 19 | * @author lp 20 | * @date 2018/6/19 21 | */ 22 | 23 | public abstract class BaseObserver extends DisposableObserver> { 24 | protected BaseView view; 25 | /** 26 | * 网络连接失败 无网 27 | */ 28 | public static final int NETWORK_ERROR = 100000; 29 | /** 30 | * 解析数据失败 31 | */ 32 | public static final int PARSE_ERROR = 1008; 33 | /** 34 | * 网络问题 35 | */ 36 | public static final int BAD_NETWORK = 1007; 37 | /** 38 | * 连接错误 39 | */ 40 | public static final int CONNECT_ERROR = 1006; 41 | /** 42 | * 连接超时 43 | */ 44 | public static final int CONNECT_TIMEOUT = 1005; 45 | 46 | /** 47 | * 其他所有情况 48 | */ 49 | public static final int NOT_TRUE_OVER = 1004; 50 | 51 | 52 | public BaseObserver(BaseView view) { 53 | this.view = view; 54 | } 55 | public BaseObserver() { 56 | } 57 | 58 | @Override 59 | protected void onStart() { 60 | if (view != null) { 61 | view.showLoading(); 62 | } 63 | } 64 | 65 | @Override 66 | public void onNext(BaseModel o) { 67 | // T t = o.getData(); 68 | try { 69 | if (view != null) { 70 | view.hideLoading(); 71 | } 72 | if (o.getError_code() == BaseContent.basecode || o.getError_code() == 1) { 73 | onSuccess(o); 74 | } else { 75 | if (view != null) { 76 | view.onErrorCode(o); 77 | } 78 | //非 true的所有情况 79 | onException(PARSE_ERROR, o.getReason()); 80 | } 81 | } catch (Exception e) { 82 | e.printStackTrace(); 83 | onError(e.toString()); 84 | } 85 | } 86 | 87 | @Override 88 | public void onError(Throwable e) { 89 | if (view != null) { 90 | view.hideLoading(); 91 | } 92 | if (e instanceof HttpException) { 93 | // HTTP错误 94 | onException(BAD_NETWORK, ""); 95 | } else if (e instanceof ConnectException 96 | || e instanceof UnknownHostException) { 97 | // 连接错误 98 | onException(CONNECT_ERROR, ""); 99 | } else if (e instanceof InterruptedIOException) { 100 | // 连接超时 101 | onException(CONNECT_TIMEOUT, ""); 102 | } else if (e instanceof JsonParseException 103 | || e instanceof JSONException 104 | || e instanceof ParseException) { 105 | // 解析错误 106 | onException(PARSE_ERROR, ""); 107 | e.printStackTrace(); 108 | } else { 109 | if (e != null) { 110 | onError(e.toString()); 111 | } else { 112 | onError("未知错误"); 113 | } 114 | } 115 | } 116 | 117 | 118 | private void onException(int unknownError, String message) { 119 | switch (unknownError) { 120 | case CONNECT_ERROR: 121 | onError("连接错误"); 122 | break; 123 | case CONNECT_TIMEOUT: 124 | onError("连接超时"); 125 | break; 126 | case BAD_NETWORK: 127 | onError("网络超时"); 128 | break; 129 | case PARSE_ERROR: 130 | onError("数据解析失败"); 131 | break; 132 | //非true的所有情况 133 | case NOT_TRUE_OVER: 134 | onError(message); 135 | break; 136 | default: 137 | break; 138 | } 139 | } 140 | 141 | //消失写到这 有一定的延迟 对dialog显示有影响 142 | @Override 143 | public void onComplete() { 144 | /* if (view != null) { 145 | view.hideLoading(); 146 | }*/ 147 | } 148 | 149 | public abstract void onSuccess(BaseModel o); 150 | 151 | public abstract void onError(String msg); 152 | } 153 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BaseObserverFlowable.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | 4 | import com.google.gson.JsonParseException; 5 | import com.lp.mvp_network.base.BaseContent; 6 | import com.lp.mvp_network.utils.NetWorkUtils; 7 | 8 | import org.json.JSONException; 9 | 10 | import java.io.InterruptedIOException; 11 | import java.net.ConnectException; 12 | import java.net.UnknownHostException; 13 | import java.text.ParseException; 14 | 15 | import io.reactivex.observers.DisposableObserver; 16 | import io.reactivex.subscribers.DisposableSubscriber; 17 | import retrofit2.HttpException; 18 | 19 | /** 20 | * File descripition: 数据处理基类 21 | * 22 | * @author lp 23 | * @date 2018/6/19 24 | */ 25 | 26 | public abstract class BaseObserverFlowable extends DisposableSubscriber> { 27 | protected BaseView view; 28 | /** 29 | * 网络连接失败 无网 30 | */ 31 | public static final int NETWORK_ERROR = 100000; 32 | /** 33 | * 解析数据失败 34 | */ 35 | public static final int PARSE_ERROR = 1008; 36 | /** 37 | * 网络问题 38 | */ 39 | public static final int BAD_NETWORK = 1007; 40 | /** 41 | * 连接错误 42 | */ 43 | public static final int CONNECT_ERROR = 1006; 44 | /** 45 | * 连接超时 46 | */ 47 | public static final int CONNECT_TIMEOUT = 1005; 48 | 49 | /** 50 | * 其他所有情况 51 | */ 52 | public static final int NOT_TRUE_OVER = 1004; 53 | 54 | 55 | public BaseObserverFlowable(BaseView view) { 56 | this.view = view; 57 | } 58 | 59 | @Override 60 | protected void onStart() { 61 | if (view != null) { 62 | view.showLoading(); 63 | } 64 | } 65 | 66 | @Override 67 | public void onNext(BaseModel o) { 68 | // T t = o.getData(); 69 | try { 70 | if (view != null) { 71 | view.hideLoading(); 72 | } 73 | if (o.getError_code() == BaseContent.basecode) { 74 | onSuccess(o); 75 | } else { 76 | view.onErrorCode(o); 77 | //非 true的所有情况 78 | onException(PARSE_ERROR, o.getReason()); 79 | } 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | onError(e.toString()); 83 | } 84 | } 85 | 86 | @Override 87 | public void onError(Throwable e) { 88 | if (view != null) { 89 | view.hideLoading(); 90 | } 91 | if (e instanceof HttpException) { 92 | // HTTP错误 93 | onException(BAD_NETWORK, ""); 94 | } else if (e instanceof ConnectException 95 | || e instanceof UnknownHostException) { 96 | // 连接错误 97 | onException(CONNECT_ERROR, ""); 98 | } else if (e instanceof InterruptedIOException) { 99 | // 连接超时 100 | onException(CONNECT_TIMEOUT, ""); 101 | } else if (e instanceof JsonParseException 102 | || e instanceof JSONException 103 | || e instanceof ParseException) { 104 | // 解析错误 105 | onException(PARSE_ERROR, ""); 106 | e.printStackTrace(); 107 | } else { 108 | if (e != null) { 109 | onError(e.toString()); 110 | } else { 111 | onError("未知错误"); 112 | } 113 | } 114 | } 115 | 116 | 117 | private void onException(int unknownError, String message) { 118 | switch (unknownError) { 119 | case CONNECT_ERROR: 120 | onError("连接错误"); 121 | break; 122 | case CONNECT_TIMEOUT: 123 | onError("连接超时"); 124 | break; 125 | case BAD_NETWORK: 126 | onError("网络超时"); 127 | break; 128 | case PARSE_ERROR: 129 | onError("数据解析失败"); 130 | break; 131 | //非true的所有情况 132 | case NOT_TRUE_OVER: 133 | onError(message); 134 | break; 135 | default: 136 | break; 137 | } 138 | } 139 | 140 | //消失写到这 有一定的延迟 对dialog显示有影响 141 | @Override 142 | public void onComplete() { 143 | /* if (view != null) { 144 | view.hideLoading(); 145 | }*/ 146 | } 147 | 148 | public abstract void onSuccess(BaseModel o); 149 | 150 | public abstract void onError(String msg); 151 | } 152 | 153 | 154 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | 4 | import com.lp.mvp_network.api.ApiRetrofit; 5 | import com.lp.mvp_network.api.ApiServer; 6 | import com.lp.mvp_network.base.file.FileObserver; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.android.schedulers.AndroidSchedulers; 10 | import io.reactivex.disposables.CompositeDisposable; 11 | import io.reactivex.schedulers.Schedulers; 12 | /** 13 | * File descripition: 创建Presenter基类 14 | * 15 | * @author lp 16 | * @date 2018/6/19 17 | */ 18 | public class BasePresenter { 19 | private CompositeDisposable compositeDisposable; 20 | public V baseView; 21 | protected ApiServer apiServer = ApiRetrofit.getInstance().getApiService(); 22 | 23 | public BasePresenter(V baseView) { 24 | this.baseView = baseView; 25 | } 26 | /** 27 | * 解除绑定 28 | */ 29 | public void detachView() { 30 | baseView = null; 31 | removeDisposable(); 32 | } 33 | /** 34 | * 返回 view 35 | * 36 | * @return 37 | */ 38 | public V getBaseView() { 39 | return baseView; 40 | } 41 | 42 | public void addDisposable(Observable observable, BaseObserver observer) { 43 | if (compositeDisposable == null) { 44 | compositeDisposable = new CompositeDisposable(); 45 | } 46 | compositeDisposable.add(observable.subscribeOn(Schedulers.io()) 47 | .observeOn(AndroidSchedulers.mainThread()) 48 | .subscribeWith(observer)); 49 | } 50 | public void addFileDisposable(Observable observable, FileObserver observer) { 51 | if (compositeDisposable == null) { 52 | compositeDisposable = new CompositeDisposable(); 53 | } 54 | compositeDisposable.add(observable.subscribeOn(Schedulers.io()) 55 | .observeOn(AndroidSchedulers.mainThread()) 56 | .subscribeWith(observer)); 57 | } 58 | 59 | public void removeDisposable() { 60 | if (compositeDisposable != null) { 61 | compositeDisposable.dispose(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BasePresenterFlowable.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | 4 | import com.lp.mvp_network.api.ApiRetrofit; 5 | import com.lp.mvp_network.api.ApiServer; 6 | 7 | import io.reactivex.Observable; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | import io.reactivex.disposables.CompositeDisposable; 10 | import io.reactivex.schedulers.Schedulers; 11 | 12 | /** 13 | * File descripition: 创建Presenter基类 14 | * 15 | * @author lp 16 | * @date 2018/6/19 17 | */ 18 | public class BasePresenterFlowable { 19 | private CompositeDisposable compositeDisposable; 20 | public V baseView; 21 | protected ApiServer apiServer = ApiRetrofit.getInstance().getApiService(); 22 | 23 | public BasePresenterFlowable(V baseView) { 24 | this.baseView = baseView; 25 | } 26 | /** 27 | * 解除绑定 28 | */ 29 | public void detachView() { 30 | baseView = null; 31 | removeDisposable(); 32 | } 33 | /** 34 | * 返回 view 35 | * 36 | * @return 37 | */ 38 | public V getBaseView() { 39 | return baseView; 40 | } 41 | 42 | public void addDisposable(Observable observable, BaseObserverFlowable observer) { 43 | if (compositeDisposable == null) { 44 | compositeDisposable = new CompositeDisposable(); 45 | } 46 | /* compositeDisposable.add(observable.subscribeOn(Schedulers.io()) 47 | .observeOn(AndroidSchedulers.mainThread()) 48 | .subscribeWith(observer));*/ 49 | } 50 | 51 | public void removeDisposable() { 52 | if (compositeDisposable != null) { 53 | compositeDisposable.dispose(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/base/mvp/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.base.mvp; 2 | 3 | /** 4 | * File descripition: 基本回调 可自定义添加所需回调 5 | * 6 | * @author lp 7 | * @date 2018/6/19 8 | */ 9 | 10 | public interface BaseView { 11 | /** 12 | * 显示dialog 13 | */ 14 | void showLoading(); 15 | 16 | /** 17 | * 隐藏 dialog 18 | */ 19 | 20 | void hideLoading(); 21 | 22 | /** 23 | * 显示错误信息 24 | * 25 | * @param msg 26 | */ 27 | void showError(String msg); 28 | 29 | /** 30 | * 错误码 31 | */ 32 | void onErrorCode(BaseModel model); 33 | 34 | /** 35 | * 进度条显示 36 | */ 37 | void showProgress(); 38 | 39 | /** 40 | * 进度条隐藏 41 | */ 42 | void hideProgress(); 43 | 44 | /** 45 | * 文件下载进度监听 46 | * 47 | * @param progress 48 | */ 49 | void onProgress(int progress); 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.MotionEvent; 8 | import android.view.View; 9 | import android.widget.EditText; 10 | 11 | import com.hjq.toast.ToastUtils; 12 | import com.lp.mvp_network.second2demo.mvp.BaseModel; 13 | import com.lp.mvp_network.second2demo.mvp.BasePresenter; 14 | import com.lp.mvp_network.second2demo.mvp.BaseView; 15 | import com.lp.mvp_network.utils.KeyBoardUtils; 16 | import com.lp.mvp_network.utils.StatusBarUtil; 17 | import com.lp.mvp_network.view.LoadingDialog; 18 | 19 | /** 20 | * File descripition: activity基类 21 | *

22 | * 23 | * @author lp 24 | * @date 2018/5/16 25 | */ 26 | public abstract class BaseActivity

extends AppCompatActivity implements BaseView { 27 | protected final String TAG = this.getClass().getSimpleName(); 28 | public Context mContext; 29 | protected P mPresenter; 30 | 31 | protected abstract P createPresenter(); 32 | 33 | private LoadingDialog loadingDialog; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | mContext = this; 39 | setContentView(getLayoutId()); 40 | mPresenter = createPresenter(); 41 | setStatusBar(); 42 | 43 | this.initData(); 44 | } 45 | 46 | /** 47 | * 获取布局ID 48 | * 49 | * @return 50 | */ 51 | protected abstract int getLayoutId(); 52 | 53 | /** 54 | * 数据初始化操作 55 | */ 56 | protected abstract void initData(); 57 | 58 | /** 59 | * 此处设置沉浸式地方 60 | */ 61 | protected void setStatusBar() { 62 | StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null); 63 | } 64 | 65 | /** 66 | * 封装toast方法(自行去实现) 67 | * 68 | * @param str 69 | */ 70 | public void showToast(String str) { 71 | ToastUtils.show(str); 72 | } 73 | 74 | public void showLongToast(String str) { 75 | ToastUtils.show(str); 76 | } 77 | 78 | @Override 79 | public void showError(String msg) { 80 | showToast(msg); 81 | } 82 | 83 | /** 84 | * 返回所有状态 除去指定的值 可设置所有(根据需求) 85 | * 86 | * @param model 87 | */ 88 | @Override 89 | public void onErrorCode(BaseModel model) { 90 | if (!model.getSuccess()) { 91 | //处理些后续逻辑 如果某个页面不想实现 子类重写这个方法 将super去掉 自定义方法 92 | // App.put(); 93 | // startActivity(LoginActivity.class); 94 | } 95 | } 96 | 97 | @Override 98 | public void showLoading() { 99 | showLoadingDialog(); 100 | } 101 | 102 | @Override 103 | public void hideLoading() { 104 | dissMissDialog(); 105 | } 106 | 107 | public void showLoadingDialog() { 108 | showLoadingDialog("加载中..."); 109 | } 110 | 111 | /** 112 | * 加载 黑框... 113 | */ 114 | public void showLoadingDialog(String msg) { 115 | if (loadingDialog == null) { 116 | loadingDialog = new LoadingDialog(this); 117 | } 118 | loadingDialog.setMessage(msg); 119 | if (!loadingDialog.isShowing()) { 120 | loadingDialog.show(); 121 | } 122 | } 123 | 124 | /** 125 | * 消失 黑框... 126 | */ 127 | public void dissMissDialog() { 128 | if (loadingDialog != null) { 129 | loadingDialog.dismiss(); 130 | } 131 | } 132 | 133 | @Override 134 | protected void onDestroy() { 135 | super.onDestroy(); 136 | if (mPresenter != null) { 137 | mPresenter.detachView(); 138 | } 139 | if (loadingDialog != null) { 140 | loadingDialog.dismiss(); 141 | } 142 | if (mPresenter != null) { 143 | mPresenter.detachView(); 144 | } 145 | } 146 | 147 | 148 | /** 149 | * [页面跳转] 150 | * 151 | * @param clz 152 | */ 153 | public void startActivity(Class clz) { 154 | startActivity(clz, null); 155 | } 156 | 157 | 158 | /** 159 | * [携带数据的页面跳转] 160 | * 161 | * @param clz 162 | * @param bundle 163 | */ 164 | public void startActivity(Class clz, Bundle bundle) { 165 | Intent intent = new Intent(); 166 | intent.setClass(this, clz); 167 | if (bundle != null) { 168 | intent.putExtras(bundle); 169 | } 170 | startActivity(intent); 171 | } 172 | 173 | /** 174 | * [含有Bundle通过Class打开编辑界面] 175 | * 176 | * @param cls 177 | * @param bundle 178 | * @param requestCode 179 | */ 180 | public void startActivityForResult(Class cls, Bundle bundle, int requestCode) { 181 | Intent intent = new Intent(); 182 | intent.setClass(this, cls); 183 | if (bundle != null) { 184 | intent.putExtras(bundle); 185 | } 186 | startActivityForResult(intent, requestCode); 187 | } 188 | 189 | /** 190 | * 以下是关于软键盘的处理 191 | */ 192 | 193 | /** 194 | * 清除editText的焦点 195 | * 196 | * @param v 焦点所在View 197 | * @param ids 输入框 198 | */ 199 | public void clearViewFocus(View v, int... ids) { 200 | if (null != v && null != ids && ids.length > 0) { 201 | for (int id : ids) { 202 | if (v.getId() == id) { 203 | v.clearFocus(); 204 | break; 205 | } 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * 隐藏键盘 212 | * 213 | * @param v 焦点所在View 214 | * @param ids 输入框 215 | * @return true代表焦点在edit上 216 | */ 217 | public boolean isFocusEditText(View v, int... ids) { 218 | if (v instanceof EditText) { 219 | EditText et = (EditText) v; 220 | for (int id : ids) { 221 | if (et.getId() == id) { 222 | return true; 223 | } 224 | } 225 | } 226 | return false; 227 | } 228 | 229 | //是否触摸在指定view上面,对某个控件过滤 230 | public boolean isTouchView(View[] views, MotionEvent ev) { 231 | if (views == null || views.length == 0) { 232 | return false; 233 | } 234 | int[] location = new int[2]; 235 | for (View view : views) { 236 | view.getLocationOnScreen(location); 237 | int x = location[0]; 238 | int y = location[1]; 239 | if (ev.getX() > x && ev.getX() < (x + view.getWidth()) 240 | && ev.getY() > y && ev.getY() < (y + view.getHeight())) { 241 | return true; 242 | } 243 | } 244 | return false; 245 | } 246 | 247 | @Override 248 | public boolean dispatchTouchEvent(MotionEvent ev) { 249 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 250 | if (isTouchView(filterViewByIds(), ev)) { 251 | return super.dispatchTouchEvent(ev); 252 | } 253 | if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) { 254 | return super.dispatchTouchEvent(ev); 255 | } 256 | View v = getCurrentFocus(); 257 | if (isFocusEditText(v, hideSoftByEditViewIds())) { 258 | KeyBoardUtils.hideInputForce(this); 259 | clearViewFocus(v, hideSoftByEditViewIds()); 260 | } 261 | } 262 | return super.dispatchTouchEvent(ev); 263 | } 264 | 265 | 266 | /** 267 | * 传入EditText的Id 268 | * 没有传入的EditText不做处理 269 | * 270 | * @return id 数组 271 | */ 272 | public int[] hideSoftByEditViewIds() { 273 | return null; 274 | } 275 | 276 | /** 277 | * 传入要过滤的View 278 | * 过滤之后点击将不会有隐藏软键盘的操作 279 | * 280 | * @return id 数组 281 | */ 282 | public View[] filterViewByIds() { 283 | return null; 284 | } 285 | 286 | 287 | /*实现案例===============================================================================================*/ 288 | /* 289 | 290 | @Override 291 | public int[] hideSoftByEditViewIds() { 292 | int[] ids = {R.id.et_company_name, R.id.et_address}; 293 | return ids; 294 | } 295 | 296 | @Override 297 | public View[] filterViewByIds() { 298 | View[] views = {mEtCompanyName, mEtAddress}; 299 | return views; 300 | } 301 | 302 | */ 303 | } 304 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.lp.mvp_network.base.mvp.BaseModel; 13 | import com.lp.mvp_network.base.mvp.BasePresenter; 14 | import com.lp.mvp_network.base.mvp.BaseView; 15 | 16 | 17 | /** 18 | * File descripition: ftagment 基类 19 | * 20 | * @author lp 21 | * @date 2018/6/19 22 | */ 23 | 24 | public abstract class BaseFragment

extends Fragment implements BaseView { 25 | public View view; 26 | 27 | public Context mContext; 28 | protected P mPresenter; 29 | 30 | protected abstract P createPresenter(); 31 | 32 | @Nullable 33 | @Override 34 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 35 | view = inflater.inflate(getLayoutId(), container, false); 36 | 37 | mContext = getActivity(); 38 | mPresenter = createPresenter(); 39 | 40 | this.initToolbar(savedInstanceState); 41 | this.initData(); 42 | 43 | return view; 44 | } 45 | 46 | /** 47 | * 获取布局ID 48 | * 49 | * @return 50 | */ 51 | protected abstract int getLayoutId(); 52 | 53 | /** 54 | * 处理顶部title 55 | * 56 | * @param savedInstanceState 57 | */ 58 | protected abstract void initToolbar(Bundle savedInstanceState); 59 | 60 | 61 | /** 62 | * 数据初始化操作 63 | */ 64 | protected abstract void initData(); 65 | 66 | public void showToast(String str) { 67 | } 68 | 69 | public void showLongToast(String str) { 70 | } 71 | 72 | @Override 73 | public void showError(String msg) { 74 | showToast(msg); 75 | } 76 | 77 | @Override 78 | public void onErrorCode(BaseModel model) { 79 | } 80 | 81 | @Override 82 | public void showLoading() { 83 | } 84 | 85 | @Override 86 | public void hideLoading() { 87 | } 88 | 89 | 90 | @Override 91 | public void onDestroy() { 92 | super.onDestroy(); 93 | this.view = null; 94 | if (mPresenter != null) { 95 | mPresenter.detachView(); 96 | } 97 | } 98 | 99 | @Override 100 | public void onDestroyView() { 101 | super.onDestroyView(); 102 | } 103 | 104 | /** 105 | * [页面跳转] 106 | * 107 | * @param clz 108 | */ 109 | public void startActivity(Class clz) { 110 | startActivity(clz, null); 111 | } 112 | 113 | 114 | /** 115 | * [携带数据的页面跳转] 116 | * 117 | * @param clz 118 | * @param bundle 119 | */ 120 | public void startActivity(Class clz, Bundle bundle) { 121 | Intent intent = new Intent(); 122 | intent.setClass(getActivity(), clz); 123 | if (bundle != null) { 124 | intent.putExtras(bundle); 125 | } 126 | startActivity(intent); 127 | } 128 | 129 | /** 130 | * [含有Bundle通过Class打开编辑界面] 131 | * 132 | * @param cls 133 | * @param bundle 134 | * @param requestCode 135 | */ 136 | public void startActivityForResult(Class cls, Bundle bundle, 137 | int requestCode) { 138 | Intent intent = new Intent(); 139 | intent.setClass(getActivity(), cls); 140 | if (bundle != null) { 141 | intent.putExtras(bundle); 142 | } 143 | startActivityForResult(intent, requestCode); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/activity/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.activity; 2 | 3 | import android.util.Log; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.lp.mvp_network.R; 8 | import com.lp.mvp_network.second2demo.BaseActivity; 9 | import com.lp.mvp_network.second2demo.api.ApiRetrofit; 10 | import com.lp.mvp_network.second2demo.bean.Bean1; 11 | import com.lp.mvp_network.second2demo.bean.Bean2; 12 | import com.lp.mvp_network.second2demo.bean.Bean3; 13 | import com.lp.mvp_network.second2demo.mvp.BaseModel; 14 | 15 | import java.util.HashMap; 16 | import java.util.List; 17 | 18 | import io.reactivex.android.schedulers.AndroidSchedulers; 19 | import io.reactivex.functions.Consumer; 20 | import io.reactivex.functions.Function; 21 | import io.reactivex.schedulers.Schedulers; 22 | 23 | public class SecondActivity extends BaseActivity implements SecondView, View.OnClickListener { 24 | private TextView mTvText; 25 | 26 | 27 | @Override 28 | public void onErrorCode(BaseModel model) { 29 | // super.onErrorCode(model); 30 | //我要自定义 31 | //实现自己的逻辑 32 | Log.e("onErrorCode", "onErrorCode"); 33 | } 34 | 35 | @Override 36 | public void showError(String msg) { 37 | if (msg.contains("重新登录")) { 38 | //处理自己定制逻辑 39 | } else { 40 | super.showError(msg); 41 | } 42 | 43 | Log.e("showError", "showError"); 44 | 45 | } 46 | 47 | @Override 48 | protected SecondPresenter createPresenter() { 49 | return new SecondPresenter(this); 50 | } 51 | 52 | @Override 53 | protected int getLayoutId() { 54 | return R.layout.activity_main; 55 | } 56 | 57 | @Override 58 | protected void initData() { 59 | findViewById(R.id.btn_first).setOnClickListener(this); 60 | TextView btn_third = findViewById(R.id.btn_third); 61 | btn_third.setVisibility(View.GONE); 62 | mTvText = findViewById(R.id.tv_text); 63 | 64 | } 65 | /* 66 | @Override 67 | public void onMainSuccess(BaseModel> o) { 68 | Log.e(o.getErrmsg(), ""); 69 | Log.e(o.getErrcode()+"", ""); 70 | mainBeans.addAll(o.getData()); 71 | Log.e("sm", mainBeans.toString()+""); 72 | mTvText.setText(o.getData().toString()); 73 | }*/ 74 | 75 | @Override 76 | public void onMainSuccess(BaseModel, Bean2, List> o) { 77 | Log.e("成功", ">>>>>>>>>>>>>>"); 78 | mTvText.setText("成功"); 79 | } 80 | 81 | @Override 82 | public void onClick(View v) { 83 | switch (v.getId()) { 84 | case R.id.btn_first: 85 | mPresenter.getManApi(); 86 | break; 87 | case R.id.btn_second: 88 | /* 89 | *//** 90 | * 俩个参数 一个是图片集合路径 一个是和后台约定的Key,如果后台不需要,随便写都行 91 | *//* 92 | List strings = new ArrayList<>(); 93 | for (int i = 0; i < 10; i++) { 94 | strings.add("tupian.lujing"); 95 | } 96 | mPresenter.expressAdd( 97 | "title", 98 | "content", 99 | RetrofitUtil.filesToMultipartBodyParts(RetrofitUtil.initImages(strings), "tupian.key")); 100 | break;*/ 101 | case R.id.btn_third: 102 | break; 103 | } 104 | 105 | 106 | } 107 | 108 | 109 | 110 | 111 | /* 112 | @Override 113 | public void onUpLoadImgSuccess(BaseModel o) { 114 | 115 | } 116 | 117 | @Override 118 | public void onUpHeadImgSuccess(BaseModel o) { 119 | 120 | } 121 | 122 | @Override 123 | public void onExpressAddSuccess(BaseModel o) { 124 | 125 | } 126 | */ 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/activity/SecondPresenter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.activity; 2 | 3 | 4 | import com.lp.mvp_network.second2demo.bean.Bean1; 5 | import com.lp.mvp_network.second2demo.bean.Bean2; 6 | import com.lp.mvp_network.second2demo.bean.Bean3; 7 | import com.lp.mvp_network.second2demo.mvp.BaseModel; 8 | import com.lp.mvp_network.second2demo.mvp.BaseObserver; 9 | import com.lp.mvp_network.second2demo.mvp.BasePresenter; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * File descripition: 15 | * 16 | * @author lp 17 | * @date 2018/6/19 18 | */ 19 | 20 | public class SecondPresenter extends BasePresenter { 21 | public SecondPresenter(SecondView baseView) { 22 | super(baseView); 23 | } 24 | 25 | /** 26 | * 写法好多种 怎么顺手怎么来 27 | */ 28 | public void getManApi() { 29 | addDisposable(apiServer.getMain2Demo("year"), new BaseObserver(baseView) { 30 | @Override 31 | public void onSuccess(BaseModel o) { 32 | baseView.onMainSuccess((BaseModel, Bean2, List>) o); 33 | } 34 | 35 | @Override 36 | public void onError(String msg) { 37 | if (baseView != null) { 38 | baseView.showError(msg); 39 | } 40 | } 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/activity/SecondView.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.activity; 2 | 3 | 4 | import com.lp.mvp_network.second2demo.bean.Bean1; 5 | import com.lp.mvp_network.second2demo.bean.Bean2; 6 | import com.lp.mvp_network.second2demo.bean.Bean3; 7 | import com.lp.mvp_network.second2demo.mvp.BaseModel; 8 | import com.lp.mvp_network.second2demo.mvp.BaseView; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * File descripition: 14 | * 15 | * @author lp 16 | * @date 2018/6/19 17 | */ 18 | 19 | public interface SecondView extends BaseView { 20 | void onMainSuccess(BaseModel, Bean2, List> o); 21 | /*void onMainSuccess(BaseModel> o); 22 | 23 | void onUpLoadImgSuccess(BaseModel o); 24 | 25 | void onUpHeadImgSuccess(BaseModel o); 26 | 27 | void onExpressAddSuccess(BaseModel o);*/ 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/api/ApiRetrofit.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.api; 2 | 3 | 4 | import com.franmontiel.persistentcookiejar.PersistentCookieJar; 5 | import com.franmontiel.persistentcookiejar.cache.SetCookieCache; 6 | import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; 7 | import com.google.gson.Gson; 8 | import com.google.gson.GsonBuilder; 9 | import com.lp.mvp_network.App; 10 | import com.lp.mvp_network.api.ApiServer; 11 | import com.lp.mvp_network.base.BaseContent; 12 | import com.lp.mvp_network.base.cookie.CookieManger; 13 | import com.lp.mvp_network.base.gson.DoubleDefaultAdapter; 14 | import com.lp.mvp_network.base.gson.IntegerDefaultAdapter; 15 | import com.lp.mvp_network.base.gson.LongDefaultAdapter; 16 | import com.lp.mvp_network.base.gson.StringNullAdapter; 17 | import com.lp.mvp_network.utils.NetWorkUtils; 18 | import com.orhanobut.logger.Logger; 19 | 20 | import java.io.IOException; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | import okhttp3.CacheControl; 24 | import okhttp3.FormBody; 25 | import okhttp3.HttpUrl; 26 | import okhttp3.Interceptor; 27 | import okhttp3.MediaType; 28 | import okhttp3.MultipartBody; 29 | import okhttp3.OkHttpClient; 30 | import okhttp3.Protocol; 31 | import okhttp3.Request; 32 | import okhttp3.RequestBody; 33 | import okhttp3.Response; 34 | import okhttp3.ResponseBody; 35 | import retrofit2.Retrofit; 36 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 37 | import retrofit2.converter.gson.GsonConverterFactory; 38 | 39 | /** 40 | * File descripition: 创建Retrofit 41 | * 42 | * @author lp 43 | * @date 2018/6/19 44 | */ 45 | 46 | public class ApiRetrofit { 47 | private String TAG = "ApiRetrofit %s"; 48 | private static ApiRetrofit apiRetrofit; 49 | private Retrofit retrofit; 50 | private ApiServer apiServer; 51 | 52 | private Gson gson; 53 | private static final int DEFAULT_TIMEOUT = 15; 54 | 55 | 56 | public ApiRetrofit() { 57 | OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); 58 | httpClientBuilder 59 | .addInterceptor(interceptor) 60 | .addInterceptor(new MockInterceptor2()) 61 | .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) 62 | .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) 63 | .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) 64 | .retryOnConnectionFailure(true);//错误重联 65 | 66 | 67 | /** 68 | * 添加cookie管理 69 | * 方法1:第三方框架 70 | */ 71 | PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), 72 | new SharedPrefsCookiePersistor(App.getContext())); 73 | httpClientBuilder.cookieJar(cookieJar); 74 | 75 | /** 76 | * 添加cookie管理 77 | * 方法2:手动封装cookie管理 78 | */ 79 | // httpClientBuilder.cookieJar(new CookieManger(App.getContext())); 80 | 81 | /** 82 | * 添加日志拦截 83 | */ 84 | httpClientBuilder.addInterceptor(interceptor); 85 | /** 86 | * 添加请求头 87 | */ 88 | httpClientBuilder.addInterceptor(new HeadUrlInterceptor()); 89 | 90 | 91 | retrofit = new Retrofit.Builder() 92 | .baseUrl(BaseContent.baseUrl) 93 | .addConverterFactory(GsonConverterFactory.create(buildGson()))//添加json转换框架(正常转换框架) 94 | // .addConverterFactory(MyGsonConverterFactory.create(buildGson()))//添加json自定义(根据需求) 95 | //支持RxJava2 96 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 97 | .client(httpClientBuilder.build()) 98 | .build(); 99 | 100 | apiServer = retrofit.create(ApiServer.class); 101 | } 102 | 103 | /** 104 | * 增加后台返回""和"null"的处理,如果后台返回格式正常,此处不需要添加 105 | * 1.int=>0 106 | * 2.double=>0.00 107 | * 3.long=>0L 108 | * 4.String=>"" 109 | * 110 | * @return 111 | */ 112 | public Gson buildGson() { 113 | if (gson == null) { 114 | gson = new GsonBuilder() 115 | .registerTypeAdapter(Integer.class, new IntegerDefaultAdapter()) 116 | .registerTypeAdapter(int.class, new IntegerDefaultAdapter()) 117 | .registerTypeAdapter(Double.class, new DoubleDefaultAdapter()) 118 | .registerTypeAdapter(double.class, new DoubleDefaultAdapter()) 119 | .registerTypeAdapter(Long.class, new LongDefaultAdapter()) 120 | .registerTypeAdapter(long.class, new LongDefaultAdapter()) 121 | .registerTypeAdapter(String.class, new StringNullAdapter()) 122 | .create(); 123 | } 124 | return gson; 125 | } 126 | 127 | public static ApiRetrofit getInstance() { 128 | if (apiRetrofit == null) { 129 | synchronized (Object.class) { 130 | if (apiRetrofit == null) { 131 | apiRetrofit = new ApiRetrofit(); 132 | } 133 | } 134 | } 135 | return apiRetrofit; 136 | } 137 | 138 | public ApiServer getApiService() { 139 | return apiServer; 140 | } 141 | 142 | /** 143 | * 请求访问quest 打印日志 144 | * response拦截器 145 | */ 146 | private Interceptor interceptor = new Interceptor() { 147 | @Override 148 | public Response intercept(Chain chain) throws IOException { 149 | Request request = chain.request(); 150 | long startTime = System.currentTimeMillis(); 151 | Response response = chain.proceed(chain.request()); 152 | long endTime = System.currentTimeMillis(); 153 | long duration = endTime - startTime; 154 | MediaType mediaType = response.body().contentType(); 155 | String content = response.body().string(); 156 | 157 | Logger.wtf(TAG, "----------Request Start----------------"); 158 | Logger.e(TAG, "| " + request.toString() + "===========" + request.headers().toString()); 159 | Logger.json(content); 160 | Logger.e(content); 161 | Logger.wtf(TAG, "----------Request End:" + duration + "毫秒----------"); 162 | 163 | return response.newBuilder() 164 | .body(ResponseBody.create(mediaType, content)) 165 | .build(); 166 | } 167 | }; 168 | 169 | /** 170 | * 添加 请求头 171 | */ 172 | public class HeadUrlInterceptor implements Interceptor { 173 | @Override 174 | public Response intercept(Chain chain) throws IOException { 175 | Request request = chain.request() 176 | .newBuilder() 177 | // .addHeader("Content-Type", "text/html; charset=UTF-8") 178 | // .addHeader("Vary", "Accept-Encoding") 179 | // .addHeader("Server", "Apache") 180 | // .addHeader("Pragma", "no-cache") 181 | // .addHeader("Cookie", "add cookies here") 182 | // .addHeader("_identity", cookie_value) 183 | .build(); 184 | return chain.proceed(request); 185 | } 186 | } 187 | 188 | /** 189 | * 获取HTTP 添加公共参数的拦截器 190 | * 暂时支持get、head请求&Post put patch的表单数据请求 191 | * 192 | * @return 193 | */ 194 | public class HttpParamsInterceptor implements Interceptor { 195 | @Override 196 | public Response intercept(Chain chain) throws IOException { 197 | Request request = chain.request(); 198 | 199 | if (request.method().equalsIgnoreCase("GET") || request.method().equalsIgnoreCase("HEAD")) { 200 | HttpUrl httpUrl = request.url().newBuilder() 201 | .addQueryParameter("version", "1.1.0") 202 | .addQueryParameter("devices", "android") 203 | .build(); 204 | request = request.newBuilder().url(httpUrl).build(); 205 | } else { 206 | RequestBody originalBody = request.body(); 207 | if (originalBody instanceof FormBody) { 208 | FormBody.Builder builder = new FormBody.Builder(); 209 | FormBody formBody = (FormBody) originalBody; 210 | for (int i = 0; i < formBody.size(); i++) { 211 | builder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i)); 212 | } 213 | FormBody newFormBody = builder 214 | .addEncoded("version", "1.1.0") 215 | .addEncoded("devices", "android") 216 | .build(); 217 | if (request.method().equalsIgnoreCase("POST")) { 218 | request = request.newBuilder().post(newFormBody).build(); 219 | } else if (request.method().equalsIgnoreCase("PATCH")) { 220 | request = request.newBuilder().patch(newFormBody).build(); 221 | } else if (request.method().equalsIgnoreCase("PUT")) { 222 | request = request.newBuilder().put(newFormBody).build(); 223 | } 224 | 225 | } else if (originalBody instanceof MultipartBody) { 226 | 227 | } 228 | 229 | } 230 | return chain.proceed(request); 231 | } 232 | } 233 | 234 | /** 235 | * 获得HTTP 缓存的拦截器 236 | * 237 | * @return 238 | */ 239 | public class HttpCacheInterceptor implements Interceptor { 240 | @Override 241 | public Response intercept(Chain chain) throws IOException { 242 | Request request = chain.request(); 243 | // 无网络时,始终使用本地Cache 244 | if (!NetWorkUtils.isConnected()) { 245 | request = request.newBuilder() 246 | .cacheControl(CacheControl.FORCE_CACHE) 247 | .build(); 248 | } 249 | Response response = chain.proceed(request); 250 | if (NetWorkUtils.isConnected()) { 251 | //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置 252 | String cacheControl = request.cacheControl().toString(); 253 | return response.newBuilder() 254 | .header("Cache-Control", cacheControl) 255 | .removeHeader("Pragma") 256 | .build(); 257 | } else { 258 | // 无网络时,设置超时为4周 259 | int maxStale = 60 * 60 * 24 * 28; 260 | return response.newBuilder() 261 | //这里的设置的是我们的没有网络的缓存时间,想设置多少就是多少。 262 | .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) 263 | .removeHeader("Pragma") 264 | .build(); 265 | } 266 | } 267 | } 268 | 269 | 270 | 271 | public class MockInterceptor implements Interceptor{ 272 | @Override 273 | public Response intercept(Chain chain) throws IOException { 274 | Gson gson = new Gson(); 275 | Response response = null; 276 | Response.Builder responseBuilder = new Response.Builder() 277 | .code(200) 278 | .message("") 279 | .request(chain.request()) 280 | .protocol(Protocol.HTTP_1_0) 281 | .addHeader("content-type", "application/json"); 282 | Request request = chain.request(); 283 | if(request.url().toString().contains(BaseContent.baseUrl)) { //拦截指定地址 284 | String responseString = "{\n" + 285 | "\t\"success\": true,\n" + 286 | "\t\"data\": [{\n" + 287 | "\t\t\"id\": 6,\n" + 288 | "\t\t\"type\": 2,\n" + 289 | "\t\t\"station_id\": 1,\n" + 290 | "\t\t\"datatime\": 1559491200000,\n" + 291 | "\t\t\"factors\": [{\n" + 292 | "\t\t\t\"id\": 11,\n" + 293 | "\t\t\t\"history_id\": 6,\n" + 294 | "\t\t\t\"station_id\": 1,\n" + 295 | "\t\t\t\"factor_id\": 6,\n" + 296 | "\t\t\t\"datatime\": 1559491200000,\n" + 297 | "\t\t\t\"value_check\": 2.225,\n" + 298 | "\t\t\t\"value_span\": 5.0,\n" + 299 | "\t\t\t\"value_standard\": 4.0,\n" + 300 | "\t\t\t\"error_difference\": -1.775,\n" + 301 | "\t\t\t\"error_percent\": -44.38,\n" + 302 | "\t\t\t\"accept\": false\n" + 303 | "\t\t}, {\n" + 304 | "\t\t\t\"id\": 12,\n" + 305 | "\t\t\t\"history_id\": 6,\n" + 306 | "\t\t\t\"station_id\": 1,\n" + 307 | "\t\t\t\"factor_id\": 7,\n" + 308 | "\t\t\t\"datatime\": 1559491200000,\n" + 309 | "\t\t\t\"value_check\": 1.595,\n" + 310 | "\t\t\t\"value_span\": 0.5,\n" + 311 | "\t\t\t\"value_standard\": 1.6,\n" + 312 | "\t\t\t\"error_difference\": -0.005,\n" + 313 | "\t\t\t\"error_percent\": -0.31,\n" + 314 | "\t\t\t\"accept\": true\n" + 315 | "\t\t}, {\n" + 316 | "\t\t\t\"id\": 13,\n" + 317 | "\t\t\t\"history_id\": 6,\n" + 318 | "\t\t\t\"station_id\": 1,\n" + 319 | "\t\t\t\"factor_id\": 8,\n" + 320 | "\t\t\t\"datatime\": 1559491200000,\n" + 321 | "\t\t\t\"value_check\": 8.104,\n" + 322 | "\t\t\t\"value_span\": 20.0,\n" + 323 | "\t\t\t\"value_standard\": 8.0,\n" + 324 | "\t\t\t\"error_difference\": 0.104,\n" + 325 | "\t\t\t\"error_percent\": 1.3,\n" + 326 | "\t\t\t\"accept\": true\n" + 327 | "\t\t},null]\n" + 328 | "\t}],\n" + 329 | "\t\"additional_data\": {\n" + 330 | "\t\t\"totalPage\": 0,\n" + 331 | "\t\t\"startPage\": 1,\n" + 332 | "\t\t\"limit\": 30,\n" + 333 | "\t\t\"total\": 0,\n" + 334 | "\t\t\"more_items_in_collection\": false\n" + 335 | "\t},\n" + 336 | "\t\"related_objects\": [{\n" + 337 | "\t\t\"id\": 6,\n" + 338 | "\t\t\"name\": \"氨氮\",\n" + 339 | "\t\t\"unit\": \"mg/L\",\n" + 340 | "\t\t\"db_field\": \"nh3n\",\n" + 341 | "\t\t\"qa_ratio\": true\n" + 342 | "\t}, {\n" + 343 | "\t\t\"id\": 7,\n" + 344 | "\t\t\"name\": \"总磷\",\n" + 345 | "\t\t\"unit\": \"mg/L\",\n" + 346 | "\t\t\"db_field\": \"tp\",\n" + 347 | "\t\t\"qa_ratio\": true\n" + 348 | "\t}, {\n" + 349 | "\t\t\"id\": 8,\n" + 350 | "\t\t\"name\": \"总氮\",\n" + 351 | "\t\t\"unit\": \"mg/L\",\n" + 352 | "\t\t\"db_field\": \"tn\",\n" + 353 | "\t\t\"qa_ratio\": true\n" + 354 | "\t}, {\n" + 355 | "\t\t\"id\": 9,\n" + 356 | "\t\t\"name\": \"CODMn\",\n" + 357 | "\t\t\"unit\": \"mg/L\",\n" + 358 | "\t\t\"db_field\": \"codmn\",\n" + 359 | "\t\t\"qa_ratio\": true\n" + 360 | "\t}],\n" + 361 | "\t\"request_time\": \"2019-06-05T16:40:14.915+08:00\"\n" + 362 | "}"; 363 | responseBuilder.body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()));//将数据设置到body中 364 | response = responseBuilder.build(); //builder模式构建response 365 | }else{ 366 | response = chain.proceed(request); 367 | } 368 | return response; 369 | } 370 | } 371 | 372 | 373 | 374 | public class MockInterceptor2 implements Interceptor{ 375 | @Override 376 | public Response intercept(Chain chain) throws IOException { 377 | Gson gson = new Gson(); 378 | Response response = null; 379 | Response.Builder responseBuilder = new Response.Builder() 380 | .code(200) 381 | .message("") 382 | .request(chain.request()) 383 | .protocol(Protocol.HTTP_1_0) 384 | .addHeader("content-type", "application/json"); 385 | Request request = chain.request(); 386 | if(request.url().toString().contains(BaseContent.baseUrl)) { //拦截指定地址 387 | String responseString = "{\n" + 388 | "\t\"success\": false,\n" + 389 | "\t\"message\": \"用户未认证或token过期,请重新登录后继续\",\n" + 390 | "\t\"request_time\": \"2019-06-10T10:15:09.132+08:00\",\n" + 391 | "\t\"error\": \"UNAUTHENTICATED\",\n" + 392 | "\t\"path\": \"/error\"\n" + 393 | "}"; 394 | responseBuilder.body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()));//将数据设置到body中 395 | response = responseBuilder.build(); //builder模式构建response 396 | }else{ 397 | response = chain.proceed(request); 398 | } 399 | return response; 400 | } 401 | } 402 | 403 | } 404 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/bean/Bean1.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * File descripition: 7 | * 8 | * @author lp 9 | * @date 2019/6/6 10 | */ 11 | 12 | public class Bean1 { 13 | 14 | /** 15 | * id : 6 16 | * type : 2 17 | * station_id : 1 18 | * datatime : 1559491200000 19 | * factors : [{"id":11,"history_id":6,"station_id":1,"factor_id":6,"datatime":1559491200000,"value_check":2.225,"value_span":5,"value_standard":4,"error_difference":-1.775,"error_percent":-44.38,"accept":false},{"id":12,"history_id":6,"station_id":1,"factor_id":7,"datatime":1559491200000,"value_check":1.595,"value_span":0.5,"value_standard":1.6,"error_difference":-0.005,"error_percent":-0.31,"accept":true},{"id":13,"history_id":6,"station_id":1,"factor_id":8,"datatime":1559491200000,"value_check":8.104,"value_span":20,"value_standard":8,"error_difference":0.104,"error_percent":1.3,"accept":true},null] 20 | */ 21 | 22 | private int id; 23 | private int type; 24 | private int station_id; 25 | private long datatime; 26 | private List factors; 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | public void setId(int id) { 33 | this.id = id; 34 | } 35 | 36 | public int getType() { 37 | return type; 38 | } 39 | 40 | public void setType(int type) { 41 | this.type = type; 42 | } 43 | 44 | public int getStation_id() { 45 | return station_id; 46 | } 47 | 48 | public void setStation_id(int station_id) { 49 | this.station_id = station_id; 50 | } 51 | 52 | public long getDatatime() { 53 | return datatime; 54 | } 55 | 56 | public void setDatatime(long datatime) { 57 | this.datatime = datatime; 58 | } 59 | 60 | public List getFactors() { 61 | return factors; 62 | } 63 | 64 | public void setFactors(List factors) { 65 | this.factors = factors; 66 | } 67 | 68 | public static class FactorsBean { 69 | /** 70 | * id : 11 71 | * history_id : 6 72 | * station_id : 1 73 | * factor_id : 6 74 | * datatime : 1559491200000 75 | * value_check : 2.225 76 | * value_span : 5.0 77 | * value_standard : 4.0 78 | * error_difference : -1.775 79 | * error_percent : -44.38 80 | * accept : false 81 | */ 82 | 83 | private int id; 84 | private int history_id; 85 | private int station_id; 86 | private int factor_id; 87 | private long datatime; 88 | private double value_check; 89 | private double value_span; 90 | private double value_standard; 91 | private double error_difference; 92 | private double error_percent; 93 | private boolean accept; 94 | 95 | public int getId() { 96 | return id; 97 | } 98 | 99 | public void setId(int id) { 100 | this.id = id; 101 | } 102 | 103 | public int getHistory_id() { 104 | return history_id; 105 | } 106 | 107 | public void setHistory_id(int history_id) { 108 | this.history_id = history_id; 109 | } 110 | 111 | public int getStation_id() { 112 | return station_id; 113 | } 114 | 115 | public void setStation_id(int station_id) { 116 | this.station_id = station_id; 117 | } 118 | 119 | public int getFactor_id() { 120 | return factor_id; 121 | } 122 | 123 | public void setFactor_id(int factor_id) { 124 | this.factor_id = factor_id; 125 | } 126 | 127 | public long getDatatime() { 128 | return datatime; 129 | } 130 | 131 | public void setDatatime(long datatime) { 132 | this.datatime = datatime; 133 | } 134 | 135 | public double getValue_check() { 136 | return value_check; 137 | } 138 | 139 | public void setValue_check(double value_check) { 140 | this.value_check = value_check; 141 | } 142 | 143 | public double getValue_span() { 144 | return value_span; 145 | } 146 | 147 | public void setValue_span(double value_span) { 148 | this.value_span = value_span; 149 | } 150 | 151 | public double getValue_standard() { 152 | return value_standard; 153 | } 154 | 155 | public void setValue_standard(double value_standard) { 156 | this.value_standard = value_standard; 157 | } 158 | 159 | public double getError_difference() { 160 | return error_difference; 161 | } 162 | 163 | public void setError_difference(double error_difference) { 164 | this.error_difference = error_difference; 165 | } 166 | 167 | public double getError_percent() { 168 | return error_percent; 169 | } 170 | 171 | public void setError_percent(double error_percent) { 172 | this.error_percent = error_percent; 173 | } 174 | 175 | public boolean isAccept() { 176 | return accept; 177 | } 178 | 179 | public void setAccept(boolean accept) { 180 | this.accept = accept; 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/bean/Bean2.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.bean; 2 | 3 | /** 4 | * File descripition: 5 | * 6 | * @author lp 7 | * @date 2019/6/6 8 | */ 9 | 10 | public class Bean2 { 11 | 12 | /** 13 | * totalPage : 0 14 | * startPage : 1 15 | * limit : 30 16 | * total : 0 17 | * more_items_in_collection : false 18 | */ 19 | 20 | private int totalPage; 21 | private int startPage; 22 | private int limit; 23 | private int total; 24 | private boolean more_items_in_collection; 25 | 26 | public int getTotalPage() { 27 | return totalPage; 28 | } 29 | 30 | public void setTotalPage(int totalPage) { 31 | this.totalPage = totalPage; 32 | } 33 | 34 | public int getStartPage() { 35 | return startPage; 36 | } 37 | 38 | public void setStartPage(int startPage) { 39 | this.startPage = startPage; 40 | } 41 | 42 | public int getLimit() { 43 | return limit; 44 | } 45 | 46 | public void setLimit(int limit) { 47 | this.limit = limit; 48 | } 49 | 50 | public int getTotal() { 51 | return total; 52 | } 53 | 54 | public void setTotal(int total) { 55 | this.total = total; 56 | } 57 | 58 | public boolean isMore_items_in_collection() { 59 | return more_items_in_collection; 60 | } 61 | 62 | public void setMore_items_in_collection(boolean more_items_in_collection) { 63 | this.more_items_in_collection = more_items_in_collection; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/bean/Bean3.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.bean; 2 | 3 | /** 4 | * File descripition: 5 | * 6 | * @author lp 7 | * @date 2019/6/6 8 | */ 9 | 10 | public class Bean3 { 11 | 12 | /** 13 | * id : 6 14 | * name : 氨氮 15 | * unit : mg/L 16 | * db_field : nh3n 17 | * qa_ratio : true 18 | */ 19 | 20 | private int id; 21 | private String name; 22 | private String unit; 23 | private String db_field; 24 | private boolean qa_ratio; 25 | 26 | public int getId() { 27 | return id; 28 | } 29 | 30 | public void setId(int id) { 31 | this.id = id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getUnit() { 43 | return unit; 44 | } 45 | 46 | public void setUnit(String unit) { 47 | this.unit = unit; 48 | } 49 | 50 | public String getDb_field() { 51 | return db_field; 52 | } 53 | 54 | public void setDb_field(String db_field) { 55 | this.db_field = db_field; 56 | } 57 | 58 | public boolean isQa_ratio() { 59 | return qa_ratio; 60 | } 61 | 62 | public void setQa_ratio(boolean qa_ratio) { 63 | this.qa_ratio = qa_ratio; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/mvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.mvp; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * File descripition: mode基类 7 | * 8 | * @author lp 9 | * @date 2018/6/19 10 | */ 11 | public class BaseModel implements Serializable { 12 | private Boolean success; 13 | private String request_time; 14 | private String message; 15 | private String error; 16 | private T1 data; 17 | private T2 additional_data; 18 | private T3 related_objects; 19 | 20 | public BaseModel(Boolean success, String request_time) { 21 | this.success = success; 22 | this.request_time = request_time; 23 | } 24 | 25 | public String getError() { 26 | return error; 27 | } 28 | 29 | public void setError(String error) { 30 | this.error = error; 31 | } 32 | 33 | public String getMessage() { 34 | return message; 35 | } 36 | 37 | public void setMessage(String message) { 38 | this.message = message; 39 | } 40 | 41 | public Boolean getSuccess() { 42 | return success; 43 | } 44 | 45 | public void setSuccess(Boolean success) { 46 | this.success = success; 47 | } 48 | 49 | public String getRequest_time() { 50 | return request_time; 51 | } 52 | 53 | public void setRequest_time(String request_time) { 54 | this.request_time = request_time; 55 | } 56 | 57 | public T1 getData() { 58 | return data; 59 | } 60 | 61 | public void setData(T1 data) { 62 | this.data = data; 63 | } 64 | 65 | public T2 getAdditional_data() { 66 | return additional_data; 67 | } 68 | 69 | public void setAdditional_data(T2 additional_data) { 70 | this.additional_data = additional_data; 71 | } 72 | 73 | public T3 getRelated_objects() { 74 | return related_objects; 75 | } 76 | 77 | public void setRelated_objects(T3 related_objects) { 78 | this.related_objects = related_objects; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/mvp/BaseObserver.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.mvp; 2 | 3 | import com.google.gson.JsonParseException; 4 | 5 | import org.json.JSONException; 6 | 7 | import java.io.InterruptedIOException; 8 | import java.net.ConnectException; 9 | import java.net.UnknownHostException; 10 | import java.text.ParseException; 11 | 12 | import io.reactivex.observers.DisposableObserver; 13 | import retrofit2.HttpException; 14 | 15 | /** 16 | * File descripition: 数据处理基类 17 | * 18 | * @author lp 19 | * @date 2018/6/19 20 | */ 21 | 22 | public abstract class BaseObserver extends DisposableObserver> { 23 | protected BaseView view; 24 | 25 | /** 26 | * 网络连接失败 无网 27 | */ 28 | public static final int NETWORK_ERROR = 100000; 29 | /** 30 | * 解析数据失败 31 | */ 32 | public static final int PARSE_ERROR = 1008; 33 | /** 34 | * 网络问题 35 | */ 36 | public static final int BAD_NETWORK = 1007; 37 | /** 38 | * 连接错误 39 | */ 40 | public static final int CONNECT_ERROR = 1006; 41 | /** 42 | * 连接超时 43 | */ 44 | public static final int CONNECT_TIMEOUT = 1005; 45 | /** 46 | * 非 true的所有情况 47 | */ 48 | public static final int NOT_TRUE_OVER = 1004; 49 | 50 | public BaseObserver(BaseView view) { 51 | this.view = view; 52 | } 53 | 54 | @Override 55 | protected void onStart() { 56 | if (view != null) { 57 | view.showLoading(); 58 | } 59 | } 60 | 61 | @Override 62 | public void onNext(BaseModel o) { 63 | // T t = o.getData(); 64 | try { 65 | if (view != null) { 66 | view.hideLoading(); 67 | } 68 | if (o.getSuccess()) { 69 | onSuccess(o); 70 | } else { 71 | view.onErrorCode(o); 72 | //非 true的所有情况 73 | onException(NOT_TRUE_OVER, o.getMessage()); 74 | } 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | onError(e.toString()); 78 | } 79 | } 80 | 81 | @Override 82 | public void onError(Throwable e) { 83 | if (view != null) { 84 | view.hideLoading(); 85 | } 86 | if (e instanceof HttpException) { 87 | // HTTP错误 88 | onException(BAD_NETWORK, ""); 89 | } else if (e instanceof ConnectException 90 | || e instanceof UnknownHostException) { 91 | // 连接错误 92 | onException(CONNECT_ERROR, ""); 93 | } else if (e instanceof InterruptedIOException) { 94 | // 连接超时 95 | onException(CONNECT_TIMEOUT, ""); 96 | } else if (e instanceof JsonParseException 97 | || e instanceof JSONException 98 | || e instanceof ParseException) { 99 | // 解析错误 100 | onException(PARSE_ERROR, ""); 101 | e.printStackTrace(); 102 | } else { 103 | if (e != null) { 104 | onError(e.toString()); 105 | } else { 106 | onError("未知错误"); 107 | } 108 | } 109 | 110 | } 111 | 112 | private void onException(int unknownError, String message) { 113 | switch (unknownError) { 114 | case CONNECT_ERROR: 115 | onError("连接错误"); 116 | break; 117 | case CONNECT_TIMEOUT: 118 | onError("连接超时"); 119 | break; 120 | case BAD_NETWORK: 121 | onError("网络超时"); 122 | break; 123 | case PARSE_ERROR: 124 | onError("数据解析失败"); 125 | break; 126 | //非true的所有情况 127 | case NOT_TRUE_OVER: 128 | onError(message); 129 | break; 130 | default: 131 | break; 132 | } 133 | } 134 | 135 | //消失写到这 有一定的延迟 对dialog显示有影响 136 | @Override 137 | public void onComplete() { 138 | /* if (view != null) { 139 | view.hideLoading(); 140 | }*/ 141 | } 142 | 143 | public abstract void onSuccess(BaseModel o); 144 | 145 | public abstract void onError(String msg); 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/mvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.mvp; 2 | 3 | 4 | 5 | import com.lp.mvp_network.api.ApiServer; 6 | import com.lp.mvp_network.second2demo.api.ApiRetrofit; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.android.schedulers.AndroidSchedulers; 10 | import io.reactivex.disposables.CompositeDisposable; 11 | import io.reactivex.schedulers.Schedulers; 12 | 13 | /** 14 | * File descripition: 创建Presenter基类 15 | * 16 | * @author lp 17 | * @date 2018/6/19 18 | */ 19 | public class BasePresenter { 20 | private CompositeDisposable compositeDisposable; 21 | public V baseView; 22 | protected ApiServer apiServer = ApiRetrofit.getInstance().getApiService(); 23 | 24 | public BasePresenter(V baseView) { 25 | this.baseView = baseView; 26 | } 27 | /** 28 | * 解除绑定 29 | */ 30 | public void detachView() { 31 | baseView = null; 32 | removeDisposable(); 33 | } 34 | /** 35 | * 返回 view 36 | * 37 | * @return 38 | */ 39 | public V getBaseView() { 40 | return baseView; 41 | } 42 | 43 | public void addDisposable(Observable observable, BaseObserver observer) { 44 | if (compositeDisposable == null) { 45 | compositeDisposable = new CompositeDisposable(); 46 | } 47 | compositeDisposable.add(observable.subscribeOn(Schedulers.io()) 48 | .observeOn(AndroidSchedulers.mainThread()) 49 | .subscribeWith(observer)); 50 | } 51 | 52 | public void removeDisposable() { 53 | if (compositeDisposable != null) { 54 | compositeDisposable.dispose(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/second2demo/mvp/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.second2demo.mvp; 2 | 3 | 4 | /** 5 | * File descripition: 基本回调 可自定义添加所需回调 6 | * 7 | * @author lp 8 | * @date 2018/6/19 9 | */ 10 | 11 | public interface BaseView { 12 | /** 13 | * 显示dialog 14 | */ 15 | void showLoading(); 16 | /** 17 | * 隐藏 dialog 18 | */ 19 | 20 | void hideLoading(); 21 | /** 22 | * 显示错误信息 23 | * 24 | * @param msg 25 | */ 26 | void showError(String msg); 27 | /** 28 | * 错误码 29 | */ 30 | void onErrorCode(BaseModel model); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/utils/KeyBoardUtils.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | import android.view.inputmethod.InputMethodManager; 7 | import android.widget.EditText; 8 | 9 | import static android.content.Context.INPUT_METHOD_SERVICE; 10 | 11 | /** 12 | *
13 |  *  author : wyz
14 |  *  e_mail : xxx@xx
15 |  *  time  : 2017/06/${DYA}
16 |  *  desc :
17 |  *  version: 1.0
18 |  * 
19 | */ 20 | 21 | public class KeyBoardUtils { 22 | 23 | /** 24 | * 打开键盘 25 | **/ 26 | public static void openKeybord(View v) { 27 | InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 28 | if (!imm.isActive()) { 29 | imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); 30 | imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 31 | } 32 | } 33 | 34 | /** 35 | * 2. * 关闭软键盘 36 | * 3. * 37 | * 4. * @param v 38 | * 5. 39 | */ 40 | public static void closeKeybord(View v) { 41 | InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 42 | if (imm.isActive()) { 43 | imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0); 44 | } 45 | } 46 | 47 | 48 | /** 49 | * 设置键盘显示与隐藏 50 | * 51 | * @param context 52 | * @param view 53 | * @param visible 54 | */ 55 | public static boolean setIMM(Context context, View view, boolean visible) { 56 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 57 | if (visible) { 58 | return imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); 59 | } else { 60 | return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 61 | 62 | } 63 | } 64 | 65 | 66 | /** 67 | * des:隐藏软键盘,这种方式参数为activity 68 | * 但没有失去焦点 69 | * 70 | * @param activity 71 | */ 72 | public static void hideInputForce(Activity activity) { 73 | if (activity == null || activity.getCurrentFocus() == null) 74 | return; 75 | 76 | ((InputMethodManager) activity.getSystemService(INPUT_METHOD_SERVICE)) 77 | .hideSoftInputFromWindow(activity.getCurrentFocus() 78 | .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); 79 | } 80 | 81 | /** 82 | * 打开软键盘 83 | * 魅族可能会有问题 84 | * 85 | * @param mEditText 86 | * @param mContext 87 | */ 88 | public static void showInput(EditText mEditText, Context mContext) { 89 | InputMethodManager imm = (InputMethodManager) mContext.getSystemService(INPUT_METHOD_SERVICE); 90 | imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN); 91 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); 92 | 93 | 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/utils/L.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.utils; 2 | 3 | import android.util.Log; 4 | 5 | 6 | 7 | /** 8 | * @ Author: qiyue (ustory) 9 | * @ Email: qiyuekoon@foxmail.com 10 | * @ Data:2016/3/6 11 | */ 12 | public class L { 13 | 14 | private final static String TAG = "mvpwork_演示:"; 15 | /** 16 | * 手动开关 17 | */ 18 | private final static boolean DEBUG = true; 19 | /** 20 | * 跟随线上线下自动开关 21 | */ 22 | // private final static boolean DEBUG = Constant.DEBUG; 23 | private final static boolean CANCEL_TAG = true; 24 | 25 | public static void i(String message) { 26 | if (DEBUG) { 27 | Log.i(TAG, message); 28 | } 29 | } 30 | 31 | public static void i(String tag, String message) { 32 | if (DEBUG) { 33 | if (!CANCEL_TAG) { 34 | Log.i(tag, message); 35 | } else { 36 | i(message); 37 | } 38 | } 39 | } 40 | 41 | public static void w(String message) { 42 | if (DEBUG) { 43 | Log.w(TAG, message); 44 | } 45 | } 46 | 47 | public static void w(String tag, String message) { 48 | if (DEBUG) { 49 | if (!CANCEL_TAG) { 50 | Log.w(tag, message); 51 | } else { 52 | w(message); 53 | } 54 | } 55 | 56 | } 57 | 58 | public static void e(String message) { 59 | if (DEBUG) { 60 | Log.e(TAG, message); 61 | } 62 | } 63 | 64 | public static void e(String tag, String message) { 65 | if (DEBUG) { 66 | if (!CANCEL_TAG) { 67 | Log.e(tag, message); 68 | } else { 69 | e(message); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/utils/RetrofitUtil.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.utils; 2 | 3 | 4 | import java.io.File; 5 | import java.util.ArrayList; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | import okhttp3.MediaType; 10 | import okhttp3.MultipartBody; 11 | import okhttp3.RequestBody; 12 | 13 | /** 14 | * File descripition: RetrofitUtil工具类 15 | * 16 | * @author lp 17 | * @date 2018/8/13 18 | */ 19 | 20 | public class RetrofitUtil { 21 | /** 22 | * 将String 字符串转换为Rrtorfit: requestBody类型的value 23 | */ 24 | public static RequestBody convertToRequestBody(String param) { 25 | RequestBody requestBody = null; 26 | requestBody = RequestBody.create(MediaType.parse("text/plain"), param); 27 | return requestBody; 28 | } 29 | 30 | /** 31 | * 将所有的File图片集合转化为retorfit上传图片所需的: MultipartBody.Part类型的集合 32 | */ 33 | public static List filesToMultipartBodyParts(List files, String key) { 34 | List parts = new ArrayList<>(files.size()); 35 | for (File file : files) { 36 | parts.add(filesToMultipartBodyParts(file, key)); 37 | } 38 | return parts; 39 | } 40 | 41 | /** 42 | * 将单个File图片转化为retorfit上传图片所需的: MultipartBody.Part类型 43 | */ 44 | public static MultipartBody.Part filesToMultipartBodyParts(File file, String key) { 45 | RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file); 46 | MultipartBody.Part part = MultipartBody.Part.createFormData(key, file.getName(), requestBody); 47 | return part; 48 | } 49 | 50 | 51 | 52 | public static List initImages(List mImages) { 53 | List listPicture = new ArrayList<>(); 54 | listPicture.clear(); 55 | Iterator stuIter = mImages.iterator(); 56 | while (stuIter.hasNext()) { 57 | String mUrl = stuIter.next(); 58 | listPicture.add(new File(mUrl)); 59 | } 60 | return listPicture; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/view/LoadingDialog.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.view; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.ColorDrawable; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import com.lp.mvp_network.R; 11 | 12 | 13 | /** 14 | * File descripition: 简单菊花框 15 | * 16 | * @author lp 17 | * @date 2019/4/10 18 | */ 19 | 20 | public class LoadingDialog extends Dialog { 21 | private TextView mTvText; 22 | 23 | public LoadingDialog(Context context) { 24 | super(context); 25 | try { 26 | Context contexts = this.getContext(); 27 | int dividerID = contexts.getResources().getIdentifier("android:id/titleDivider", null, null); 28 | View divider = this.findViewById(dividerID); 29 | if (divider != null) { 30 | divider.setBackgroundColor(Color.TRANSPARENT); 31 | } 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 36 | setContentView(R.layout.dialog_loading); 37 | mTvText = findViewById(R.id.tv_text); 38 | setCanceledOnTouchOutside(false); 39 | } 40 | 41 | public LoadingDialog setMessage(String message) { 42 | mTvText.setText(message); 43 | return this; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/lp/mvp_network/view/ProgressDialog.java: -------------------------------------------------------------------------------- 1 | package com.lp.mvp_network.view; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.ColorDrawable; 7 | import android.view.View; 8 | 9 | import com.gastudio.downloadloadding.library.GADownloadingView; 10 | import com.lp.mvp_network.R; 11 | 12 | /** 13 | * File descripition: 14 | * 15 | * @author lp 16 | * @date 2019/8/8 17 | */ 18 | public class ProgressDialog extends Dialog { 19 | private GADownloadingView mProgressBar; 20 | 21 | public ProgressDialog(Context context) { 22 | super(context); 23 | try { 24 | Context contexts = this.getContext(); 25 | int dividerID = contexts.getResources().getIdentifier("android:id/titleDivider", null, null); 26 | View divider = this.findViewById(dividerID); 27 | if (divider != null) { 28 | divider.setBackgroundColor(Color.TRANSPARENT); 29 | } 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 34 | setContentView(R.layout.progress_uptade); 35 | setCanceledOnTouchOutside(false); 36 | setCancelable(false); 37 | mProgressBar = findViewById(R.id.ga_downloading); 38 | mProgressBar.performAnimation(); 39 | } 40 | 41 | public GADownloadingView getProgressBar() { 42 | return mProgressBar; 43 | } 44 | 45 | 46 | public ProgressDialog updateProgress(int progress) { 47 | mProgressBar.updateProgress(progress); 48 | return this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/loading_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LPTim/MVP-Retrofit2-okhttp3-Rxjava2/e5fd2ed4b6c797124882a0657b62bb26472564af/app/src/main/res/drawable/loading_bg.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LPTim/MVP-Retrofit2-okhttp3-Rxjava2/e5fd2ed4b6c797124882a0657b62bb26472564af/app/src/main/res/drawable/logo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/progressbar_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_file.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 |