Android开发MVP架构记录
安卓的MVP(Model-View-Presenter)架构是一种常见的软件设计模式,用于帮助开发者组织和分离应用程序的不同组成部分。MVP架构的目标是将应用程序的业务逻辑(Presenter)、用户界面(View)和数据模型(Model)解耦,从而提高代码的可维护性、可测试性和可扩展性。
下面是MVP架构中各个组成部分的角色和职责:
-
Model(模型):Model表示应用程序的数据模型层,负责处理数据的获取、存储、操作以及业务逻辑的处理。它可以是数据库、网络请求、文件系统等。Model不直接与View交互,而是通过Presenter进行通信。
-
View(视图):View是用户界面层,负责展示数据和接收用户的输入操作。它通常是Activity、Fragment或者自定义的View组件。View需要将用户的操作传递给Presenter,并将Presenter返回的数据展示给用户。
-
Presenter(展示器):Presenter是连接Model和View的桥梁,负责处理业务逻辑和控制数据流。它接收用户的操作请求并根据需要从Model中获取数据,然后将处理结果传递给View进行展示。Presenter不直接操作View,而是通过定义的接口进行交互。
MVP架构的优点包括:
- 分离关注点:MVP架构将业务逻辑、数据模型和用户界面分离,使得各自的责任更加清晰,易于维护和修改。
- 可测试性:由于Presenter和Model是独立的组件,并且没有直接依赖于Android Framework,因此可以更容易地进行单元测试。
- 可扩展性:通过定义接口和契约类(Contract)来规范组件之间的交互,可以方便地进行功能扩展和替换。
一个安卓项目结构示例:
-
activity:存放activity页面
-
adapter:存放适配器,配合RecycleView展示页面
-
base:存放基类,如:BaseActivity、BaseFargment,将一些公共方法写在基类中
-
entity:存放实体类,或一些数据结构对象
-
essential:存放接口类,里面的接口定义了一系列规范,是程序的核心
IView接口类:是(Activity或Fragment)视图的接口,定义视图有哪些执行方法,每个方法的具体实现中会对UI进行操作。
//所有IView的接口 public interface IView { //登录页接口规范 interface LoginView extends BaseView{ void successLogin(); void failLogin(); } //发现页接口规范 interface ExploreView extends BaseView{ void showBlogs(List<Blog> blogList); } //其他视图接口规范 }
IPrensenter接口类:是Prensenter的接口,定义了Presenter的行为
//所有Presenter的接口 public interface IPresenter { //登录presenter接口 interface login extends BasePresenter { void checkLogin(String body); } //发现prensenter接口 interface exploreReq extends BasePresenter { void getPageBlogs(int page,int limit); } //其他presenter的接口 }
-
fragment:存放fragment页面
-
presenter:存放prensenter实现类
public class ExplorePresenter implements IPresenter.exploreReq { IView.ExploreView exploreView; public ExplorePresenter(IView.ExploreView exploreView) { this.exploreView = exploreView; } @Override public BaseView getBase() { return exploreView; } //观察者 Observer<List<Blog>> blogObserver = new Observer<List<Blog>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(List<Blog> blogList) { exploreView.showBlogs(blogList); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }; @Override public void getPageBlogs(int page, int limit) { ApiServiceFactory.getInstance().getPageBlogs(page, limit).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(blogObserver); } }
-
retrofit:网络请求框架,存放相关类。
ApiService类
//retrofit定义接口 public interface ApiService { @GET("api/getBlog/") Observable<List<Blog>> getPageBlogs(@Query("page") int page, @Query("limit") int limit); @POST("api/login") Observable<Result<User>> login(@Body String body); // 添加其他接口方法... }
ApiServiceFactory
public class ApiServiceFactory { private static final String BASE_URL = "http://10.152.177.187:8180/"; private static OkHttpClient okHttpClient; private static Retrofit retrofit; private static ApiService apiService; private static final long cacheSize = 1024 * 1024 * 15;// 缓存文件最大限制大小20M private static String cacheDirectory = Environment.getExternalStorageDirectory() + "/aop"; // 设置缓存文件路径 private static Cache cache = new Cache(new File(cacheDirectory), cacheSize); // public static ApiService getInstance() { if (apiService == null) { if (retrofit == null) { retrofit = createRetrofit(); } apiService = retrofit.create(ApiService.class); } return apiService; } private static Retrofit createRetrofit() { return new Retrofit.Builder() .baseUrl(BASE_URL) .client(getOkHttpClient()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } private static OkHttpClient getOkHttpClient() { if (okHttpClient == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(30, TimeUnit.SECONDS); // 设置连接超时时间 builder.writeTimeout(30, TimeUnit.SECONDS);// 设置写入超时时间 builder.readTimeout(30, TimeUnit.SECONDS);// 设置读取数据超时时间 builder.retryOnConnectionFailure(true);// 设置进行连接失败重试 // builder.addNetworkInterceptor(getInterceptor()); if (Constants.ISDEBUG) { builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));//拦截器 } builder.cache(cache);// 设置缓存,cacheDir和cacheSize需要根据实际情况设置 okHttpClient = builder.build(); } return okHttpClient; } private static Interceptor getInterceptor() { // 返回你自定义的拦截器,如果没有特殊需求可以返回null return null; } }
Result类:规范返回数据结构类,使所有的返回数据结构为result类,真正数据存放在result.data中,这样就规范了返回结果。
//统一返回数据结构 public class Result<T> { private String code; private String msg; private T data; //T表示泛型 public String getCode() { return code; } public String getMsg() { return msg; } public T getData() { return data; } public void setCode(String code) { this.code = code; } public void setMsg(String msg) { this.msg = msg; } public void setData(T data) { this.data = data; } public Result() { } public Result(T data) { this.data = data; } public static Result success() { Result result = new Result<>(); result.setCode("200"); result.setMsg("成功"); return result; } public static <T> Result<T> success(T data) { Result<T> result = new Result<>(data); result.setCode("0"); result.setMsg("成功"); return result; } public static Result error(String code, String msg) { Result result = new Result(); result.setCode(code); result.setMsg(msg); return result; } }
-
util:存放工具类、常量类、全局变量