├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── users │ │ └── xucanyou666 │ │ └── rxjava2_retrofit_mvp │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── users │ │ │ └── xucanyou666 │ │ │ └── rxjava2_retrofit_mvp │ │ │ ├── base │ │ │ ├── BaseActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── BaseMvpActivity.java │ │ │ ├── BasePresenter.java │ │ │ ├── BaseView.java │ │ │ └── MyApplication.java │ │ │ ├── contants │ │ │ └── StaticQuality.java │ │ │ ├── contract │ │ │ └── IPoetryContract.java │ │ │ ├── entity │ │ │ └── PoetryEntity.java │ │ │ ├── iApiService │ │ │ └── GetPoetryEntity.java │ │ │ ├── model │ │ │ └── PoetryModel.java │ │ │ ├── presenter │ │ │ └── PoetryPresenter.java │ │ │ ├── util │ │ │ ├── RetrofitManager.java │ │ │ └── RxJavaUtil.java │ │ │ └── view │ │ │ ├── MainActivity.java │ │ │ └── MainFragment.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── fragment_main.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 │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── users │ └── xucanyou666 │ └── rxjava2_retrofit_mvp │ └── 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/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | xmlns:android 11 | 12 | ^$ 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | xmlns:.* 22 | 23 | ^$ 24 | 25 | 26 | BY_NAME 27 | 28 |
29 |
30 | 31 | 32 | 33 | .*:id 34 | 35 | http://schemas.android.com/apk/res/android 36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 | .*:name 45 | 46 | http://schemas.android.com/apk/res/android 47 | 48 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | name 56 | 57 | ^$ 58 | 59 | 60 | 61 |
62 |
63 | 64 | 65 | 66 | style 67 | 68 | ^$ 69 | 70 | 71 | 72 |
73 |
74 | 75 | 76 | 77 | .* 78 | 79 | ^$ 80 | 81 | 82 | BY_NAME 83 | 84 |
85 |
86 | 87 | 88 | 89 | .* 90 | 91 | http://schemas.android.com/apk/res/android 92 | 93 | 94 | ANDROID_ATTRIBUTE_ORDER 95 | 96 |
97 |
98 | 99 | 100 | 101 | .* 102 | 103 | .* 104 | 105 | 106 | BY_NAME 107 | 108 |
109 |
110 |
111 |
112 |
113 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RxJava2_Retrofit_MVP 2 | > 带你封装自己的MVP+Retrofit+RxJava2框架 3 | > 本实例仅作学习参考, 希望大家点点小星星 4 | 5 | 界面截图: 6 | 7 | ![1aXJRx.png](https://s2.ax1x.com/2020/02/03/1aXJRx.png) 8 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | compileOptions { 6 | sourceCompatibility JavaVersion.VERSION_1_8 7 | targetCompatibility JavaVersion.VERSION_1_8 8 | } 9 | defaultConfig { 10 | applicationId "com.users.xucanyou666.rxjava2_retrofit_mvp" 11 | minSdkVersion 19 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | // RxJava 27 | implementation 'io.reactivex.rxjava2:rxjava:2.1.12' 28 | implementation 'com.squareup.retrofit2:retrofit:2.6.0' 29 | // Retrofit和jxjava关联 30 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' 31 | // Retrofit使用Gson转换 32 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0' 33 | // RxAndroid 34 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 35 | //引入ButterKnife 36 | implementation "com.jakewharton:butterknife:10.2.0" 37 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 38 | annotationProcessor "com.jakewharton:butterknife-compiler:10.2.0" 39 | 40 | implementation "com.google.android.material:material:1.0.0" 41 | implementation fileTree(dir: 'libs', include: ['*.jar']) 42 | implementation 'androidx.appcompat:appcompat:1.1.0' 43 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 44 | testImplementation 'junit:junit:4.12' 45 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 47 | } 48 | -------------------------------------------------------------------------------- /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/users/xucanyou666/rxjava2_retrofit_mvp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.users.xucanyou666.rxjava2_retrofit_mvp", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | import androidx.fragment.app.Fragment; 7 | import androidx.fragment.app.FragmentTransaction; 8 | 9 | import com.users.xucanyou666.rxjava2_retrofit_mvp.R; 10 | import com.users.xucanyou666.rxjava2_retrofit_mvp.view.MainFragment; 11 | 12 | import butterknife.ButterKnife; 13 | 14 | /** 15 | * Description : BaseActivity 基类活动 16 | * 17 | * @author XuCanyou666 18 | * @date 2020/2/2 19 | */ 20 | 21 | 22 | public abstract class BaseActivity extends AppCompatActivity { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(getLayoutId()); 28 | initPresenter(); 29 | initViews(); 30 | ButterKnife.bind(this); 31 | } 32 | 33 | 34 | /** 35 | * 抽象方法:实例化Presenter 36 | */ 37 | protected abstract void initPresenter(); 38 | 39 | /** 40 | * 抽象方法:初始化控件,一般在BaseActivity中通过ButterKnife来绑定,所以该方法内部一般我们初始化界面相关的操作 41 | * 42 | * @return 控件 43 | */ 44 | protected abstract void initViews(); 45 | 46 | 47 | /** 48 | * 抽象方法:得到布局id 49 | * 50 | * @return 布局id 51 | */ 52 | protected abstract int getLayoutId(); 53 | 54 | 55 | /** 56 | * 启动Fragment 57 | * 58 | * @param id id 59 | * @param fragment 碎片 60 | */ 61 | protected void startFragment(int id, Fragment fragment) { 62 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 63 | fragmentTransaction.add(id, fragment); 64 | fragmentTransaction.commit(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.annotation.Nullable; 13 | import androidx.fragment.app.Fragment; 14 | import androidx.fragment.app.FragmentTransaction; 15 | 16 | import butterknife.ButterKnife; 17 | import butterknife.Unbinder; 18 | 19 | import static android.content.ContentValues.TAG; 20 | 21 | /** 22 | * Fragment的基类,封装了一些Fragment的相关操作 23 | * created by xucanyou666 24 | * on 2020/1/31 16:21 25 | * email:913710642@qq.com 26 | */ 27 | public abstract class BaseFragment extends Fragment implements BaseView { 28 | protected T mPresenter; 29 | protected Context mContext; 30 | protected Bundle mBundle; 31 | protected Unbinder unbinder; 32 | protected View view; 33 | 34 | /** 35 | * 恢复数据 36 | * 37 | * @param outState bundle 38 | */ 39 | @Override 40 | public void onSaveInstanceState(@NonNull Bundle outState) { 41 | super.onSaveInstanceState(outState); 42 | if (mBundle != null) { 43 | outState.putBundle("bundle", mBundle); 44 | } 45 | } 46 | 47 | /** 48 | * 绑定activity 49 | * 50 | * @param context context 51 | */ 52 | @Override 53 | public void onAttach(@NonNull Context context) { 54 | super.onAttach(context); 55 | mContext = context; 56 | } 57 | 58 | /** 59 | * 运行在onAttach之后,可以接收别人传递过来的参数,实例化对象 60 | * 可以解决返回的时候页面空白的bug 61 | * 62 | * @param savedInstanceState 63 | */ 64 | @Override 65 | public void onCreate(@Nullable Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | if (savedInstanceState != null) { 68 | mBundle = savedInstanceState.getBundle("bundle"); 69 | } else { 70 | mBundle = getArguments() == null ? new Bundle() : getArguments(); 71 | } 72 | //初始化presenter 73 | mPresenter = initPresenter(); 74 | } 75 | 76 | protected T getPresenter() { 77 | return mPresenter; 78 | } 79 | 80 | 81 | /** 82 | * 运行在onCreate之后,生成View视图 83 | * 84 | * @param inflater 85 | * @param container 86 | * @param savedInstanceState 87 | * @return 88 | */ 89 | @Nullable 90 | @Override 91 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 92 | view = initView(inflater, container, savedInstanceState); 93 | unbinder = ButterKnife.bind(this, view); 94 | return view; 95 | } 96 | 97 | /** 98 | * 运行在onCreateView之后 99 | * 加载数据 100 | * 101 | * @param savedInstanceState 102 | */ 103 | @Override 104 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 105 | super.onActivityCreated(savedInstanceState); 106 | mPresenter.attachView(this); 107 | 108 | } 109 | 110 | 111 | /** 112 | * 跳转Fragment 113 | * 114 | * @param toFragment 跳转去的fragment 115 | */ 116 | public void startFragment(Fragment toFragment) { 117 | Log.d(TAG, "haha"); 118 | startFragment(toFragment, null); 119 | } 120 | 121 | /** 122 | * 跳转Fragment 123 | * 124 | * @param toFragment 跳转到的fragment 125 | * @param tag fragment的标签 126 | */ 127 | public void startFragment(Fragment toFragment, String tag) { 128 | FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); 129 | fragmentTransaction.hide(this).add(android.R.id.content, toFragment, tag); 130 | fragmentTransaction.addToBackStack(tag); 131 | fragmentTransaction.commitAllowingStateLoss(); 132 | } 133 | 134 | @Override 135 | public void onDestroyView() { 136 | super.onDestroyView(); 137 | unbinder.unbind(); 138 | } 139 | 140 | /** 141 | * fragment进行回退 142 | * 类似于activity的OnBackPress 143 | */ 144 | public void onBack() { 145 | getFragmentManager().popBackStack(); 146 | } 147 | 148 | @Override 149 | public void onDetach() { 150 | mPresenter.detachView(); 151 | super.onDetach(); 152 | } 153 | 154 | /** 155 | * 初始化Fragment应有的视图 156 | * 157 | * @return view 158 | */ 159 | public abstract View initView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState); 160 | 161 | 162 | /** 163 | * 创建presenter 164 | * 165 | * @return 必须是BasePresenter的子类 166 | */ 167 | public abstract T initPresenter(); 168 | 169 | /** 170 | * 得到context 171 | * 172 | * @return context 173 | */ 174 | @Override 175 | public Context getContext() { 176 | return mContext; 177 | } 178 | 179 | /** 180 | * 得到bundle 181 | * 182 | * @return bundle 183 | */ 184 | public Bundle getBundle() { 185 | return mBundle; 186 | } 187 | 188 | /** 189 | * 得到fragment 190 | * 191 | * @return fragment 192 | */ 193 | public Fragment getFragment() { 194 | return this; 195 | } 196 | 197 | 198 | } 199 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/BaseMvpActivity.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | 4 | /** 5 | * created by xucanyou666 MVP活动的基类,封装好了一些销毁presenter的解绑 6 | * on 2019/12/24 20:53 7 | * email:913710642@qq.com 8 | */ 9 | 10 | public abstract class BaseMvpActivity extends BaseActivity { 11 | 12 | private P presenter; 13 | 14 | /** 15 | * 初始化presenter 16 | */ 17 | @Override 18 | protected void initPresenter() { 19 | presenter = createPresenter(); 20 | if (presenter != null) { 21 | presenter.attachView((V) this); 22 | } 23 | } 24 | 25 | /** 26 | * 创建presenter 27 | * 28 | * @return Presenter 29 | */ 30 | protected abstract P createPresenter(); 31 | 32 | 33 | /** 34 | * 得到presenter 35 | * 36 | * @return presenter 37 | */ 38 | protected P getPresenter() { 39 | return presenter; 40 | } 41 | 42 | /** 43 | * 销毁 44 | */ 45 | @Override 46 | protected void onDestroy() { 47 | super.onDestroy(); 48 | if (presenter != null) { 49 | presenter.detachView(); 50 | } 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | 4 | import io.reactivex.disposables.CompositeDisposable; 5 | import io.reactivex.disposables.Disposable; 6 | 7 | /** 8 | * created by xucanyou666 9 | * on 2020/1/16 17:12 10 | * email:913710642@qq.com 11 | */ 12 | public abstract class BasePresenter { 13 | //将所有正在处理的Subscription都添加到CompositeSubscription中。统一退出的时候注销观察 14 | private CompositeDisposable mCompositeDisposable; 15 | private V baseView; 16 | 17 | /** 18 | * 和View绑定 19 | * 20 | * @param baseView 21 | */ 22 | public void attachView(V baseView) { 23 | this.baseView = baseView; 24 | } 25 | 26 | /** 27 | * 解绑View,该方法在BaseMvpActivity类中被调用 28 | */ 29 | public void detachView() { 30 | baseView = null; 31 | // 在界面退出等需要解绑观察者的情况下调用此方法统一解绑,防止Rx造成的内存泄漏 32 | if (mCompositeDisposable != null) { 33 | mCompositeDisposable.dispose(); 34 | } 35 | } 36 | 37 | /** 38 | * 获取View 39 | * 40 | * @return view 41 | */ 42 | public V getMvpView() { 43 | return baseView; 44 | } 45 | 46 | 47 | 48 | /** 49 | * 将Disposable添加,在每次网络访问之前初始化时进行添加操作 50 | * 51 | * @param subscription subscription 52 | */ 53 | public void addDisposable(Disposable subscription) { 54 | //csb 如果解绑了的话添加 sb 需要新的实例否则绑定时无效的 55 | if (mCompositeDisposable == null || mCompositeDisposable.isDisposed()) { 56 | mCompositeDisposable = new CompositeDisposable(); 57 | } 58 | mCompositeDisposable.add(subscription); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | 4 | /** 5 | * created by xucanyou666 6 | * on 2020/1/31 18:26 7 | * email:913710642@qq.com 8 | */ 9 | public interface BaseView { 10 | 11 | /** 12 | * 显示进度框 13 | */ 14 | void showProgressDialog(); 15 | 16 | 17 | /** 18 | * 关闭进度框 19 | */ 20 | void hideProgressDialog(); 21 | 22 | 23 | /** 24 | * 出错信息的回调 25 | * 26 | * @param result 错误信息 27 | */ 28 | void onError(String result); 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/base/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.base; 2 | 3 | 4 | import android.app.Application; 5 | import android.content.Context; 6 | 7 | /** 8 | * 基类 9 | * created by xucanyou666 10 | * on 2019/11/2 14:46 11 | * email:913710642@qq.com 12 | * @author xucanyou666 13 | */ 14 | public class MyApplication extends Application { 15 | private static Context context; 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | context = getApplicationContext(); 21 | } 22 | 23 | public static Context getContext() { 24 | return context; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/contants/StaticQuality.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.contants; 2 | 3 | 4 | /** 5 | * created by xucanyou666 6 | * on 2019/11/17 19:01 7 | * email:913710642@qq.com 8 | */ 9 | public class StaticQuality { 10 | public static final String BASE_URL="https://api.gushi.ci/"; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/contract/IPoetryContract.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.contract; 2 | 3 | 4 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.BaseView; 5 | import com.users.xucanyou666.rxjava2_retrofit_mvp.entity.PoetryEntity; 6 | 7 | import io.reactivex.Observable; 8 | 9 | /** 10 | * 诗歌的接口管理器 11 | * created by xucanyou666 12 | * on 2020/2/2 15:33 13 | * email:913710642@qq.com 14 | */ 15 | public interface IPoetryContract { 16 | interface IPoetryModel { 17 | /** 18 | * 得到诗歌 19 | * 20 | * @return 诗歌 21 | */ 22 | Observable getPoetry(); 23 | } 24 | 25 | interface IPoetryPresenter { 26 | void getPoetry(); 27 | } 28 | 29 | interface IPoetryView extends BaseView { 30 | /** 31 | * @param author 作者 32 | */ 33 | void searchSuccess(String author); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/entity/PoetryEntity.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.entity; 2 | 3 | 4 | /** 5 | * 诗歌的实体类 6 | * created by xucanyou666 7 | * on 2020/1/23 21:23 8 | * email:913710642@qq.com 9 | * API返回示例: 10 | * { 11 | * "content": "胡瓶落膊紫薄汗,碎叶城西秋月团。", 12 | * "origin": "从军行七首", 13 | * "author": "王昌龄", 14 | * "category": "古诗文-天气-月亮" 15 | * } 16 | */ 17 | public class PoetryEntity { 18 | private String content; //诗歌内容 19 | private String origin; //来源 20 | private String author; //作者 21 | private String category; //分类 22 | 23 | public String getContent() { 24 | return content; 25 | } 26 | 27 | public void setContent(String content) { 28 | this.content = content; 29 | } 30 | 31 | public String getOrigin() { 32 | return origin; 33 | } 34 | 35 | public void setOrigin(String origin) { 36 | this.origin = origin; 37 | } 38 | 39 | public String getAuthor() { 40 | return author; 41 | } 42 | 43 | public void setAuthor(String author) { 44 | this.author = author; 45 | } 46 | 47 | public String getCategory() { 48 | return category; 49 | } 50 | 51 | public void setCategory(String category) { 52 | this.category = category; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/iApiService/GetPoetryEntity.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.iApiService; 2 | 3 | 4 | import com.users.xucanyou666.rxjava2_retrofit_mvp.entity.PoetryEntity; 5 | 6 | import io.reactivex.Observable; 7 | import retrofit2.http.GET; 8 | 9 | /** 10 | * retrofit接口 11 | * created by xucanyou666 12 | * on 2020/1/23 21:25 13 | * email:913710642@qq.com 14 | */ 15 | public interface GetPoetryEntity { 16 | /** 17 | * 获取古诗词 18 | * 19 | * @return 古诗词 20 | */ 21 | @GET("all.json") 22 | Observable getPoetry(); 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/model/PoetryModel.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.model; 2 | 3 | 4 | import com.users.xucanyou666.rxjava2_retrofit_mvp.contract.IPoetryContract; 5 | import com.users.xucanyou666.rxjava2_retrofit_mvp.entity.PoetryEntity; 6 | import com.users.xucanyou666.rxjava2_retrofit_mvp.iApiService.GetPoetryEntity; 7 | import com.users.xucanyou666.rxjava2_retrofit_mvp.util.RetrofitManager; 8 | 9 | import io.reactivex.Observable; 10 | 11 | /** 12 | * created by xucanyou666 13 | * on 2020/1/16 17:06 14 | * email:913710642@qq.com 15 | */ 16 | public class PoetryModel implements IPoetryContract.IPoetryModel { 17 | 18 | 19 | private PoetryModel() { 20 | 21 | } 22 | 23 | public static PoetryModel getInstance() { 24 | return Inner.instance; 25 | } 26 | 27 | private static class Inner { 28 | private static final PoetryModel instance = new PoetryModel(); 29 | } 30 | 31 | 32 | /** 33 | * 获取古诗词 34 | * 35 | * @return 古诗词 36 | */ 37 | @Override 38 | public Observable getPoetry() { 39 | return RetrofitManager.getInstance().createRs(GetPoetryEntity.class).getPoetry(); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/presenter/PoetryPresenter.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.presenter; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.BasePresenter; 7 | import com.users.xucanyou666.rxjava2_retrofit_mvp.contract.IPoetryContract; 8 | import com.users.xucanyou666.rxjava2_retrofit_mvp.entity.PoetryEntity; 9 | import com.users.xucanyou666.rxjava2_retrofit_mvp.model.PoetryModel; 10 | import com.users.xucanyou666.rxjava2_retrofit_mvp.util.RxJavaUtil; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.Observer; 14 | import io.reactivex.disposables.Disposable; 15 | import io.reactivex.functions.Consumer; 16 | 17 | /** 18 | * created by xucanyou666 19 | * on 2020/1/16 17:09 20 | * email:913710642@qq.com 21 | */ 22 | public class PoetryPresenter extends BasePresenter implements IPoetryContract.IPoetryPresenter { 23 | 24 | private static final String TAG = "PoetryPresenter"; 25 | 26 | private PoetryEntity mPoetryEntity; 27 | private PoetryModel mPoetryModel; 28 | 29 | private PoetryPresenter() { 30 | mPoetryModel = PoetryModel.getInstance(); 31 | } 32 | 33 | public static PoetryPresenter getInstance() { 34 | return Inner.instance; 35 | } 36 | 37 | private static class Inner { 38 | private static final PoetryPresenter instance = new PoetryPresenter(); 39 | } 40 | 41 | /** 42 | * 得到诗歌 43 | */ 44 | @Override 45 | public void getPoetry() { 46 | Observable observable = mPoetryModel.getPoetry().doOnSubscribe(new Consumer() { 47 | @Override 48 | public void accept(Disposable disposable) throws Exception { 49 | addDisposable(disposable); 50 | } 51 | }); 52 | observable = RxJavaUtil.toSubscribe(observable); 53 | observable.subscribe(new Observer() { 54 | @Override 55 | public void onSubscribe(Disposable d) { 56 | } 57 | 58 | @Override 59 | public void onNext(PoetryEntity poetryEntity) { 60 | mPoetryEntity = poetryEntity; 61 | } 62 | 63 | @Override 64 | public void onError(Throwable e) { 65 | getMvpView().onError(e.getMessage()); 66 | Log.d(TAG, "onError: " + e.getMessage()); 67 | } 68 | 69 | @Override 70 | public void onComplete() { 71 | if (mPoetryEntity != null) { 72 | getMvpView().searchSuccess(mPoetryEntity.getAuthor()); 73 | } 74 | } 75 | }); 76 | 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/util/RetrofitManager.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.util; 2 | 3 | 4 | import java.util.concurrent.TimeUnit; 5 | 6 | import okhttp3.OkHttpClient; 7 | import retrofit2.Retrofit; 8 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 9 | import retrofit2.converter.gson.GsonConverterFactory; 10 | 11 | import static com.users.xucanyou666.rxjava2_retrofit_mvp.contants.StaticQuality.BASE_URL; 12 | 13 | /** 14 | * Retrofit单例工具类 15 | * created by xucanyou666 16 | * on 2020/1/16 16:38 17 | * email:913710642@qq.com 18 | */ 19 | public class RetrofitManager { 20 | private Retrofit mRetrofit; 21 | 22 | 23 | //构造器私有,这个工具类只有一个实例 24 | private RetrofitManager() { 25 | OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); 26 | httpClientBuilder.connectTimeout(15, TimeUnit.SECONDS); 27 | mRetrofit = new Retrofit.Builder() 28 | .client(httpClientBuilder.build()) 29 | .addConverterFactory(GsonConverterFactory.create()) 30 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 31 | .baseUrl(BASE_URL) 32 | .build(); 33 | } 34 | 35 | 36 | /** 37 | * 静态内部类单例模式 38 | * 39 | * @return 40 | */ 41 | public static RetrofitManager getInstance() { 42 | return Inner.retrofitManager; 43 | } 44 | 45 | private static class Inner { 46 | private static final RetrofitManager retrofitManager = new RetrofitManager(); 47 | } 48 | 49 | 50 | /** 51 | * 利用泛型传入接口class返回接口实例 52 | * 53 | * @param ser 类 54 | * @param 类的类型 55 | * @return Observable 56 | */ 57 | public T createRs(Class ser) { 58 | return mRetrofit.create(ser); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/util/RxJavaUtil.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.util; 2 | 3 | 4 | import io.reactivex.Observable; 5 | import io.reactivex.android.schedulers.AndroidSchedulers; 6 | import io.reactivex.schedulers.Schedulers; 7 | 8 | /** 9 | * created by xucanyou666 10 | * on 2019/11/17 19:20 11 | * email:913710642@qq.com 12 | * 13 | * @author xucanyou666 14 | */ 15 | public class RxJavaUtil { 16 | /** 17 | * 线程调度工作 18 | * 19 | * @param observable 被观察者 20 | * @param 类型 21 | */ 22 | public static Observable toSubscribe(Observable observable) { 23 | return observable.subscribeOn(Schedulers.io()) 24 | .unsubscribeOn(Schedulers.io()) 25 | .observeOn(AndroidSchedulers.mainThread()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.view; 2 | 3 | import android.util.Log; 4 | import android.view.View; 5 | import android.widget.Button; 6 | import android.widget.LinearLayout; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import androidx.fragment.app.FragmentTransaction; 11 | 12 | import com.users.xucanyou666.rxjava2_retrofit_mvp.R; 13 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.BaseMvpActivity; 14 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.MyApplication; 15 | import com.users.xucanyou666.rxjava2_retrofit_mvp.contract.IPoetryContract; 16 | import com.users.xucanyou666.rxjava2_retrofit_mvp.presenter.PoetryPresenter; 17 | 18 | import butterknife.BindView; 19 | import butterknife.OnClick; 20 | 21 | /** 22 | * Description : MainActivity 23 | * 24 | * @author XuCanyou666 25 | * @date 2020/2/3 26 | */ 27 | 28 | public class MainActivity extends BaseMvpActivity implements IPoetryContract.IPoetryView { 29 | 30 | @BindView(R.id.btn_get_poetry) 31 | Button btnGetPoetry; 32 | @BindView(R.id.tv_poetry_author) 33 | TextView tvPoetryAuthor; 34 | @BindView(R.id.btn_goto_fragment) 35 | Button btnGotoFragment; 36 | @BindView(R.id.ll) 37 | LinearLayout ll; 38 | 39 | @Override 40 | protected void initViews() { 41 | 42 | } 43 | 44 | @Override 45 | protected int getLayoutId() { 46 | return R.layout.activity_main; 47 | } 48 | 49 | @Override 50 | protected PoetryPresenter createPresenter() { 51 | return PoetryPresenter.getInstance(); 52 | } 53 | 54 | @Override 55 | public void searchSuccess(String author) { 56 | tvPoetryAuthor.setText(author); 57 | } 58 | 59 | @Override 60 | public void showProgressDialog() { 61 | 62 | } 63 | 64 | @Override 65 | public void hideProgressDialog() { 66 | 67 | } 68 | 69 | @Override 70 | public void onError(String result) { 71 | Toast.makeText(MyApplication.getContext(), result, Toast.LENGTH_SHORT).show(); 72 | } 73 | 74 | private static final String TAG = "MainActivity"; 75 | 76 | @OnClick({R.id.btn_get_poetry, R.id.btn_goto_fragment}) 77 | public void onViewClicked(View view) { 78 | switch (view.getId()) { 79 | case R.id.btn_get_poetry: 80 | getPresenter().getPoetry(); 81 | break; 82 | case R.id.btn_goto_fragment: 83 | startFragment(R.id.ll, new MainFragment()); 84 | break; 85 | default: 86 | break; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/users/xucanyou666/rxjava2_retrofit_mvp/view/MainFragment.java: -------------------------------------------------------------------------------- 1 | package com.users.xucanyou666.rxjava2_retrofit_mvp.view; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import androidx.annotation.Nullable; 13 | 14 | import com.users.xucanyou666.rxjava2_retrofit_mvp.R; 15 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.BaseFragment; 16 | import com.users.xucanyou666.rxjava2_retrofit_mvp.base.MyApplication; 17 | import com.users.xucanyou666.rxjava2_retrofit_mvp.contract.IPoetryContract; 18 | import com.users.xucanyou666.rxjava2_retrofit_mvp.presenter.PoetryPresenter; 19 | 20 | import butterknife.BindView; 21 | import butterknife.OnClick; 22 | 23 | /** 24 | * Description : MainFragment 25 | * 26 | * @author XuCanyou666 27 | * @date 2020/2/2 28 | */ 29 | 30 | 31 | public class MainFragment extends BaseFragment implements IPoetryContract.IPoetryView { 32 | 33 | 34 | @BindView(R.id.btn_get_poetry) 35 | Button btnGetPoetry; 36 | @BindView(R.id.tv_poetry_author) 37 | TextView tvPoetryAuthor; 38 | 39 | 40 | 41 | 42 | @Override 43 | public View initView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 44 | return inflater.inflate(R.layout.fragment_main, container, false); 45 | } 46 | 47 | @Override 48 | public PoetryPresenter initPresenter() { 49 | return PoetryPresenter.getInstance(); 50 | } 51 | 52 | 53 | @Override 54 | public void showProgressDialog() { 55 | 56 | } 57 | 58 | @Override 59 | public void hideProgressDialog() { 60 | 61 | } 62 | 63 | @Override 64 | public void onError(String result) { 65 | Toast.makeText(MyApplication.getContext(), result, Toast.LENGTH_SHORT).show(); 66 | 67 | } 68 | 69 | @OnClick(R.id.btn_get_poetry) 70 | public void onViewClicked() { 71 | getPresenter().getPoetry(); 72 | } 73 | 74 | @Override 75 | public void searchSuccess(String author) { 76 | tvPoetryAuthor.setText(author); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /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/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 |