Android MVP框架 详细代码

android mvp的好处,网上一搜一大堆,相对于一开始普通的在activity中处理所有的不管是网络请求还是页面渲染,最大的好处是简洁了,废话不多说,看代码

这里网络请求使用了两种,一种是自己封装的okhttp,一种是retrofit+rxjava,可以看出retrofit+rxjava的链式调用和普通的okhttp的区别

mvp,m-model 处理数据,v-activity渲染展示,p-persenter 用于连接m和v,其中又引入锲约类的概念,用于管理这三个所有的接口。

先看代码,

,为了方便我直接放在一个包里了,可以看到 有TestActivity,(mvp-v),TestModel(mvp-m),TestPersenter(mvp-p),其中TestContract就是契约类,用于管理用到的所有接口,多了一个TestCallback用于使用自己封装的okhttp回调,使用retrofit+rxjava时可以省略,这其中也有人习惯把TestModel省略,直接在Persenter中处理数据然后在view中返回。

 

 

先看契约类,其中BaseView可以提取一些公共的方法

 

public interface TestContract {

    interface TestModel{
        void getData(String id,TestCallback callback);
        Observable<HomePage> getData();
    }

    interface TestPersenter{
        void getData(String id);
    }
    interface TestView extends BaseView {
void SetData(HomePage homePage);
}
 }
public interface BaseView {

    void Toast(String s);

    /**
     * 绑定Android生命周期 防止RxJava内存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();

}

 

可以清楚的看到,model,persenter,view使用到的接口。

再看activity中,implements  TestContract.TestView接口,必须实现接口中的方法----SetData,定义了一个按钮,一个TextView,点击按钮,获取数据,显示在TextView中,其中TestPersenter testPersenter = new TestPersenter(this);体现了persenter的连接作用,获取到实例,调用persenter中的getData方法,


public class TestActivity extends BaseActivity implements TestContract.TestView {

TestPersenter testPersenter = new TestPersenter(this);

@BindView(R.id.button)
Button button;
@BindView(R.id.testview)
TextView testview;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ButterKnife.bind(this);

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testPersenter.getData("1");
}
});
}


@Override
public void SetData(HomePage homePage) {
testview.setText(homePage.getMessage());
}

@Override
public void Toast(String s) {
super.Toast(s);

}
}
 
public class BaseActivity extends AppCompatActivity implements BaseView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base2);
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getSupportActionBar().hide();
        ImmersionBar.with(this)
                .statusBarColor(R.color.bar)     //状态栏颜色,不写默认透明色
                .statusBarDarkFont(true) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .fitsSystemWindows(true)
                .keyboardEnable(true)
                .init();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 必须调用该方法,防止内存泄漏
        ImmersionBar.destroy(this,null);
    }
    /**
     * 绑定生命周期 防止MVP内存泄漏
     *
     * @param <T>
     * @return
     */
    @Override
    public <T> AutoDisposeConverter<T> bindAutoDispose() {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider
                .from(this, Lifecycle.Event.ON_DESTROY));
    }

    @Override
    public void Toast(String s) {

    }
}

 

TestPersenter,首先implements 接口,实现接口中的方法---getData,其次拿到了model和view,在getData方法中,调用model获取数据,调用view的setData方法展示数据到页面,从这里也可以看出persenter的连接作用,连接model和view。

public class TestPersenter implements TestContract.TestPersenter{

    TestContract.TestModel model ;
    TestContract.TestView testView;

    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }

    @Override
    public void getData(String id) {
        model.getData("1", new TestCallback() {
            @Override
            public <T> void success(T enty) {
                testView.SetData((HomePage) enty);
            }

            @Override
            public void error(String msg) {
                
            }
        });
    }
}

model:同样implements接口,实现接口中的方法getData,第一个方法是使用自己封装的okhttp网络类,在这里就看出TestCallback 的作用了,访问接口获取数据后,通过TestCallback 返回,TestCallback 中只定义了两个简单的,一个成功时的回调,一个失败时的回调


public class TestModel implements TestContract.TestModel {

@Override
public void getData(String id, TestCallback callback) {
new OkHttpUtil().getJson(HttpUrl.homePage, new OkHttpUtil.HttpCallBack() {
@Override
public void onSusscess(String data) throws JSONException, ParseException {
HomePage homePage = new Gson().fromJson(data,HomePage.class);
if(homePage.isSuccess()){
callback.success(homePage);
}else{
callback.error(homePage.getMessage());
}
}

@Override
public void onError(String meg) {
super.onError(meg);
callback.error(meg);
}
});
}

@Override
public Observable<HomePage> getData() {
       return RetrofitClient.getInstance().getApi().GetData();
    }
}
 
public interface TestCallback {
    <T> void success(T enty);

    void error(String msg);
}

使用retrofit+rxjava,可以看到,省略了TestCallback回调,直接链式调用,onNext中调用了view的setData方法显示数据。

public class TestPersenter implements TestContract.TestPersenter{

    TestContract.TestModel model ;
    TestContract.TestView testView;

    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }

    @Override
    public void getData(String id) {
//        model.getData("1", new TestCallback() {
//            @Override
//            public <T> void success(T enty) {
//                testView.SetData((HomePage) enty);
//            }
//
//            @Override
//            public void error(String msg) {
//
//            }
//        });
        
        model.getData()
            .compose(RxScheduler.Obs_io_main())
            .to(studyView.bindAutoDispose())
            .subscribe(new Observer<HomePage>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {

                }

                @Override
                public void onNext(@NonNull HomePage homePage) {
                    testView.SetData(homePage);
                }

                @Override
                public void onError(@NonNull Throwable e) {
           
) } @Override public void onComplete() { } }); } }



retrofit的使用到的方法

 

 

 

public interface APIService {

/**
* 首页数据
* @return
*/
@GET("app/home_page/queryList")
Observable<HomePage> GetData();

}
public class RetrofitClient {

    private static volatile RetrofitClient instance;
    private APIService apiService;
    private String baseUrl = "****";
    private Retrofit retrofit;
    private OkHttpClient okHttpClient;

    private RetrofitClient() {
    }

    public static RetrofitClient getInstance() {
        if (instance == null) {
            synchronized (RetrofitClient.class) {
                if (instance == null) {
                    instance = new RetrofitClient();
                }
            }
        }
        return instance;
    }

    /**
     * 设置Header
     *
     * @return
     */
    private Interceptor getHeaderInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(@NonNull Chain chain) throws IOException {
                Request original = chain.request();
                Request.Builder requestBuilder = original.newBuilder();
                //添加Token
//                        .header("token", "");
                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        };

    }

    /**
     * 设置拦截器 打印日志
     *
     * @return
     */
    private Interceptor getInterceptor() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        //显示日志
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        return interceptor;
    }

    public OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            //如果为DEBUG 就打印日志
            if (BuildConfig.DEBUG) {
                okHttpClient = new OkHttpClient().newBuilder()
                        //设置Header
                        .addInterceptor(getHeaderInterceptor())
                        //设置拦截器
                        .addInterceptor(getInterceptor())
                        .build();
            } else {
                okHttpClient = new OkHttpClient().newBuilder()
                        //设置Header
                        .addInterceptor(getHeaderInterceptor())
                        .build();
            }

        }

        return okHttpClient;
    }

    public APIService getApi() {
        //初始化一个client,不然retrofit会自己默认添加一个
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    //设置网络请求的Url地址
                    .baseUrl(baseUrl)
                    //设置数据解析器
                    .addConverterFactory(GsonConverterFactory.create())
                    //设置网络请求适配器,使其支持RxJava与RxAndroid
                    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                    .client(getOkHttpClient())
                    .build();
        }
        //创建—— 网络请求接口—— 实例
        if (apiService==null){
            apiService = retrofit.create(APIService.class);
        }

        return apiService;
    }


}

 

public class RxScheduler {

    /**
     * 统一线程处理
     *
     * @param <T> 指定的泛型类型
     * @return FlowableTransformer
     */
    public static <T> FlowableTransformer< T, T> Flo_io_main() {
        return new FlowableTransformer<T, T>() {
            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 统一线程处理
     *
     * @param <T> 指定的泛型类型
     * @return ObservableTransformer
     */
    public static <T> ObservableTransformer<T, T> Obs_io_main() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply( Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

}
public interface BaseView {

    void Toast(String s);

    /**
     * 绑定Android生命周期 防止RxJava内存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();

}
 //okhttp3
    implementation 'com.squareup.okhttp3:okhttp:4.2.0'
    implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
    implementation 'com.google.code.gson:gson:2.8.6'

    //retrofit2
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

    //AutoDispose解决RxJava内存泄漏
    implementation 'com.uber.autodispose2:autodispose:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-android:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-lifecycle:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-androidx-lifecycle:2.0.0'
  // 基础依赖包,必须要依赖
implementation 'com.gyf.immersionbar:immersionbar:3.0.0-beta07'
// fragment快速实现(可选)
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0-beta07'

 

至此,mvp框架结束,mvp增加了接口,使页面和数据处理分开,层次分明,后期好维护。在较小项目中,就几个页面,不必使用框架,也不必为了框架而使用,适合项目的才是最好的。

 

posted @ 2021-12-09 10:00  头一回  阅读(1346)  评论(0编辑  收藏  举报