1.MVP介绍
在Android项目中,Activity和Fragment占据了大部分的开发工作。如果有一种设计模式(或者说代码结构)专门是为优化Activity和Fragment的代码而产生的,你说这种模式重要不?这就是MVP设计模式。
按照MVC的分层,Activity和Fragment(后面只说Activity)应该属于View层,用于展示UI界面,以及接收用户的输入,此外还要承担一些生命周期的工作。Activity是在Android开发中充当非常重要的角色,特别是TA的生命周期的功能,所以开发的时候我们经常把一些业务逻辑直接写在Activity里面,这非常直观方便,代价就是Activity会越来越臃肿,超过1000行代码是常有的事,而且如果是一些可以通用的业务逻辑(比如用户登录),写在具体的Activity里就意味着这个逻辑不能复用了。如果有进行代码重构经验的人,看到1000+行的类肯定会有所顾虑。因此,Activity不仅承担了View的角色,还承担了一部分的Controller角色,这样一来V和C就耦合在一起了,虽然这样写方便,但是如果业务调整的话,要维护起来就难了,而且在一个臃肿的Activity类查找业务逻辑的代码也会非常蛋疼,所以看起来有必要在Activity中,把View和Controller抽离开来,而这就是MVP模式的工作了。
MVP模式的核心思想:
MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,Model类还是原来的Model。
这就是MVP模式,现在这样的话,Activity的工作的简单了,只用来响应生命周期,其他工作都丢到Presenter中去完成。从上图可以看出,Presenter是Model和View之间的桥梁,为了让结构变得更加简单,View并不能直接对Model进行操作,这也是MVP与MVC最大的不同之处。
2.与mvc区别
3.Rxjava+Retrofit+Mvp的在项目中得使用
1)项目结构如下
2)添加依赖
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.0' compile 'io.reactivex:rxandroid:1.2.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:retrofit:2.1.0' testCompile 'junit:junit:4.12'}
3)api包内容
public interface APIManagerService { @GET("/weather/index") Observable<WeatherData> getWeatherData(@Query("format") String format, @Query("cityname") String cityname, @Query("key") String key) ;}
public class APIManager { private static final String ENDPOINT = "http://v.juhe.cn"; private static final Retrofit sRetrofit = new Retrofit .Builder() .baseUrl(ENDPOINT) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器 .build(); private static final APIManagerService apiManager = sRetrofit.create(APIManagerService.class); /** * 获取天气数据 * @param city * @return */ public static Observable<WeatherData> getWeatherData(String format, String city) { return apiManager.getWeatherData(format,city,"ad1d20bebafe0668502c8eea5ddd0333"); } }
4)创建bean对象
public class WeatherData { private String resultcode; private String reason; private ResultEntity result; private int error_code; public void setResultcode(String resultcode) { this.resultcode = resultcode; } public void setReason(String reason) { this.reason = reason; } public void setResult(ResultEntity result) { this.result = result; } public void setError_code(int error_code) { this.error_code = error_code; } public String getResultcode() { return resultcode; } public String getReason() { return reason; } public ResultEntity getResult() { return result; } public int getError_code() { return error_code; } public static class ResultEntity { private SkEntity sk; private TodayEntity today; private List<FutureEntity> future; public void setSk(SkEntity sk) { this.sk = sk; } public void setToday(TodayEntity today) { this.today = today; } public void setFuture(List<FutureEntity> future) { this.future = future; } public SkEntity getSk() { return sk; } public TodayEntity getToday() { return today; } public List<FutureEntity> getFuture() { return future; } public static class SkEntity { private String temp; private String wind_direction; private String wind_strength; private String humidity; private String time; public void setTemp(String temp) { this.temp = temp; } public void setWind_direction(String wind_direction) { this.wind_direction = wind_direction; } public void setWind_strength(String wind_strength) { this.wind_strength = wind_strength; } public void setHumidity(String humidity) { this.humidity = humidity; } public void setTime(String time) { this.time = time; } public String getTemp() { return temp; } public String getWind_direction() { return wind_direction; } public String getWind_strength() { return wind_strength; } public String getHumidity() { return humidity; } public String getTime() { return time; } @Override public String toString() { return "SkEntity{" + "temp='" + temp + '\'' + ", wind_direction='" + wind_direction + '\'' + ", wind_strength='" + wind_strength + '\'' + ", humidity='" + humidity + '\'' + ", time='" + time + '\'' + '}'; } } public static class TodayEntity { @Override public String toString() { return "TodayEntity{" + "temperature='" + temperature + '\'' + ", weather='" + weather + '\'' + ", weather_id=" + weather_id + ", wind='" + wind + '\'' + ", week='" + week + '\'' + ", city='" + city + '\'' + ", date_y='" + date_y + '\'' + ", dressing_index='" + dressing_index + '\'' + ", dressing_advice='" + dressing_advice + '\'' + ", uv_index='" + uv_index + '\'' + ", comfort_index='" + comfort_index + '\'' + ", wash_index='" + wash_index + '\'' + ", travel_index='" + travel_index + '\'' + ", exercise_index='" + exercise_index + '\'' + ", drying_index='" + drying_index + '\'' + '}'; } private String temperature; private String weather; private WeatherIdEntity weather_id; private String wind; private String week; private String city; private String date_y; private String dressing_index; private String dressing_advice; private String uv_index; private String comfort_index; private String wash_index; private String travel_index; private String exercise_index; private String drying_index; public void setTemperature(String temperature) { this.temperature = temperature; } public void setWeather(String weather) { this.weather = weather; } public void setWeather_id(WeatherIdEntity weather_id) { this.weather_id = weather_id; } public void setWind(String wind) { this.wind = wind; } public void setWeek(String week) { this.week = week; } public void setCity(String city) { this.city = city; } public void setDate_y(String date_y) { this.date_y = date_y; } public void setDressing_index(String dressing_index) { this.dressing_index = dressing_index; } public void setDressing_advice(String dressing_advice) { this.dressing_advice = dressing_advice; } public void setUv_index(String uv_index) { this.uv_index = uv_index; } public void setComfort_index(String comfort_index) { this.comfort_index = comfort_index; } public void setWash_index(String wash_index) { this.wash_index = wash_index; } public void setTravel_index(String travel_index) { this.travel_index = travel_index; } public void setExercise_index(String exercise_index) { this.exercise_index = exercise_index; } public void setDrying_index(String drying_index) { this.drying_index = drying_index; } public String getTemperature() { return temperature; } public String getWeather() { return weather; } public WeatherIdEntity getWeather_id() { return weather_id; } public String getWind() { return wind; } public String getWeek() { return week; } public String getCity() { return city; } public String getDate_y() { return date_y; } public String getDressing_index() { return dressing_index; } public String getDressing_advice() { return dressing_advice; } public String getUv_index() { return uv_index; } public String getComfort_index() { return comfort_index; } public String getWash_index() { return wash_index; } public String getTravel_index() { return travel_index; } public String getExercise_index() { return exercise_index; } public String getDrying_index() { return drying_index; } public static class WeatherIdEntity { private String fa; private String fb; public void setFa(String fa) { this.fa = fa; } public void setFb(String fb) { this.fb = fb; } public String getFa() { return fa; } public String getFb() { return fb; } } } public static class FutureEntity { private String temperature; private String weather; /** * fa : 01 * fb : 01 */ private WeatherIdEntity weather_id; private String wind; private String week; private String date; public void setTemperature(String temperature) { this.temperature = temperature; } public void setWeather(String weather) { this.weather = weather; } public void setWeather_id(WeatherIdEntity weather_id) { this.weather_id = weather_id; } public void setWind(String wind) { this.wind = wind; } public void setWeek(String week) { this.week = week; } public void setDate(String date) { this.date = date; } public String getTemperature() { return temperature; } public String getWeather() { return weather; } public WeatherIdEntity getWeather_id() { return weather_id; } public String getWind() { return wind; } public String getWeek() { return week; } public String getDate() { return date; } public static class WeatherIdEntity { private String fa; private String fb; public void setFa(String fa) { this.fa = fa; } public void setFb(String fb) { this.fb = fb; } public String getFa() { return fa; } public String getFb() { return fb; } @Override public String toString() { return "WeatherIdEntity{" + "fa='" + fa + '\'' + ", fb='" + fb + '\'' + '}'; } } @Override public String toString() { return "FutureEntity{" + "temperature='" + temperature + '\'' + ", weather='" + weather + '\'' + ", weather_id=" + weather_id + ", wind='" + wind + '\'' + ", week='" + week + '\'' + ", date='" + date + '\'' + '}'; } } @Override public String toString() { return "ResultEntity{" + "sk=" + sk + ", today=" + today + ", future=" + future + '}'; } } @Override public String toString() { return "WeatherData{" + "resultcode='" + resultcode + '\'' + ", reason='" + reason + '\'' + ", result=" + result + ", error_code=" + error_code + '}'; }
5)model层
public interface WeatherModel { Subscription getWeatherData(String format, String city);}
public class WeatherModelImp implements WeatherModel { private WeatherOnListener mWeatherOnListener; public WeatherModelImp(WeatherOnListener mWeatherOnListener) { this.mWeatherOnListener = mWeatherOnListener; } @Override public Subscription getWeatherData(String format, String city) { //com.example.admin.rxretrofitmvp.api.APIManager Observable<WeatherData> request = com.example.admin.rxretrofitmvp.api.APIManager.getWeatherData(format, city).cache(); Subscription sub = request.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<WeatherData>() { @Override public void call(WeatherData weatherData) { mWeatherOnListener.onSuccess(weatherData); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { mWeatherOnListener.onFailure(throwable); } }); return sub; }
6)Present层
public class BasePesenter { protected CompositeSubscription mCompositeSubscription; //RXjava取消注册,以避免内存泄露 public void onUnsubscribe() { if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) { mCompositeSubscription.unsubscribe(); } } //RXjava注册 public void addSubscription(Subscription subscriber) { if (mCompositeSubscription == null) { mCompositeSubscription = new CompositeSubscription(); } mCompositeSubscription.add(subscriber); } }
public abstract class WeatherPresenter extends BasePesenter { public abstract void getWeatherData(String format, String city);}
public class WeatherPresenterImp extends WeatherPresenter implements WeatherOnListener{ /** * WeatherModel和WeatherView都是通过接口来实现,这就Java设计原则中依赖倒置原则使用 */ private WeatherModel mWeatherModel; private WeatherView mWeatherView; public WeatherPresenterImp( WeatherView mWeatherView) { this.mWeatherModel = new WeatherModelImp(this); this.mWeatherView = mWeatherView; } @Override public void getWeatherData(String format, String city) { mWeatherView.showProgress(); addSubscription(mWeatherModel.getWeatherData(format,city)); } @Override public void onSuccess(WeatherData s) { mWeatherView.loadWeather(s); mWeatherView.hideProgress(); Log.d("-------", "onSuccess() called with: " + "s = [" + s.toString() + "]"); } @Override public void onFailure(Throwable e) { mWeatherView.hideProgress(); Log.d("-------", "onFailure" + e.getMessage()); } }
7)view层
public interface WeatherView { void showProgress(); void hideProgress(); void loadWeather(WeatherData weatherData);}
8)监听器
public interface WeatherOnListener { void onSuccess(WeatherData s); void onFailure(Throwable e);}
9)LodingHelper
public class LoadingUIHelper { private static Dialog dialog; public static void showDialogForLoading(final Context context, String tipContext){ final AlertDialog.Builder builder = new AlertDialog.Builder(context); dialog = builder.create(); builder.setTitle(""); builder.setMessage(tipContext); builder.setIcon(R.mipmap.ic_launcher); builder.setNegativeButton("取消",new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialogInterface, int i) { dialog.dismiss(); } }); builder.setPositiveButton("確定",new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialogInterface, int i) { } }); builder.show(); } public static void hideDialogForLoading(){ if(dialog != null){ dialog.dismiss(); } } }
10)在Activity中处理
public class MainActivity extends AppCompatActivity implements WeatherView{ private WeatherPresenterImp mWeatherPresenter; private TextView textView1; private TextView textView2; private TextView textView3; private TextView textView4; private TextView textView5; private TextView textView6; private TextView textView7; private TextView textView8; private TextView textView9; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWeatherPresenter = new WeatherPresenterImp(this); mWeatherPresenter.getWeatherData("2", "苏州"); textView1 = (TextView) findViewById(R.id.textView1); textView2 = (TextView) findViewById(R.id.textView2); textView3 = (TextView) findViewById(R.id.textView3); textView4 = (TextView) findViewById(R.id.textView4); textView5 = (TextView) findViewById(R.id.textView5); textView6 = (TextView) findViewById(R.id.textView6); textView7 = (TextView) findViewById(R.id.textView7); textView8 = (TextView) findViewById(R.id.textView8); textView9 = (TextView) findViewById(R.id.textView9); } @Override public void showProgress() { LoadingUIHelper.showDialogForLoading(this,"获取数据"); } @Override public void hideProgress() { LoadingUIHelper.hideDialogForLoading(); Toast.makeText(this,"服务器异常",Toast.LENGTH_SHORT).show(); mWeatherPresenter.onUnsubscribe(); } @Override public void loadWeather(WeatherData weatherData) { Log.d("weatherData", "weatherData==" + weatherData.toString()); textView1.setText("城市:"+weatherData.getResult().getToday().getCity()); textView2.setText("日期:"+weatherData.getResult().getToday().getWeek()); textView3.setText("今日温度:"+weatherData.getResult().getToday().getTemperature()); // textView4.setText("天气标识:" +WeatherIDUtils.transfer(weatherData.getResult().getToday().getWeather_id().getFa())); textView5.setText("穿衣指数:" + weatherData.getResult().getToday().getDressing_advice()); textView6.setText("干燥指数:"+weatherData.getResult().getToday().getDressing_index()); textView7.setText("紫外线强度:"+weatherData.getResult().getToday().getUv_index()); textView8.setText("穿衣建议:"+weatherData.getResult().getToday().getDressing_advice()); textView9.setText("旅游指数:"+weatherData.getResult().getToday().getTravel_index()); } @Override protected void onDestroy() { super.onDestroy(); //取消注册 mWeatherPresenter.onUnsubscribe(); } }