├── .idea └── vcs.xml └── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── test │ └── mvp │ └── mvpdemo │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── test │ │ └── mvp │ │ └── mvpdemo │ │ ├── mvc │ │ └── MainActivity.java │ │ └── mvp │ │ ├── v1 │ │ ├── MainContract.java │ │ ├── model │ │ │ └── DataModel.java │ │ ├── presenter │ │ │ └── MainPresenter.java │ │ └── view │ │ │ └── MainActivity.java │ │ ├── v2 │ │ ├── MainContract.java │ │ ├── basemvp │ │ │ ├── BaseActivity.java │ │ │ ├── BasePresenter.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ ├── model │ │ │ └── DataModel.java │ │ ├── presenter │ │ │ └── MainPresenter.java │ │ └── view │ │ │ └── MainActivity.java │ │ ├── v3 │ │ ├── MainContract.java │ │ ├── basemvp │ │ │ ├── BaseActivity.java │ │ │ ├── BasePresenter.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ ├── model │ │ │ └── DataModel.java │ │ ├── presenter │ │ │ └── MainPresenter.java │ │ └── view │ │ │ └── MainActivity.java │ │ ├── v4 │ │ ├── MainContract.java │ │ ├── basemvp │ │ │ ├── BaseActivity.java │ │ │ ├── BaseModel.java │ │ │ ├── BasePresenter.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ ├── model │ │ │ └── DataModel.java │ │ ├── presenter │ │ │ └── MainPresenter.java │ │ └── view │ │ │ └── MainActivity.java │ │ ├── v5 │ │ ├── MainContract.java │ │ ├── basemvp │ │ │ ├── BaseActivity.java │ │ │ ├── BaseModel.java │ │ │ ├── BasePresenter.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ ├── inject │ │ │ └── InjectPresenter.java │ │ ├── model │ │ │ └── DataModel.java │ │ ├── presenter │ │ │ └── MainPresenter.java │ │ └── view │ │ │ └── MainActivity.java │ │ ├── v6 │ │ ├── MainContract.java │ │ ├── SecondContract.java │ │ ├── basemvp │ │ │ ├── BaseActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── BaseModel.java │ │ │ ├── BasePresenter.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ ├── inject │ │ │ └── InjectPresenter.java │ │ ├── model │ │ │ ├── DataModel.java │ │ │ └── SecondModel.java │ │ ├── presenter │ │ │ ├── MainPresenter.java │ │ │ └── SecondPresenter.java │ │ └── view │ │ │ ├── MainActivity.java │ │ │ ├── SecondActivity.java │ │ │ └── SecondFragment.java │ │ └── v7 │ │ ├── MainContract.java │ │ ├── SecondContract.java │ │ ├── basemvp │ │ ├── BaseActivity.java │ │ ├── BaseFragment.java │ │ ├── BaseModel.java │ │ ├── BasePresenter.java │ │ ├── IBasePresenter.java │ │ └── IBaseView.java │ │ ├── inject │ │ └── InjectPresenter.java │ │ ├── model │ │ ├── DataModel.java │ │ └── SecondModel.java │ │ ├── presenter │ │ ├── MainPresenter.java │ │ └── SecondPresenter.java │ │ ├── proxy │ │ ├── IProxy.java │ │ ├── ProxyActivity.java │ │ ├── ProxyFragment.java │ │ └── ProxyImpl.java │ │ └── view │ │ ├── MainActivity.java │ │ ├── SecondActivity.java │ │ └── SecondFragment.java └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── caomei.jpg │ ├── cheng.jpg │ ├── huolongguo.jpg │ ├── ic_launcher_background.xml │ ├── juzi.jpg │ ├── lanmei.jpg │ ├── pingguo.jpg │ └── xigua.jpg │ ├── layout │ ├── activity_main.xml │ ├── activity_second.xml │ └── fragment_second.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 └── test └── mvp └── mvpdemo └── ExampleUnitTest.java /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.test.mvp.mvpdemo" 7 | minSdkVersion 21 8 | targetSdkVersion 28 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 | buildToolsVersion '28.0.3' 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(include: ['*.jar'], dir: 'libs') 28 | implementation 'com.android.support:appcompat-v7:28.+' 29 | implementation 'com.android.support:design:28.0.0' 30 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 34 | implementation("com.squareup.okhttp3:okhttp:4.0.0") 35 | } 36 | -------------------------------------------------------------------------------- /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/test/mvp/mvpdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo; 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() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.test.mvp.mvpdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvc/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvc; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.test.mvp.mvpdemo.R; 11 | 12 | import java.io.IOException; 13 | 14 | import okhttp3.Call; 15 | import okhttp3.Callback; 16 | import okhttp3.OkHttpClient; 17 | import okhttp3.Request; 18 | import okhttp3.Response; 19 | 20 | /** 21 | * 一般 MVC 的写法 22 | * 23 | * @author 神探丶威威猫 24 | * @blog https://blog.csdn.net/smile_running 25 | * @warning 点个赞哦,评个论哦 26 | */ 27 | public class MainActivity extends AppCompatActivity { 28 | 29 | private TextView tv; 30 | private static final String TAG = "MainActivity"; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_main); 36 | 37 | initViews(); 38 | 39 | request(); 40 | showDialog(); 41 | } 42 | 43 | private void initViews() { 44 | tv = findViewById(R.id.tv); 45 | } 46 | 47 | private void showDialog() { 48 | ProgressDialog dialog = new ProgressDialog(this); 49 | dialog.show(); 50 | new Handler().postDelayed(new Runnable() { 51 | @Override 52 | public void run() { 53 | dialog.dismiss(); 54 | } 55 | }, 1500); 56 | } 57 | 58 | private void request() { 59 | OkHttpClient client = new OkHttpClient(); 60 | Request request = new Request.Builder() 61 | .url("https://www.baidu.com/") 62 | .build(); 63 | client.newCall(request).enqueue(new Callback() { 64 | @Override 65 | public void onFailure(Call call, IOException e) { 66 | } 67 | 68 | @Override 69 | public void onResponse(Call call, Response response) throws IOException { 70 | String resp = response.body().string(); 71 | toast(resp); 72 | } 73 | }); 74 | } 75 | 76 | private void toast(String resp) { 77 | runOnUiThread(new Runnable() { 78 | @Override 79 | public void run() { 80 | Toast.makeText(MainActivity.this, "" + resp, Toast.LENGTH_SHORT).show(); 81 | tv.setText(resp); 82 | } 83 | }); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v1/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v1; 2 | 3 | import okhttp3.Callback; 4 | 5 | /** 6 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 7 | */ 8 | public interface MainContract { 9 | interface IMainModel { 10 | void requestBaidu(Callback callback); 11 | } 12 | 13 | interface IMainView { 14 | void showDialog(); 15 | 16 | void succes(String content); 17 | } 18 | 19 | interface IMainPresenter { 20 | void handlerData(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v1/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v1.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v1.MainContract; 4 | 5 | import okhttp3.Callback; 6 | import okhttp3.OkHttpClient; 7 | import okhttp3.Request; 8 | 9 | /** 10 | * model 层,请求网络或数据库,提供数据源(原始数据) 11 | */ 12 | public class DataModel implements MainContract.IMainModel { 13 | 14 | @Override 15 | public void requestBaidu(Callback callback) { 16 | OkHttpClient client = new OkHttpClient(); 17 | Request request = new Request.Builder() 18 | .url("https://www.baidu.com/") 19 | .build(); 20 | client.newCall(request).enqueue(callback); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v1/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v1.presenter; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v1.MainContract; 4 | import com.test.mvp.mvpdemo.mvp.v1.model.DataModel; 5 | 6 | import java.io.IOException; 7 | 8 | import okhttp3.Call; 9 | import okhttp3.Callback; 10 | import okhttp3.Response; 11 | 12 | /** 13 | * presenter 层,承担业务逻辑处理,数据源处理等 14 | */ 15 | public class MainPresenter implements MainContract.IMainPresenter { 16 | 17 | private MainContract.IMainModel mModel; 18 | private MainContract.IMainView mView; 19 | 20 | public MainPresenter(MainContract.IMainView view) { 21 | this.mView = view; 22 | mModel = new DataModel(); 23 | } 24 | 25 | @Override 26 | public void handlerData() { 27 | if (mView != null) { 28 | mView.showDialog(); 29 | } 30 | /** 31 | * 发起请求,获得回调数据 32 | */ 33 | mModel.requestBaidu(new Callback() { 34 | @Override 35 | public void onFailure(Call call, IOException e) { 36 | } 37 | 38 | @Override 39 | public void onResponse(Call call, Response response) throws IOException { 40 | String content = response.body().string(); 41 | if (mView != null) { 42 | mView.succes(content); 43 | } 44 | } 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v1/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v1.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.test.mvp.mvpdemo.R; 11 | import com.test.mvp.mvpdemo.mvp.v1.MainContract; 12 | import com.test.mvp.mvpdemo.mvp.v1.presenter.MainPresenter; 13 | 14 | /** 15 | * MVP 的写法,Version 1: 基础写法 16 | * 17 | * @author 神探丶威威猫 18 | * @blog https://blog.csdn.net/smile_running 19 | * @warning 点个赞哦,评个论哦 20 | */ 21 | public class MainActivity extends AppCompatActivity implements MainContract.IMainView { 22 | 23 | private TextView tv; 24 | 25 | private MainPresenter mPresenter; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_main); 31 | 32 | initViews(); 33 | 34 | mPresenter = new MainPresenter(this); 35 | mPresenter.handlerData(); 36 | } 37 | 38 | private void initViews() { 39 | tv = findViewById(R.id.tv); 40 | } 41 | 42 | @Override 43 | public void showDialog() { 44 | ProgressDialog dialog = new ProgressDialog(this); 45 | dialog.show(); 46 | new Handler().postDelayed(new Runnable() { 47 | @Override 48 | public void run() { 49 | dialog.dismiss(); 50 | } 51 | }, 1500); 52 | } 53 | 54 | @Override 55 | public void succes(String content) { 56 | runOnUiThread(new Runnable() { 57 | @Override 58 | public void run() { 59 | Toast.makeText(MainActivity.this, "" + content, Toast.LENGTH_SHORT).show(); 60 | tv.setText(content); 61 | } 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v2.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v2.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView{ 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | public abstract class BaseActivity

extends AppCompatActivity implements IBaseView { 11 | 12 | protected P mPresenter; 13 | 14 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 15 | 16 | protected abstract void initViews(); 17 | 18 | protected abstract void initData(); 19 | 20 | protected abstract P setPresenter(); 21 | 22 | protected T $(@IdRes int viewId) { 23 | return findViewById(viewId); 24 | } 25 | 26 | @SuppressWarnings("unchecked") 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | initLayout(savedInstanceState); 32 | 33 | /** 34 | * 实例化和绑定 P 层 35 | */ 36 | mPresenter = setPresenter(); 37 | mPresenter.attech(this); 38 | 39 | initViews(); 40 | initData(); 41 | } 42 | 43 | @Override 44 | protected void onDestroy() { 45 | super.onDestroy(); 46 | /** 47 | * 解绑,避免内存泄漏 48 | */ 49 | mPresenter.detech(); 50 | mPresenter = null; 51 | } 52 | 53 | @Override 54 | public Context getContext() { 55 | return this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.basemvp; 2 | 3 | public abstract class BasePresenter implements IBasePresenter { 4 | protected V mView; 5 | 6 | @SuppressWarnings("unchecked") 7 | @Override 8 | public void attech(IBaseView view) { 9 | mView = (V) view; 10 | } 11 | 12 | @Override 13 | public void detech() { 14 | mView = null; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attech(V view); 6 | 7 | void detech(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v2.MainContract; 4 | 5 | import okhttp3.Callback; 6 | import okhttp3.OkHttpClient; 7 | import okhttp3.Request; 8 | 9 | /** 10 | * model 层,请求网络或数据库,提供数据源(原始数据) 11 | */ 12 | public class DataModel implements MainContract.IMainModel { 13 | 14 | @Override 15 | public void requestBaidu(Callback callback) { 16 | OkHttpClient client = new OkHttpClient(); 17 | Request request = new Request.Builder() 18 | .url("https://www.baidu.com/") 19 | .build(); 20 | client.newCall(request).enqueue(callback); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v2.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v2.basemvp.BasePresenter; 7 | import com.test.mvp.mvpdemo.mvp.v2.basemvp.IBaseView; 8 | import com.test.mvp.mvpdemo.mvp.v2.model.DataModel; 9 | 10 | import java.io.IOException; 11 | 12 | import okhttp3.Call; 13 | import okhttp3.Callback; 14 | import okhttp3.Response; 15 | 16 | /** 17 | * presenter 层,承担业务逻辑处理,数据源处理等 18 | */ 19 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 20 | 21 | private MainContract.IMainModel mModel; 22 | 23 | @Override 24 | public void attech(IBaseView view) { 25 | super.attech(view); 26 | mModel = new DataModel(); 27 | } 28 | 29 | @Override 30 | public void handlerData() { 31 | if (mView != null) { 32 | mView.showDialog(); 33 | } 34 | /** 35 | * 发起请求,获得回调数据 36 | */ 37 | mModel.requestBaidu(new Callback() { 38 | @Override 39 | public void onFailure(Call call, IOException e) { 40 | } 41 | 42 | @Override 43 | public void onResponse(Call call, Response response) throws IOException { 44 | String content = response.body().string(); 45 | if (mView != null) { 46 | mView.succes(content); 47 | } 48 | } 49 | }); 50 | } 51 | 52 | @Override 53 | public void detech() { 54 | super.detech(); 55 | /** 56 | * 释放内存、关闭网络请求、关闭线程等操作 57 | */ 58 | Log.d("==========", "detech: 解除绑定,释放内存"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v2/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v2.view; 2 | 3 | import android.app.Activity; 4 | import android.app.ProgressDialog; 5 | import android.content.Context; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.support.annotation.Nullable; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.test.mvp.mvpdemo.R; 13 | import com.test.mvp.mvpdemo.mvp.v2.MainContract; 14 | import com.test.mvp.mvpdemo.mvp.v2.basemvp.BaseActivity; 15 | import com.test.mvp.mvpdemo.mvp.v2.presenter.MainPresenter; 16 | 17 | /** 18 | * MVP 的写法,Version 2: 使用模板方法模式 + 泛型 封装 mvp 基类 19 | * 20 | * @author 神探丶威威猫 21 | * @blog https://blog.csdn.net/smile_running 22 | * @warning 点个赞哦,评个论哦 23 | */ 24 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 25 | 26 | private TextView tv; 27 | 28 | @Override 29 | protected void initLayout(@Nullable Bundle savedInstanceState) { 30 | setContentView(R.layout.activity_main); 31 | } 32 | 33 | @Override 34 | protected void initViews() { 35 | tv = $(R.id.tv); 36 | } 37 | 38 | @Override 39 | protected void initData() { 40 | mPresenter.handlerData(); 41 | } 42 | 43 | @Override 44 | protected MainContract.IMainPresenter setPresenter() { 45 | return new MainPresenter(); 46 | } 47 | 48 | @Override 49 | public void showDialog() { 50 | ProgressDialog dialog = new ProgressDialog(getContext()); 51 | dialog.show(); 52 | new Handler().postDelayed(new Runnable() { 53 | @Override 54 | public void run() { 55 | dialog.dismiss(); 56 | } 57 | }, 1500); 58 | } 59 | 60 | @Override 61 | public void succes(String content) { 62 | runOnUiThread(new Runnable() { 63 | @Override 64 | public void run() { 65 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 66 | tv.setText(content); 67 | } 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v3.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v3.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView { 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | public abstract class BaseActivity

extends AppCompatActivity implements IBaseView { 11 | 12 | private P mPresenter; 13 | 14 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 15 | 16 | protected abstract P setPresenter(); 17 | 18 | protected abstract void initViews(); 19 | 20 | protected abstract void initData(); 21 | 22 | 23 | @SuppressWarnings("SameParameterValue") 24 | protected T $(@IdRes int viewId) { 25 | return findViewById(viewId); 26 | } 27 | 28 | @SuppressWarnings("unchecked") 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | initLayout(savedInstanceState); 34 | 35 | /** 36 | * 实例化和绑定 P 层 37 | */ 38 | this.mPresenter = setPresenter(); 39 | this.mPresenter.attech(this); 40 | 41 | initViews(); 42 | initData(); 43 | } 44 | 45 | @Override 46 | protected void onDestroy() { 47 | super.onDestroy(); 48 | /** 49 | * 解绑,避免内存泄漏 50 | */ 51 | this.mPresenter.detech(); 52 | this.mPresenter = null; 53 | } 54 | 55 | @Override 56 | public Context getContext() { 57 | return this; 58 | } 59 | 60 | public P getPresenter() { 61 | return mPresenter; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.basemvp; 2 | 3 | import java.lang.ref.SoftReference; 4 | import java.lang.reflect.InvocationHandler; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Proxy; 7 | 8 | public abstract class BasePresenter implements IBasePresenter { 9 | private SoftReference mReferenceView; 10 | private V mProxyView; 11 | 12 | @SuppressWarnings("unchecked") 13 | @Override 14 | public void attech(IBaseView view) { 15 | mReferenceView = new SoftReference<>(view); 16 | mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { 17 | @Override 18 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 19 | if (mReferenceView == null || mReferenceView.get() == null) { 20 | return null; 21 | } 22 | return method.invoke(mReferenceView.get(), objects); 23 | } 24 | }); 25 | } 26 | 27 | @SuppressWarnings("unchecked") 28 | public V getView() { 29 | return mProxyView; 30 | } 31 | 32 | @Override 33 | public void detech() { 34 | mReferenceView.clear(); 35 | mReferenceView = null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attech(IBaseView view); 6 | 7 | void detech(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v3.MainContract; 4 | 5 | import okhttp3.Callback; 6 | import okhttp3.OkHttpClient; 7 | import okhttp3.Request; 8 | 9 | /** 10 | * model 层,请求网络或数据库,提供数据源(原始数据) 11 | */ 12 | public class DataModel implements MainContract.IMainModel { 13 | 14 | @Override 15 | public void requestBaidu(Callback callback) { 16 | OkHttpClient client = new OkHttpClient(); 17 | Request request = new Request.Builder() 18 | .url("https://www.baidu.com/") 19 | .build(); 20 | client.newCall(request).enqueue(callback); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v3.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v3.basemvp.BasePresenter; 7 | import com.test.mvp.mvpdemo.mvp.v3.basemvp.IBaseView; 8 | import com.test.mvp.mvpdemo.mvp.v3.model.DataModel; 9 | 10 | import java.io.IOException; 11 | 12 | import okhttp3.Call; 13 | import okhttp3.Callback; 14 | import okhttp3.Response; 15 | 16 | /** 17 | * presenter 层,承担业务逻辑处理,数据源处理等 18 | */ 19 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 20 | 21 | private MainContract.IMainModel mModel; 22 | 23 | @Override 24 | public void attech(IBaseView view) { 25 | super.attech(view); 26 | mModel = new DataModel(); 27 | } 28 | 29 | @Override 30 | public void handlerData() { 31 | getView().showDialog(); 32 | 33 | mModel.requestBaidu(new Callback() { 34 | @Override 35 | public void onFailure(Call call, IOException e) { 36 | } 37 | 38 | @Override 39 | public void onResponse(Call call, Response response) throws IOException { 40 | String content = response.body().string(); 41 | getView().succes(content); 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | public void detech() { 48 | super.detech(); 49 | /** 50 | * 释放内存、关闭网络请求、关闭线程等操作 51 | */ 52 | Log.d("==========", "detech: 解除绑定,释放内存"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v3/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v3.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.annotation.Nullable; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.test.mvp.mvpdemo.R; 11 | import com.test.mvp.mvpdemo.mvp.v3.MainContract; 12 | import com.test.mvp.mvpdemo.mvp.v3.basemvp.BaseActivity; 13 | import com.test.mvp.mvpdemo.mvp.v3.presenter.MainPresenter; 14 | 15 | /** 16 | * MVP 的写法,Version 3: 使用软引用 + 动态代理 17 | * 18 | * @author 神探丶威威猫 19 | * @blog https://blog.csdn.net/smile_running 20 | * @warning 点个赞哦,评个论哦 21 | */ 22 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 23 | 24 | private TextView tv; 25 | 26 | @Override 27 | protected void initLayout(@Nullable Bundle savedInstanceState) { 28 | setContentView(R.layout.activity_main); 29 | } 30 | 31 | @Override 32 | protected void initViews() { 33 | tv = $(R.id.tv); 34 | } 35 | 36 | @Override 37 | protected void initData() { 38 | getPresenter().handlerData(); 39 | } 40 | 41 | @Override 42 | protected MainContract.IMainPresenter setPresenter() { 43 | return new MainPresenter(); 44 | } 45 | 46 | @Override 47 | public void showDialog() { 48 | ProgressDialog dialog = new ProgressDialog(getContext()); 49 | dialog.show(); 50 | new Handler().postDelayed(new Runnable() { 51 | @Override 52 | public void run() { 53 | dialog.dismiss(); 54 | } 55 | }, 1500); 56 | } 57 | 58 | @Override 59 | public void succes(String content) { 60 | runOnUiThread(new Runnable() { 61 | @Override 62 | public void run() { 63 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 64 | tv.setText(content); 65 | } 66 | }); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView { 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | public abstract class BaseActivity

extends AppCompatActivity implements IBaseView { 11 | 12 | private P mPresenter; 13 | 14 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 15 | 16 | protected abstract P setPresenter(); 17 | 18 | protected abstract void initViews(); 19 | 20 | protected abstract void initData(); 21 | 22 | 23 | @SuppressWarnings("SameParameterValue") 24 | protected T $(@IdRes int viewId) { 25 | return findViewById(viewId); 26 | } 27 | 28 | @SuppressWarnings("unchecked") 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | initLayout(savedInstanceState); 34 | 35 | /** 36 | * 实例化和绑定 P 层 37 | */ 38 | this.mPresenter = setPresenter(); 39 | this.mPresenter.attach(this); 40 | 41 | initViews(); 42 | initData(); 43 | } 44 | 45 | @Override 46 | protected void onDestroy() { 47 | super.onDestroy(); 48 | /** 49 | * 解绑,避免内存泄漏 50 | */ 51 | this.mPresenter.detach(); 52 | this.mPresenter = null; 53 | } 54 | 55 | @Override 56 | public Context getContext() { 57 | return this; 58 | } 59 | 60 | public P getPresenter() { 61 | return mPresenter; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/basemvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.basemvp; 2 | 3 | public abstract class BaseModel { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.basemvp; 2 | 3 | import android.util.Log; 4 | 5 | import java.lang.ref.SoftReference; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Proxy; 10 | import java.lang.reflect.Type; 11 | 12 | public abstract class BasePresenter implements IBasePresenter { 13 | private SoftReference mReferenceView; 14 | private V mProxyView; 15 | private M mModel; 16 | 17 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 18 | @Override 19 | public void attach(IBaseView view) { 20 | //使用软引用创建对象 21 | mReferenceView = new SoftReference<>(view); 22 | //使用动态代理做统一的逻辑判断 aop 思想 23 | mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { 24 | @Override 25 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 26 | if (mReferenceView == null || mReferenceView.get() == null) { 27 | return null; 28 | } 29 | return method.invoke(mReferenceView.get(), objects); 30 | } 31 | }); 32 | 33 | //通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model 34 | ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 35 | 36 | Log.d("===========", "attach: "+this.getClass().getSimpleName()); 37 | if (type != null) { 38 | Type[] types = type.getActualTypeArguments(); 39 | try { 40 | mModel = (M) ((Class) types[1]).newInstance(); 41 | } catch (IllegalAccessException e) { 42 | e.printStackTrace(); 43 | } catch (InstantiationException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public V getView() { 52 | return mProxyView; 53 | } 54 | 55 | protected M getModel() { 56 | return mModel; 57 | } 58 | 59 | @Override 60 | public void detach() { 61 | mReferenceView.clear(); 62 | mReferenceView = null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attach(IBaseView view); 6 | 7 | void detach(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v4.MainContract; 4 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.BaseModel; 5 | 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | 10 | /** 11 | * model 层,请求网络或数据库,提供数据源(原始数据) 12 | */ 13 | public class DataModel extends BaseModel implements MainContract.IMainModel { 14 | 15 | @Override 16 | public void requestBaidu(Callback callback) { 17 | OkHttpClient client = new OkHttpClient(); 18 | Request request = new Request.Builder() 19 | .url("https://www.baidu.com/") 20 | .build(); 21 | client.newCall(request).enqueue(callback); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v4.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.BaseModel; 7 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.BasePresenter; 8 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.IBaseView; 9 | import com.test.mvp.mvpdemo.mvp.v4.model.DataModel; 10 | 11 | import java.io.IOException; 12 | 13 | import okhttp3.Call; 14 | import okhttp3.Callback; 15 | import okhttp3.Response; 16 | 17 | /** 18 | * presenter 层,承担业务逻辑处理,数据源处理等 19 | */ 20 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 21 | 22 | @Override 23 | public void handlerData() { 24 | getView().showDialog(); 25 | 26 | getModel().requestBaidu(new Callback() { 27 | @Override 28 | public void onFailure(Call call, IOException e) { 29 | } 30 | 31 | @Override 32 | public void onResponse(Call call, Response response) throws IOException { 33 | String content = response.body().string(); 34 | getView().succes(content); 35 | } 36 | }); 37 | } 38 | 39 | @Override 40 | public void detach() { 41 | super.detach(); 42 | /** 43 | * 释放内存、关闭网络请求、关闭线程等操作 44 | */ 45 | Log.d("==========", "detech: 解除绑定,释放内存"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v4/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v4.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.annotation.Nullable; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.test.mvp.mvpdemo.R; 11 | import com.test.mvp.mvpdemo.mvp.v4.MainContract; 12 | import com.test.mvp.mvpdemo.mvp.v4.basemvp.BaseActivity; 13 | import com.test.mvp.mvpdemo.mvp.v4.presenter.MainPresenter; 14 | 15 | /** 16 | * MVP 的写法,Version 4: 动态创建 Model 17 | * 18 | * @author 神探丶威威猫 19 | * @blog https://blog.csdn.net/smile_running 20 | * @warning 点个赞哦,评个论哦 21 | */ 22 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 23 | 24 | private TextView tv; 25 | 26 | @Override 27 | protected void initLayout(@Nullable Bundle savedInstanceState) { 28 | setContentView(R.layout.activity_main); 29 | } 30 | 31 | @Override 32 | protected void initViews() { 33 | tv = $(R.id.tv); 34 | } 35 | 36 | @Override 37 | protected void initData() { 38 | getPresenter().handlerData(); 39 | } 40 | 41 | @Override 42 | protected MainContract.IMainPresenter setPresenter() { 43 | return new MainPresenter(); 44 | } 45 | 46 | @Override 47 | public void showDialog() { 48 | ProgressDialog dialog = new ProgressDialog(getContext()); 49 | dialog.show(); 50 | new Handler().postDelayed(new Runnable() { 51 | @Override 52 | public void run() { 53 | dialog.dismiss(); 54 | } 55 | }, 1500); 56 | } 57 | 58 | @Override 59 | public void succes(String content) { 60 | runOnUiThread(new Runnable() { 61 | @Override 62 | public void run() { 63 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 64 | tv.setText(content); 65 | } 66 | }); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v5.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v5.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView { 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | import com.test.mvp.mvpdemo.mvp.v5.inject.InjectPresenter; 11 | 12 | import java.lang.reflect.Field; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public abstract class BaseActivity

extends AppCompatActivity implements IBaseView { 17 | 18 | private P mPresenter; 19 | 20 | /** 21 | * 保存使用注解的 Presenter ,用于解绑 22 | */ 23 | private List mInjectPresenters; 24 | 25 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 26 | 27 | protected abstract P setPresenter(); 28 | 29 | protected abstract void initViews(); 30 | 31 | protected abstract void initData(); 32 | 33 | 34 | @SuppressWarnings("SameParameterValue") 35 | protected T $(@IdRes int viewId) { 36 | return findViewById(viewId); 37 | } 38 | 39 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 40 | @Override 41 | protected void onCreate(@Nullable Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | 44 | initLayout(savedInstanceState); 45 | 46 | /** 47 | * 实例化和绑定 P 层 48 | */ 49 | this.mPresenter = setPresenter(); 50 | if (mPresenter != null) { 51 | this.mPresenter.attach(this); 52 | } 53 | 54 | mInjectPresenters = new ArrayList<>(); 55 | 56 | //获得已经申明的变量,包括私有的 57 | Field[] fields = this.getClass().getDeclaredFields(); 58 | for (Field field : fields) { 59 | //获取变量上面的注解类型 60 | InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class); 61 | if (injectPresenter != null) { 62 | try { 63 | Class type = (Class) field.getType(); 64 | BasePresenter mInjectPresenter = type.newInstance(); 65 | mInjectPresenter.attach(this); 66 | field.setAccessible(true); 67 | field.set(this, mInjectPresenter); 68 | mInjectPresenters.add(mInjectPresenter); 69 | } catch (IllegalAccessException e) { 70 | e.printStackTrace(); 71 | } catch (InstantiationException e) { 72 | e.printStackTrace(); 73 | }catch (ClassCastException e){ 74 | e.printStackTrace(); 75 | throw new RuntimeException("SubClass must extends Class:BasePresenter"); 76 | } 77 | } 78 | } 79 | 80 | initViews(); 81 | initData(); 82 | } 83 | 84 | @Override 85 | protected void onDestroy() { 86 | super.onDestroy(); 87 | /** 88 | * 解绑,避免内存泄漏 89 | */ 90 | this.mPresenter.detach(); 91 | this.mPresenter = null; 92 | for (BasePresenter presenter : mInjectPresenters) { 93 | presenter.detach(); 94 | } 95 | mInjectPresenters.clear(); 96 | mInjectPresenters = null; 97 | } 98 | 99 | @Override 100 | public Context getContext() { 101 | return this; 102 | } 103 | 104 | public P getPresenter() { 105 | return mPresenter; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/basemvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.basemvp; 2 | 3 | public abstract class BaseModel { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.basemvp; 2 | 3 | import java.lang.ref.SoftReference; 4 | import java.lang.reflect.InvocationHandler; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.ParameterizedType; 7 | import java.lang.reflect.Proxy; 8 | import java.lang.reflect.Type; 9 | 10 | public abstract class BasePresenter implements IBasePresenter { 11 | private SoftReference mReferenceView; 12 | private V mProxyView; 13 | private M mModel; 14 | 15 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 16 | @Override 17 | public void attach(IBaseView view) { 18 | //使用软引用创建对象 19 | mReferenceView = new SoftReference<>(view); 20 | //使用动态代理做统一的逻辑判断 aop 思想 21 | mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { 22 | @Override 23 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 24 | if (mReferenceView == null || mReferenceView.get() == null) { 25 | return null; 26 | } 27 | return method.invoke(mReferenceView.get(), objects); 28 | } 29 | }); 30 | 31 | //通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model 32 | ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 33 | if (type != null) { 34 | Type[] types = type.getActualTypeArguments(); 35 | try { 36 | mModel = (M) ((Class) types[1]).newInstance(); 37 | } catch (IllegalAccessException e) { 38 | e.printStackTrace(); 39 | } catch (InstantiationException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | } 45 | 46 | @SuppressWarnings("unchecked") 47 | public V getView() { 48 | return mProxyView; 49 | } 50 | 51 | protected M getModel() { 52 | return mModel; 53 | } 54 | 55 | @Override 56 | public void detach() { 57 | mReferenceView.clear(); 58 | mReferenceView = null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attach(IBaseView view); 6 | 7 | void detach(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/inject/InjectPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.inject; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface InjectPresenter { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v5.MainContract; 4 | import com.test.mvp.mvpdemo.mvp.v5.basemvp.BaseModel; 5 | 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | 10 | /** 11 | * model 层,请求网络或数据库,提供数据源(原始数据) 12 | */ 13 | public class DataModel extends BaseModel implements MainContract.IMainModel { 14 | 15 | @Override 16 | public void requestBaidu(Callback callback) { 17 | OkHttpClient client = new OkHttpClient(); 18 | Request request = new Request.Builder() 19 | .url("https://www.baidu.com/") 20 | .build(); 21 | client.newCall(request).enqueue(callback); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v5.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v5.basemvp.BasePresenter; 7 | import com.test.mvp.mvpdemo.mvp.v5.model.DataModel; 8 | 9 | import java.io.IOException; 10 | 11 | import okhttp3.Call; 12 | import okhttp3.Callback; 13 | import okhttp3.Response; 14 | 15 | /** 16 | * presenter 层,承担业务逻辑处理,数据源处理等 17 | */ 18 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 19 | 20 | @Override 21 | public void handlerData() { 22 | getView().showDialog(); 23 | 24 | getModel().requestBaidu(new Callback() { 25 | @Override 26 | public void onFailure(Call call, IOException e) { 27 | } 28 | 29 | @Override 30 | public void onResponse(Call call, Response response) throws IOException { 31 | String content = response.body().string(); 32 | getView().succes(content); 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public void detach() { 39 | super.detach(); 40 | /** 41 | * 释放内存、关闭网络请求、关闭线程等操作 42 | */ 43 | Log.d("==========", "detech: 解除绑定,释放内存"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v5/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v5.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.annotation.Nullable; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.test.mvp.mvpdemo.R; 11 | import com.test.mvp.mvpdemo.mvp.v5.MainContract; 12 | import com.test.mvp.mvpdemo.mvp.v5.basemvp.BaseActivity; 13 | import com.test.mvp.mvpdemo.mvp.v5.inject.InjectPresenter; 14 | import com.test.mvp.mvpdemo.mvp.v5.presenter.MainPresenter; 15 | 16 | /** 17 | * MVP 的写法,Version 5: 依赖注入,解决多个 Presenter 的问题 18 | * 19 | * @author 神探丶威威猫 20 | * @blog https://blog.csdn.net/smile_running 21 | * @warning 点个赞哦,评个论哦 22 | */ 23 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 24 | 25 | private TextView tv; 26 | 27 | @InjectPresenter 28 | private MainPresenter mPresenter; 29 | 30 | @Override 31 | protected void initLayout(@Nullable Bundle savedInstanceState) { 32 | setContentView(R.layout.activity_main); 33 | } 34 | 35 | @Override 36 | protected void initViews() { 37 | tv = $(R.id.tv); 38 | } 39 | 40 | @Override 41 | protected void initData() { 42 | // getPresenter().handlerData(); 43 | mPresenter.handlerData(); 44 | } 45 | 46 | @Override 47 | protected MainContract.IMainPresenter setPresenter() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public void showDialog() { 53 | ProgressDialog dialog = new ProgressDialog(getContext()); 54 | dialog.show(); 55 | new Handler().postDelayed(new Runnable() { 56 | @Override 57 | public void run() { 58 | dialog.dismiss(); 59 | } 60 | }, 1500); 61 | } 62 | 63 | @Override 64 | public void succes(String content) { 65 | runOnUiThread(new Runnable() { 66 | @Override 67 | public void run() { 68 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 69 | tv.setText(content); 70 | } 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView { 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/SecondContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | public interface SecondContract { 9 | interface ISecondModel { 10 | void requestBaidu(Callback callback); 11 | } 12 | 13 | interface ISecondView extends IBaseView { 14 | void showDialog(); 15 | 16 | void succes(String content); 17 | } 18 | 19 | interface ISecondPresenter extends IBasePresenter { 20 | void handlerData(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.util.Log; 9 | import android.view.View; 10 | 11 | import com.test.mvp.mvpdemo.mvp.v6.inject.InjectPresenter; 12 | 13 | import java.lang.reflect.Field; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public abstract class BaseActivity extends AppCompatActivity implements IBaseView { 18 | 19 | /** 20 | * 保存使用注解的 Presenter ,用于解绑 21 | */ 22 | private List mInjectPresenters; 23 | 24 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 25 | 26 | protected abstract void initViews(); 27 | 28 | protected abstract void initData(); 29 | 30 | 31 | @SuppressWarnings("SameParameterValue") 32 | protected T $(@IdRes int viewId) { 33 | return findViewById(viewId); 34 | } 35 | 36 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 37 | @Override 38 | protected void onCreate(@Nullable Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | 41 | initLayout(savedInstanceState); 42 | 43 | mInjectPresenters = new ArrayList<>(); 44 | 45 | //获得已经申明的变量,包括私有的 46 | Field[] fields = this.getClass().getDeclaredFields(); 47 | Log.d("============", "bindPresenter: " + this.getClass().getName()); 48 | for (Field field : fields) { 49 | //获取变量上面的注解类型 50 | InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class); 51 | if (injectPresenter != null) { 52 | try { 53 | Class type = (Class) field.getType(); 54 | BasePresenter mInjectPresenter = type.newInstance(); 55 | mInjectPresenter.attach(this); 56 | field.setAccessible(true); 57 | field.set(this, mInjectPresenter); 58 | mInjectPresenters.add(mInjectPresenter); 59 | } catch (IllegalAccessException e) { 60 | e.printStackTrace(); 61 | } catch (InstantiationException e) { 62 | e.printStackTrace(); 63 | }catch (ClassCastException e){ 64 | e.printStackTrace(); 65 | throw new RuntimeException("SubClass must extends Class:BasePresenter"); 66 | } 67 | } 68 | } 69 | 70 | initViews(); 71 | initData(); 72 | } 73 | 74 | @Override 75 | protected void onDestroy() { 76 | super.onDestroy(); 77 | /** 78 | * 解绑,避免内存泄漏 79 | */ 80 | for (BasePresenter presenter : mInjectPresenters) { 81 | presenter.detach(); 82 | } 83 | mInjectPresenters.clear(); 84 | mInjectPresenters = null; 85 | } 86 | 87 | @Override 88 | public Context getContext() { 89 | return this; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.IdRes; 5 | import android.support.annotation.LayoutRes; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import com.test.mvp.mvpdemo.mvp.v6.inject.InjectPresenter; 13 | import java.lang.reflect.Field; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public abstract class BaseFragment extends Fragment implements IBaseView { 18 | 19 | private List mInjectPresenters; 20 | 21 | private View mLayoutView; 22 | 23 | protected abstract @LayoutRes int setLayout(); 24 | 25 | protected abstract void initViews(@Nullable Bundle savedInstanceState); 26 | 27 | protected abstract void initData(); 28 | 29 | @SuppressWarnings("ConstantConditions") 30 | protected T $(@IdRes int viewId) { 31 | return this.getView().findViewById(viewId); 32 | } 33 | 34 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 35 | @Nullable 36 | @Override 37 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 38 | View view = inflater.inflate(setLayout(), container, false); 39 | 40 | mInjectPresenters = new ArrayList<>(); 41 | 42 | //获得已经申明的变量,包括私有的 43 | Field[] fields = this.getClass().getDeclaredFields(); 44 | for (Field field : fields) { 45 | //获取变量上面的注解类型 46 | InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class); 47 | if (injectPresenter != null) { 48 | try { 49 | Class type = (Class) field.getType(); 50 | BasePresenter mInjectPresenter = type.newInstance(); 51 | //绑定 52 | mInjectPresenter.attach(this); 53 | field.setAccessible(true); 54 | field.set(this, mInjectPresenter); 55 | mInjectPresenters.add(mInjectPresenter); 56 | } catch (IllegalAccessException e) { 57 | e.printStackTrace(); 58 | } catch (java.lang.InstantiationException e) { 59 | e.printStackTrace(); 60 | } catch (ClassCastException e) { 61 | e.printStackTrace(); 62 | throw new RuntimeException("SubClass must extends Class:BasePresenter"); 63 | } 64 | } 65 | } 66 | return view; 67 | } 68 | 69 | @Override 70 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 71 | super.onViewCreated(view, savedInstanceState); 72 | 73 | initViews(savedInstanceState); 74 | initData(); 75 | } 76 | 77 | @Override 78 | public void onDestroy() { 79 | super.onDestroy(); 80 | for (BasePresenter presenter : mInjectPresenters) { 81 | presenter.detach(); 82 | } 83 | mInjectPresenters.clear(); 84 | mInjectPresenters = null; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | public abstract class BaseModel { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | import android.util.Log; 4 | 5 | import java.lang.ref.SoftReference; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Proxy; 10 | import java.lang.reflect.Type; 11 | 12 | public abstract class BasePresenter implements IBasePresenter { 13 | 14 | private SoftReference mReferenceView; 15 | private V mProxyView; 16 | private M mModel; 17 | 18 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 19 | @Override 20 | public void attach(IBaseView view) { 21 | //使用软引用创建对象 22 | Log.d("============view", "bindPresenter: " + view.getClass().getName()); 23 | mReferenceView = new SoftReference<>(view); 24 | 25 | //使用动态代理做统一的逻辑判断 aop 思想 26 | mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { 27 | @Override 28 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 29 | if (mReferenceView == null || mReferenceView.get() == null) { 30 | return null; 31 | } 32 | return method.invoke(mReferenceView.get(), objects); 33 | } 34 | }); 35 | 36 | //通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model 37 | ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 38 | if (type != null) { 39 | Type[] types = type.getActualTypeArguments(); 40 | try { 41 | mModel = (M) ((Class) types[1]).newInstance(); 42 | } catch (IllegalAccessException e) { 43 | e.printStackTrace(); 44 | } catch (InstantiationException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | } 50 | 51 | @SuppressWarnings("unchecked") 52 | public V getView() { 53 | return mProxyView; 54 | } 55 | 56 | protected M getModel() { 57 | return mModel; 58 | } 59 | 60 | @Override 61 | public void detach() { 62 | mReferenceView.clear(); 63 | mReferenceView = null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attach(IBaseView view); 6 | 7 | void detach(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/inject/InjectPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.inject; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface InjectPresenter { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v6.MainContract; 4 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BaseModel; 5 | 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | 10 | /** 11 | * model 层,请求网络或数据库,提供数据源(原始数据) 12 | */ 13 | public class DataModel extends BaseModel implements MainContract.IMainModel { 14 | 15 | @Override 16 | public void requestBaidu(Callback callback) { 17 | OkHttpClient client = new OkHttpClient(); 18 | Request request = new Request.Builder() 19 | .url("https://www.baidu.com/") 20 | .build(); 21 | client.newCall(request).enqueue(callback); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/model/SecondModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v6.SecondContract; 4 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BaseModel; 5 | import okhttp3.Callback; 6 | import okhttp3.OkHttpClient; 7 | import okhttp3.Request; 8 | 9 | public class SecondModel extends BaseModel implements SecondContract.ISecondModel { 10 | @Override 11 | public void requestBaidu(Callback callback) { 12 | OkHttpClient client = new OkHttpClient(); 13 | Request request = new Request.Builder() 14 | .url("https://blog.csdn.net/smile_running") 15 | .build(); 16 | client.newCall(request).enqueue(callback); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v6.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BasePresenter; 7 | import com.test.mvp.mvpdemo.mvp.v6.model.DataModel; 8 | 9 | import java.io.IOException; 10 | 11 | import okhttp3.Call; 12 | import okhttp3.Callback; 13 | import okhttp3.Response; 14 | 15 | /** 16 | * presenter 层,承担业务逻辑处理,数据源处理等 17 | */ 18 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 19 | 20 | @Override 21 | public void handlerData() { 22 | getView().showDialog(); 23 | 24 | getModel().requestBaidu(new Callback() { 25 | @Override 26 | public void onFailure(Call call, IOException e) { 27 | } 28 | 29 | @Override 30 | public void onResponse(Call call, Response response) throws IOException { 31 | String content = response.body().string(); 32 | getView().succes(content); 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public void detach() { 39 | super.detach(); 40 | /** 41 | * 释放内存、关闭网络请求、关闭线程等操作 42 | */ 43 | Log.d("==========", "detech: 解除绑定,释放内存"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/presenter/SecondPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.presenter; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v6.SecondContract; 4 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BasePresenter; 5 | import com.test.mvp.mvpdemo.mvp.v6.model.SecondModel; 6 | import java.io.IOException; 7 | import okhttp3.Call; 8 | import okhttp3.Callback; 9 | import okhttp3.Response; 10 | 11 | public class SecondPresenter extends BasePresenter implements SecondContract.ISecondPresenter { 12 | 13 | @Override 14 | public void handlerData() { 15 | getView().showDialog(); 16 | 17 | getModel().requestBaidu(new Callback() { 18 | @Override 19 | public void onFailure(Call call, IOException e) { 20 | } 21 | 22 | @Override 23 | public void onResponse(Call call, Response response) throws IOException { 24 | String content = response.body().string(); 25 | getView().succes(content); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.support.annotation.Nullable; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.test.mvp.mvpdemo.R; 13 | import com.test.mvp.mvpdemo.mvp.v6.MainContract; 14 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BaseActivity; 15 | import com.test.mvp.mvpdemo.mvp.v6.inject.InjectPresenter; 16 | import com.test.mvp.mvpdemo.mvp.v6.presenter.MainPresenter; 17 | 18 | /** 19 | * MVP 的写法,Version 6: 封装 BaseFragment 20 | * 21 | * @author 神探丶威威猫 22 | * @blog https://blog.csdn.net/smile_running 23 | * @warning 点个赞哦,评个论哦 24 | */ 25 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 26 | 27 | private TextView tv; 28 | 29 | @InjectPresenter 30 | private MainPresenter mPresenter; 31 | 32 | @Override 33 | protected void initLayout(@Nullable Bundle savedInstanceState) { 34 | setContentView(R.layout.activity_main); 35 | } 36 | 37 | @Override 38 | protected void initViews() { 39 | tv = $(R.id.tv); 40 | 41 | tv.setOnClickListener(new View.OnClickListener() { 42 | @Override 43 | public void onClick(View view) { 44 | startActivity(new Intent(getContext(), SecondActivity.class)); 45 | } 46 | }); 47 | } 48 | 49 | @Override 50 | protected void initData() { 51 | mPresenter.handlerData(); 52 | } 53 | 54 | @Override 55 | public void showDialog() { 56 | ProgressDialog dialog = new ProgressDialog(getContext()); 57 | dialog.show(); 58 | new Handler().postDelayed(new Runnable() { 59 | @Override 60 | public void run() { 61 | dialog.dismiss(); 62 | } 63 | }, 1500); 64 | } 65 | 66 | @Override 67 | public void succes(String content) { 68 | runOnUiThread(new Runnable() { 69 | @Override 70 | public void run() { 71 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 72 | tv.setText(content); 73 | } 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/view/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.view; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.test.mvp.mvpdemo.R; 8 | 9 | public class SecondActivity extends AppCompatActivity { 10 | 11 | @Override 12 | protected void onCreate(@Nullable Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_second); 15 | /** 16 | * 开启一个 fragment 17 | */ 18 | getSupportFragmentManager().beginTransaction().replace(R.id.second_container, new SecondFragment()).commit(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v6/view/SecondFragment.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v6.view; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.widget.TextView; 6 | import android.widget.Toast; 7 | 8 | import com.test.mvp.mvpdemo.R; 9 | import com.test.mvp.mvpdemo.mvp.v6.SecondContract; 10 | import com.test.mvp.mvpdemo.mvp.v6.basemvp.BaseFragment; 11 | import com.test.mvp.mvpdemo.mvp.v6.inject.InjectPresenter; 12 | import com.test.mvp.mvpdemo.mvp.v6.presenter.SecondPresenter; 13 | 14 | public class SecondFragment extends BaseFragment implements SecondContract.ISecondView { 15 | 16 | private TextView tvFragment; 17 | 18 | @InjectPresenter 19 | private SecondPresenter mPresenter; 20 | 21 | @Override 22 | protected int setLayout() { 23 | return R.layout.fragment_second; 24 | } 25 | 26 | @Override 27 | protected void initViews(@Nullable Bundle savedInstanceState) { 28 | tvFragment = $(R.id.tv_fragment); 29 | } 30 | 31 | @Override 32 | protected void initData() { 33 | mPresenter.handlerData(); 34 | } 35 | 36 | @Override 37 | public void showDialog() { 38 | // Toast.makeText(getContext(), "this is Fragment", Toast.LENGTH_SHORT).show(); 39 | } 40 | 41 | @SuppressWarnings("ConstantConditions") 42 | @Override 43 | public void succes(String content) { 44 | getActivity().runOnUiThread(new Runnable() { 45 | @Override 46 | public void run() { 47 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 48 | tvFragment.setText(content); 49 | } 50 | }); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | /** 9 | * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 10 | */ 11 | public interface MainContract { 12 | interface IMainModel { 13 | void requestBaidu(Callback callback); 14 | } 15 | 16 | interface IMainView extends IBaseView { 17 | void showDialog(); 18 | 19 | void succes(String content); 20 | } 21 | 22 | interface IMainPresenter extends IBasePresenter { 23 | void handlerData(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/SecondContract.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBaseView; 5 | 6 | import okhttp3.Callback; 7 | 8 | public interface SecondContract { 9 | interface ISecondModel { 10 | void requestBaidu(Callback callback); 11 | } 12 | 13 | interface ISecondView extends IBaseView { 14 | void showDialog(); 15 | 16 | void succes(String content); 17 | } 18 | 19 | interface ISecondPresenter extends IBasePresenter { 20 | void handlerData(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | import com.test.mvp.mvpdemo.mvp.v7.proxy.ProxyActivity; 11 | 12 | public abstract class BaseActivity extends AppCompatActivity implements IBaseView { 13 | 14 | private ProxyActivity mProxyActivity; 15 | 16 | protected abstract void initLayout(@Nullable Bundle savedInstanceState); 17 | 18 | protected abstract void initViews(); 19 | 20 | protected abstract void initData(); 21 | 22 | 23 | @SuppressWarnings("SameParameterValue") 24 | protected T $(@IdRes int viewId) { 25 | return findViewById(viewId); 26 | } 27 | 28 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | initLayout(savedInstanceState); 34 | 35 | mProxyActivity = createProxyActivity(); 36 | mProxyActivity.bindPresenter(); 37 | 38 | initViews(); 39 | initData(); 40 | } 41 | 42 | @SuppressWarnings("unchecked") 43 | private ProxyActivity createProxyActivity() { 44 | if (mProxyActivity == null) { 45 | return new ProxyActivity(this); 46 | } 47 | return mProxyActivity; 48 | } 49 | 50 | @Override 51 | protected void onDestroy() { 52 | super.onDestroy(); 53 | mProxyActivity.unbindPresenter(); 54 | } 55 | 56 | @Override 57 | public Context getContext() { 58 | return this; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.IdRes; 5 | import android.support.annotation.LayoutRes; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import com.test.mvp.mvpdemo.mvp.v7.proxy.ProxyFragment; 14 | 15 | public abstract class BaseFragment extends Fragment implements IBaseView { 16 | 17 | private ProxyFragment mProxyFragment; 18 | 19 | protected abstract @LayoutRes 20 | int setLayout(); 21 | 22 | protected abstract void initViews(@Nullable Bundle savedInstanceState); 23 | 24 | protected abstract void initData(); 25 | 26 | @SuppressWarnings("ConstantConditions") 27 | protected T $(@IdRes int viewId) { 28 | return this.getView().findViewById(viewId); 29 | } 30 | 31 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 32 | @Nullable 33 | @Override 34 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 35 | View view = inflater.inflate(setLayout(), container, false); 36 | 37 | mProxyFragment = createProxyFragment(); 38 | mProxyFragment.bindPresenter(); 39 | 40 | return view; 41 | } 42 | 43 | @Override 44 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 45 | super.onViewCreated(view, savedInstanceState); 46 | 47 | initViews(savedInstanceState); 48 | initData(); 49 | } 50 | 51 | @SuppressWarnings("unchecked") 52 | private ProxyFragment createProxyFragment() { 53 | if (mProxyFragment == null) { 54 | return new ProxyFragment<>(this); 55 | } 56 | return mProxyFragment; 57 | } 58 | 59 | @Override 60 | public void onDestroy() { 61 | super.onDestroy(); 62 | mProxyFragment.unbindPresenter(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | public abstract class BaseModel { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | import android.util.Log; 4 | 5 | import java.lang.ref.SoftReference; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Proxy; 10 | import java.lang.reflect.Type; 11 | 12 | public abstract class BasePresenter implements IBasePresenter { 13 | 14 | private SoftReference mReferenceView; 15 | private V mProxyView; 16 | private M mModel; 17 | 18 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 19 | @Override 20 | public void attach(IBaseView view) { 21 | //使用软引用创建对象 22 | mReferenceView = new SoftReference<>(view); 23 | 24 | //使用动态代理做统一的逻辑判断 aop 思想 25 | mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { 26 | @Override 27 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 28 | if (mReferenceView == null || mReferenceView.get() == null) { 29 | return null; 30 | } 31 | return method.invoke(mReferenceView.get(), objects); 32 | } 33 | }); 34 | 35 | //通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model 36 | ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 37 | if (type != null) { 38 | Type[] types = type.getActualTypeArguments(); 39 | try { 40 | mModel = (M) ((Class) types[1]).newInstance(); 41 | } catch (IllegalAccessException e) { 42 | e.printStackTrace(); 43 | } catch (InstantiationException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public V getView() { 52 | return mProxyView; 53 | } 54 | 55 | protected M getModel() { 56 | return mModel; 57 | } 58 | 59 | @Override 60 | public void detach() { 61 | mReferenceView.clear(); 62 | mReferenceView = null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | public interface IBasePresenter { 4 | 5 | void attach(IBaseView view); 6 | 7 | void detach(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/basemvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.basemvp; 2 | 3 | import android.content.Context; 4 | 5 | public interface IBaseView { 6 | 7 | Context getContext(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/inject/InjectPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.inject; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface InjectPresenter { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/model/DataModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.MainContract; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BaseModel; 5 | 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | 10 | /** 11 | * model 层,请求网络或数据库,提供数据源(原始数据) 12 | */ 13 | public class DataModel extends BaseModel implements MainContract.IMainModel { 14 | 15 | @Override 16 | public void requestBaidu(Callback callback) { 17 | OkHttpClient client = new OkHttpClient(); 18 | Request request = new Request.Builder() 19 | .url("https://www.baidu.com/") 20 | .build(); 21 | client.newCall(request).enqueue(callback); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/model/SecondModel.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.model; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.SecondContract; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BaseModel; 5 | 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | 10 | public class SecondModel extends BaseModel implements SecondContract.ISecondModel { 11 | @Override 12 | public void requestBaidu(Callback callback) { 13 | OkHttpClient client = new OkHttpClient(); 14 | Request request = new Request.Builder() 15 | .url("https://blog.csdn.net/smile_running") 16 | .build(); 17 | client.newCall(request).enqueue(callback); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.presenter; 2 | 3 | import android.util.Log; 4 | 5 | import com.test.mvp.mvpdemo.mvp.v7.MainContract; 6 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BasePresenter; 7 | import com.test.mvp.mvpdemo.mvp.v7.model.DataModel; 8 | 9 | import java.io.IOException; 10 | 11 | import okhttp3.Call; 12 | import okhttp3.Callback; 13 | import okhttp3.Response; 14 | 15 | /** 16 | * presenter 层,承担业务逻辑处理,数据源处理等 17 | */ 18 | public class MainPresenter extends BasePresenter implements MainContract.IMainPresenter { 19 | 20 | @Override 21 | public void handlerData() { 22 | getView().showDialog(); 23 | 24 | getModel().requestBaidu(new Callback() { 25 | @Override 26 | public void onFailure(Call call, IOException e) { 27 | } 28 | 29 | @Override 30 | public void onResponse(Call call, Response response) throws IOException { 31 | String content = response.body().string(); 32 | getView().succes(content); 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public void detach() { 39 | super.detach(); 40 | /** 41 | * 释放内存、关闭网络请求、关闭线程等操作 42 | */ 43 | Log.d("==========", "detech: 解除绑定,释放内存"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/presenter/SecondPresenter.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.presenter; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.SecondContract; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BasePresenter; 5 | import com.test.mvp.mvpdemo.mvp.v7.model.SecondModel; 6 | 7 | import java.io.IOException; 8 | 9 | import okhttp3.Call; 10 | import okhttp3.Callback; 11 | import okhttp3.Response; 12 | 13 | public class SecondPresenter extends BasePresenter implements SecondContract.ISecondPresenter { 14 | 15 | @Override 16 | public void handlerData() { 17 | getView().showDialog(); 18 | 19 | getModel().requestBaidu(new Callback() { 20 | @Override 21 | public void onFailure(Call call, IOException e) { 22 | } 23 | 24 | @Override 25 | public void onResponse(Call call, Response response) throws IOException { 26 | String content = response.body().string(); 27 | getView().succes(content); 28 | } 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/proxy/IProxy.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.proxy; 2 | 3 | public interface IProxy { 4 | void bindPresenter(); 5 | 6 | void unbindPresenter(); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/proxy/ProxyActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.proxy; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBaseView; 4 | 5 | public class ProxyActivity extends ProxyImpl { 6 | public ProxyActivity(V view) { 7 | super(view); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/proxy/ProxyFragment.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.proxy; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBaseView; 4 | 5 | public class ProxyFragment extends ProxyImpl { 6 | public ProxyFragment(V view) { 7 | super(view); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/proxy/ProxyImpl.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.proxy; 2 | 3 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BasePresenter; 4 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.IBaseView; 5 | import com.test.mvp.mvpdemo.mvp.v7.inject.InjectPresenter; 6 | import java.lang.reflect.Field; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ProxyImpl implements IProxy { 11 | 12 | private IBaseView mView; 13 | private List mInjectPresenters; 14 | 15 | public ProxyImpl(IBaseView view) { 16 | this.mView = view; 17 | mInjectPresenters = new ArrayList<>(); 18 | } 19 | 20 | @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) 21 | @Override 22 | public void bindPresenter() { 23 | //获得已经申明的变量,包括私有的 24 | Field[] fields = mView.getClass().getDeclaredFields(); 25 | for (Field field : fields) { 26 | //获取变量上面的注解类型 27 | InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class); 28 | if (injectPresenter != null) { 29 | try { 30 | Class type = (Class) field.getType(); 31 | BasePresenter mInjectPresenter = type.newInstance(); 32 | mInjectPresenter.attach(mView); 33 | field.setAccessible(true); 34 | field.set(mView, mInjectPresenter); 35 | mInjectPresenters.add(mInjectPresenter); 36 | } catch (IllegalAccessException e) { 37 | e.printStackTrace(); 38 | } catch (InstantiationException e) { 39 | e.printStackTrace(); 40 | } catch (ClassCastException e) { 41 | e.printStackTrace(); 42 | throw new RuntimeException("SubClass must extends Class:BasePresenter"); 43 | } 44 | } 45 | } 46 | } 47 | 48 | @Override 49 | public void unbindPresenter() { 50 | /** 51 | * 解绑,避免内存泄漏 52 | */ 53 | for (BasePresenter presenter : mInjectPresenters) { 54 | presenter.detach(); 55 | } 56 | mInjectPresenters.clear(); 57 | mInjectPresenters = null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.support.annotation.Nullable; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.test.mvp.mvpdemo.R; 13 | import com.test.mvp.mvpdemo.mvp.v7.MainContract; 14 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BaseActivity; 15 | import com.test.mvp.mvpdemo.mvp.v7.inject.InjectPresenter; 16 | import com.test.mvp.mvpdemo.mvp.v7.presenter.MainPresenter; 17 | 18 | /** 19 | * MVP 的写法,Version 6: 静态代理,消除重复代码 20 | * 21 | * @author 神探丶威威猫 22 | * @blog https://blog.csdn.net/smile_running 23 | * @warning 点个赞哦,评个论哦 24 | */ 25 | public class MainActivity extends BaseActivity implements MainContract.IMainView { 26 | 27 | private TextView tv; 28 | 29 | @InjectPresenter 30 | private MainPresenter mPresenter; 31 | 32 | @Override 33 | protected void initLayout(@Nullable Bundle savedInstanceState) { 34 | setContentView(R.layout.activity_main); 35 | } 36 | 37 | @Override 38 | protected void initViews() { 39 | tv = $(R.id.tv); 40 | 41 | tv.setOnClickListener(new View.OnClickListener() { 42 | @Override 43 | public void onClick(View view) { 44 | startActivity(new Intent(getContext(), SecondActivity.class)); 45 | } 46 | }); 47 | } 48 | 49 | @Override 50 | protected void initData() { 51 | mPresenter.handlerData(); 52 | } 53 | 54 | @Override 55 | public void showDialog() { 56 | ProgressDialog dialog = new ProgressDialog(getContext()); 57 | dialog.show(); 58 | new Handler().postDelayed(new Runnable() { 59 | @Override 60 | public void run() { 61 | dialog.dismiss(); 62 | } 63 | }, 1500); 64 | } 65 | 66 | @Override 67 | public void succes(String content) { 68 | runOnUiThread(new Runnable() { 69 | @Override 70 | public void run() { 71 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 72 | tv.setText(content); 73 | } 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/view/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.view; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.test.mvp.mvpdemo.R; 8 | 9 | public class SecondActivity extends AppCompatActivity { 10 | 11 | @Override 12 | protected void onCreate(@Nullable Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_second); 15 | /** 16 | * 开启一个 fragment 17 | */ 18 | getSupportFragmentManager().beginTransaction().replace(R.id.second_container, new SecondFragment()).commit(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/test/mvp/mvpdemo/mvp/v7/view/SecondFragment.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo.mvp.v7.view; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.widget.TextView; 6 | import android.widget.Toast; 7 | 8 | import com.test.mvp.mvpdemo.R; 9 | import com.test.mvp.mvpdemo.mvp.v7.SecondContract; 10 | import com.test.mvp.mvpdemo.mvp.v7.basemvp.BaseFragment; 11 | import com.test.mvp.mvpdemo.mvp.v7.inject.InjectPresenter; 12 | import com.test.mvp.mvpdemo.mvp.v7.presenter.SecondPresenter; 13 | 14 | public class SecondFragment extends BaseFragment implements SecondContract.ISecondView { 15 | 16 | private TextView tvFragment; 17 | 18 | @InjectPresenter 19 | private SecondPresenter mPresenter; 20 | 21 | @Override 22 | protected int setLayout() { 23 | return R.layout.fragment_second; 24 | } 25 | 26 | @Override 27 | protected void initViews(@Nullable Bundle savedInstanceState) { 28 | tvFragment = $(R.id.tv_fragment); 29 | } 30 | 31 | @Override 32 | protected void initData() { 33 | mPresenter.handlerData(); 34 | } 35 | 36 | @Override 37 | public void showDialog() { 38 | // Toast.makeText(getContext(), "this is Fragment", Toast.LENGTH_SHORT).show(); 39 | } 40 | 41 | @SuppressWarnings("ConstantConditions") 42 | @Override 43 | public void succes(String content) { 44 | getActivity().runOnUiThread(new Runnable() { 45 | @Override 46 | public void run() { 47 | Toast.makeText(getContext(), "" + content, Toast.LENGTH_SHORT).show(); 48 | tvFragment.setText(content); 49 | } 50 | }); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /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/caomei.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/caomei.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/cheng.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/cheng.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/huolongguo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/huolongguo.jpg -------------------------------------------------------------------------------- /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/juzi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/juzi.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/lanmei.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/lanmei.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/pingguo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/pingguo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/xigua.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/drawable/xigua.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xww0826/AndroidMVP_Demo/bd3ec2e32e258224ef1424703f7f6fb4122208ba/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MVPDemo-smile_Running 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/test/mvp/mvpdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.test.mvp.mvpdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } --------------------------------------------------------------------------------