版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24675479/article/details/79863215
MVC使用
ServiceApi接口
public interface ServiceApi {
// 接口涉及到解耦,userLogin 方法是没有任何实现代码
@POST("loginuser")// 登录接口 GET(相对路径)
@FormUrlEncoded
Observable<Result<UserInfo>> queryUserInfo(
// @Query(后台需要解析的字段)
@Field("token") String token);
}
UserInfo用户信息
public class UserInfo {
public String au_nickname;
public String au_sex;
@Override
public String toString() {
return "UserInfo{" +
"userName='" + au_nickname + '\'' +
", userPwd='" + au_sex + '\'' +
'}';
}
}
RetrofitClient
public class RetrofitClient {
private final static ServiceApi mServiceApi;
static {
OkHttpClient okHttpClient = new OkHttpClient
.Builder()
.addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.e("TAG",message);
}
}).setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
// 各种套路和招式 ,发现问题解决问题,基础,源码的理解
// 1. 没打印?
// 2. 数据格式不一致?成功 data 是个对象,不成功 data 是个 String
// 3. 还有就是 baseUrl 问题? (Retrofit 找不到任何入口可以修改)
// 3.1 不同的 baseUrl 构建不同的 Retrofit 对象 (直不应该首选)
// 3.2 自己想办法,取巧也行走漏洞
Retrofit retrofit = new Retrofit.Builder()
// 访问后台接口的主路径
.baseUrl("http://ppw.zmzxd.cn/index.php/api/v1/")
// 添加解析转换工厂,Gson 解析,Xml解析,等等
.addConverterFactory(GsonConverterFactory.create())
// 添加 OkHttpClient,不添加默认就是 光杆 OkHttpClient
.client(okHttpClient)
// 支持RxJava Call -> Obsevrable 怎么做到的? 1 2 采用了 Adapter 设计模式
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
// 创建一个 实例对象
mServiceApi = retrofit.create(ServiceApi.class);
}
public static ServiceApi getServiceApi() {
return mServiceApi;
}
public static <T> Observable.Transformer<Result<T>, T> transformer() {
return new Observable.Transformer<Result<T>, T>() {
@Override
public Observable<T> call(Observable<Result<T>> resultObservable) {
// resultObservable -> Observable<Result<UserInfo>> userLogin
return resultObservable.flatMap(new Func1<Result<T>, Observable<T>>() {
@Override
public Observable<T> call(Result<T> tResult) {
// 解析不同的情况返回
if(tResult.isOk()){
// 返回成功
return createObservable(tResult.data);
}else {
// 返回失败
return Observable.error(new ErrorHandle.ServiceError("",tResult.getMsg()));
}
}
}).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
};
}
private static <T> Observable<T> createObservable(final T data) {
return Observable.create(new Action1<Emitter<T>>() {
@Override
public void call(Emitter<T> tEmitter) {
tEmitter.onNext(data);
tEmitter.onCompleted();
}
}, Emitter.BackpressureMode.NONE);
}
}
BaseResult
public class BaseResult {
String bol;
String msg;
public String getMsg() {
return msg;
}
public String getCode() {
return bol;
}
public boolean isOk(){
return "true".equals(bol);
}
}
Result
public class Result<T> extends BaseResult{
public T data;
}
ErrorHandle
public class ErrorHandle {
public static class ServiceError extends Throwable{
String errorCode;
public ServiceError(String errorCode, String errorMsg) {
super(errorMsg);
this.errorCode = errorCode;
}
}
}
BaseSubscriber
public abstract class BaseSubscriber<T> extends Subscriber<T> {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
// e :网络异常,解析异常,结果处理过程中异常
e.printStackTrace();
if(e instanceof ErrorHandle.ServiceError){
ErrorHandle.ServiceError serviceError = (ErrorHandle.ServiceError) e;
onError("",serviceError.getMessage());
}else {
// 自己处理
onError("","未知异常");
}
}
protected abstract void onError(String errorCode, String errorMessage);
}
使用
public class MainActivity extends AppCompatActivity {
private TextView mUserInfoTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// OkHttp +RxJava + Retrofit 这样写代码行不行? 1 ,2 ,
mUserInfoTv = (TextView) findViewById(R.id.user_info_tv);
// 1. MVC 两个地方:个人主页,编辑资料,MVC意味着 ,这些代码是需要写很多份
// 2. 如果团队协作,多人开发,那么这个页面(编辑资料)一般都是一个人在做,项目比较紧凑的时候,不好分配人
// 3. 如果某些界面需求变更的情况下,不好定位,或者说出了 Bug 的情况下不怎么好修改(代码多)
RetrofitClient.getServiceApi()
.queryUserInfo("5daefee2ce7f9208d465fab4ae6e40c2")
// .subscribeOn().observeOn().subscribe()
// Subscriber 封装一下
// 第二个坑 , 坑我们 返回值都是一个泛型,转换返回值泛型
.compose(RetrofitClient.<UserInfo>transformer())
// 注册完了要登录
.subscribe(new BaseSubscriber<UserInfo>() {
@Override
protected void onError(String errorCode, String errorMessage) {
toast(errorMessage);
}
@Override
public void onNext(UserInfo userInfo) {
// 这个处理代码不一样
mUserInfoTv.setText(userInfo.toString());
}
});
}
private void toast(String text) {
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
private void log(String text) {
Log.e("TAG->Result", text);
}
}
MVP第一个版本
UserInfoContract协议类,可有可无
public class UserInfoContract {
interface UserInfoView{
// 1.正在加载中
// 2.获取出错了
// 3.成功了要显示数据
void onLoading();
void onError();
void onSucceed(UserInfo userInfo);
}
// user presenter 层
interface UserInfoPresenter {
void getUsers(String token);
}
interface UserInfoModel{
Observable<UserInfo> getUsers(String token);
}
}
UserInfoModel:M层
public class UserInfoModel implements UserInfoContract.UserInfoModel {
@Override
public Observable<UserInfo> getUsers(String token) {
return RetrofitClient.getServiceApi()
.queryUserInfo("5daefee2ce7f9208d465fab4ae6e40c2")
// .subscribeOn().observeOn().subscribe()
// Subscriber 封装一下
// 第二个坑 , 坑我们 返回值都是一个泛型,转换返回值泛型
.compose(RetrofitClient.<UserInfo>transformer());
}
}
UserInfoPresenter:P层
class UserInfoPresenter implements UserInfoContract.UserInfoPresenter {
UserInfoContract.UserInfoView mView;
UserInfoContract.UserInfoModel mModel;
public UserInfoPresenter(UserInfoContract.UserInfoView view) {
this.mView=view;
mModel=new UserInfoModel();
}
@Override
public void getUsers(String token) {
mModel.getUsers(token).subscribe(new BaseSubscriber<UserInfo>() {
@Override
protected void onError(String code, String message) {
mView.onError();
}
@Override
public void onNext(UserInfo userInfo) {
mView.onSucceed(userInfo);
}
});
}
}
使用
public class MainActivity extends AppCompatActivity implements UserInfoContract.UserInfoView {
private TextView mUserInfoTv;
private UserInfoPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// OkHttp +RxJava + Retrofit 这样写代码行不行? 1 ,2 ,
mUserInfoTv = (TextView) findViewById(R.id.user_info_tv);
// 1. MVC 两个地方:个人主页,编辑资料,MVC意味着 ,这些代码是需要写很多份
// 2. 如果团队协作,多人开发,那么这个页面(编辑资料)一般都是一个人在做,项目比较紧凑的时候,不好分配人
// 3. 如果某些界面需求变更的情况下,不好定位,或者说出了 Bug 的情况下不怎么好修改(代码多)
mPresenter=new UserInfoPresenter(this);
mPresenter.getUsers("ed6b0f7f34dd8cf7b003e40691457175");
}
@Override
public void onLoading() {
}
@Override
public void onError() {
}
@Override
public void onSucceed(UserInfo userInfo) {
// 成功
mUserInfoTv.setText(userInfo.toString());
}
}
MVP第二个版本:解决第一个版本存在的一个当我们进去然后直接退出程序的时候,本不应该继续加载数据,这时候
//这个方法不能满足我们
public UserInfoPresenter(UserInfoContract.UserInfoView view) {
this.mView=view;
mModel=new UserInfoModel();
}
UserInfoPresenter修改
class UserInfoPresenter implements UserInfoContract.UserInfoPresenter {
UserInfoContract.UserInfoView mView;
UserInfoContract.UserInfoModel mModel;
public UserInfoPresenter() {
mModel = new UserInfoModel();
}
public void attachView(UserInfoContract.UserInfoView view) {
mView = view;
}
public void detachView() {
mView = null;
}
@Override
public void getUsers(String token) {
mModel.getUsers(token).subscribe(new BaseSubscriber<UserInfo>() {
@Override
protected void onError(String code, String message) {
if (mView != null) {
mView.onError();
}
}
@Override
public void onNext(UserInfo userInfo) {
if(mView!=null)
mView.onSucceed(userInfo);
}
});
}
}
MainActivity进行相应修改
public class MainActivity extends AppCompatActivity implements UserInfoContract.UserInfoView {
private TextView mUserInfoTv;
private UserInfoPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// OkHttp +RxJava + Retrofit 这样写代码行不行? 1 ,2 ,
mUserInfoTv = (TextView) findViewById(R.id.user_info_tv);
// 1. MVC 两个地方:个人主页,编辑资料,MVC意味着 ,这些代码是需要写很多份
// 2. 如果团队协作,多人开发,那么这个页面(编辑资料)一般都是一个人在做,项目比较紧凑的时候,不好分配人
// 3. 如果某些界面需求变更的情况下,不好定位,或者说出了 Bug 的情况下不怎么好修改(代码多)
mPresenter=new UserInfoPresenter();
mPresenter.getUsers("ed6b0f7f34dd8cf7b003e40691457175");
mPresenter.attachView(this);
}
@Override
public void onLoading() {
}
@Override
public void onError() {
}
@Override
public void onSucceed(UserInfo userInfo) {
// 成功
mUserInfoTv.setText(userInfo.toString());
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView();
}
}
MVP第三个版本:我们每次的时候都需要添加attach和detach方法太麻烦
BaseView
public interface BaseView {
}
BasePresenter
public class BasePresenter <T extends BaseView> {
private T mView;
public void attachView(T view) {
mView = view;
}
public void detachView() {
mView = null;
}
public T getView() {
return mView;
}
}
BaseMvpActivity:基类activity
public abstract class BaseMvpActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
private P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView();
mPresenter=createPresenter();
mPresenter.attachView(this);
initView();
initData();
}
protected abstract P createPresenter();
protected abstract void initData();
protected abstract void initView();
protected abstract void setContentView();
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView();
}
public P getPresenter() {
return mPresenter;
}
}
UserInfoPresenter进行修改
class UserInfoPresenter extends BasePresenter<UserInfoContract.UserInfoView> implements UserInfoContract.UserInfoPresenter {
UserInfoContract.UserInfoModel mModel;
public UserInfoPresenter() {
mModel = new UserInfoModel();
}
@Override
public void getUsers(String token) {
mModel.getUsers(token).subscribe(new BaseSubscriber<UserInfo>() {
@Override
protected void onError(String code, String message) {
if (getView() != null) {
getView().onError();
}
}
@Override
public void onNext(UserInfo userInfo) {
if(getView()!=null)
getView().onSucceed(userInfo);
}
});
}
}
MainActivity再次进行修改
public class MainActivity extends BaseMvpActivity<UserInfoPresenter> implements UserInfoContract.UserInfoView {
private TextView mUserInfoTv;
@Override
protected UserInfoPresenter createPresenter() {
return new UserInfoPresenter();
}
@Override
protected void initData() {
getPresenter().getUsers("ed6b0f7f34dd8cf7b003e40691457175");
}
@Override
protected void initView() {
mUserInfoTv = (TextView) findViewById(R.id.user_info_tv);
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_main);
}
@Override
public void onLoading() {
}
@Override
public void onError() {
}
@Override
public void onSucceed(UserInfo userInfo) {
// 成功
mUserInfoTv.setText(userInfo.toString());
}
}
MVP第四次版本:每次呢,都需要判断是否为空,也很麻烦( if (getView() != null) ),可以使用动态代理
BasePresenter修改
public class BasePresenter <T extends BaseView> {
private SoftReference<T> mViewReference;
private T mProxyView;
public void attachView(final T view) {
mViewReference = new SoftReference<T>(view);
mProxyView= (T) Proxy.newProxyInstance(view.getClass().getClassLoader()
, view.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(mViewReference==null||mViewReference.get()==null){
return null;
}
// 没解绑执行的是原始被代理 View 的方法
return method.invoke(mViewReference.get(),args);
}
});
}
public void detachView() {
this.mViewReference.clear();
this.mViewReference = null;
this.mProxyView = null;
}
public T getView() {
return mProxyView;
}
}
MVP第五次版本:如果一个activity有多个presenter?new可以,但是不太好,可以使用注解,还有动态生成model类
BasePresenter动态生成model
public class BasePresenter<V extends BaseView,M extends BaseModel> {
// 目前两个两个公用方法 ,传递的时候 会有不同的 View ,怎么办?泛型
private WeakReference<V> mViewReference;
private V mProxyView;
// View 一般都是 Activity ,涉及到内存泄漏,但是已经解绑了不会,如果没解绑就会泄漏
// 最好还是用一下软引用
// 动态创建的 model 的对象
private M mModel;
// View 有一个特点,都是接口
// GC 回收的算法机制(哪几种)标记清楚法
public void attach(V view){
this.mViewReference = new WeakReference<V>(view);
// 用代理对象
mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 执行这个方法 ,调用的是被代理的对象
if(mViewReference == null||mViewReference.get() == null) {
return null;
}
// 没解绑执行的是原始被代理 View 的方法
return method.invoke(mViewReference.get(),args);
}
});
// 创建我们的 Model ,动态创建? 获取 Class 通过反射 (Activity实例创建的?class 反射创建的,布局的 View 对象怎么创建的?反射)
// 获取 Class 对象
Type[] params = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
try {
// 最好要判断一下类型
mModel = (M) ((Class)params[1]).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public void detach(){
// 不解绑的问题 Activity -> Presenter ,Presenter 持有了 Activity 应该是会有内存泄漏
this.mViewReference.clear();
this.mViewReference = null;
// 注释
// this.mProxyView = null;
}
public M getModel() {
return mModel;
}
public V getView() {
return mProxyView;
}
}
InjectPresenter注解
@Target(ElementType.FIELD)// 属性
@Retention(RetentionPolicy.RUNTIME)// 运行时
public @interface InjectPresenter {
}
BaseMvpActivity进行修改
public abstract class BaseMvpActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
private P mPresenter;
private List<BasePresenter> mPresenters;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView();
mPresenters = new ArrayList<>();
// 创建 P,创建只能交给 子类,每个 Activity 都不一样
mPresenter = createPresenter();
mPresenter.attach(this);
// 这个地方要去注入 Presenter 通过反射 (Dagger) soEasy
//如TextView
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
if(injectPresenter != null){
// 创建注入
Class<? extends BasePresenter> presenterClazz = null;
// 自己去判断一下类型? 获取继承的父类,如果不是 继承 BasePresenter 抛异常
try {
presenterClazz = (Class<? extends BasePresenter>) field.getType();
} catch (Exception e){
// 乱七八糟一些注入
throw new RuntimeException("No support inject presenter type " + field.getType().getName());
}
try {
// 创建 Presenter 对象
BasePresenter basePresenter = presenterClazz.newInstance();
// 并没有解绑,还是会有问题,这个怎么办?1 2
basePresenter.attach(this);
// 设置
field.setAccessible(true);
field.set(this,basePresenter);
mPresenters.add(basePresenter);
} catch (Exception e) {
e.printStackTrace();
}
}
}
initView();
initData();
}
// 由子类去实现创建
protected abstract P createPresenter();
protected abstract void initData();
protected abstract void initView();
protected abstract void setContentView();
@Override
public void onDestroy() {
super.onDestroy();
// 一定要解绑
for (BasePresenter presenter : mPresenters) {
presenter.detach();
}
mPresenter.detach();
}
public P getPresenter() {
return mPresenter;
}
}
MVP第六次版本:静态代理设计模式封装一下
IMvpProxy代理接口
public interface IMvpProxy {
void bindAndCreatePresenter();// 一个是和创建绑定
void unbindPresenter();// 一个是解绑
}
MvpProvxyImpl实现类
public class MvpProxyImpl<V extends BaseView> implements IMvpProxy {
private V view;
private List<BasePresenter> mPresenters;
public MvpProxyImpl(V view) {
this.view = view;
mPresenters = new ArrayList<>();
}
@Override
public void bindAndPresenter() {
//注入Presenter
//Activity,Fragment,ViewGroup
Field[] fields = view.getClass().getDeclaredFields();
for (Field field : fields) {
InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
if (injectPresenter != null) {
// 创建注入
Class<? extends BasePresenter> presenterClazz = null;
// 自己去判断一下类型? 获取继承的父类,如果不是 继承 BasePresenter 抛异常
try {
//编译器会在运行的时候会对我们的泛型进行擦除(一般是针对系统的)
//没编译前的一种约束,写代码的时候只能是同一种类型
//泛型擦除一般是针对系统的,我们自己指定的泛型信息一般会保存
presenterClazz = (Class<? extends BasePresenter>) field.getType();//泛型擦除
if (!BasePresenter.class.isAssignableFrom(presenterClazz)) {
//判断Class是否继承自BasePresenter,如果不是抛异常
throw new RuntimeException("No support inject presenter type " + presenterClazz.getName());
}
} catch (Exception e) {
// 乱七八糟一些注入,没有报错
throw new RuntimeException("No support inject presenter type " + field.getType().getName());
}
BasePresenter basePresenter = null;
try {
// 创建 Presenter 对象
basePresenter = presenterClazz.newInstance();
basePresenter.attach(view);
// 设置
field.setAccessible(true);
field.set(view, basePresenter);
mPresenters.add(basePresenter);
} catch (Exception e) {
e.printStackTrace();
}
//检查我们的view层,是否实现了BasePresenter的view接口
checkView(basePresenter);
}
}
}
private void checkView(BasePresenter basePresenter) {
//要拿到view层的所有接口和basePresenter中的所有view接口,view层没有实现就抛出异常
Type[] params = ((ParameterizedType) basePresenter.getClass().getGenericSuperclass()).getActualTypeArguments();
Class viewClazz = ((Class) params[0]);
Class<?>[] interfaces = view.getClass().getInterfaces();
boolean isImplementsView=false;
for (Class<?> anInterface : interfaces) {
if(anInterface.isAssignableFrom(viewClazz)){
isImplementsView=true;
}
}
if(!isImplementsView){
throw new RuntimeException(view.getClass().getSimpleName()+"View must implements"+viewClazz.getName());
}
}
@Override
public void unbindPresenter() {
// 一定要解绑
for (BasePresenter presenter : mPresenters) {
presenter.detach();
}
view = null;
}
}
ActivityMvpProxy,以后可能有FragmentMvpProvxy和VeiwGroup
public class ActivityMvpProxy<V extends BaseView> extends MvpProvxyImpl{
public ActivityMvpProxy(BaseView view) {
super(view);
}
}
BaseMvpActivity进行修改
public abstract class BaseMvpActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
private P mPresenter;
private ActivityMvpProxy mMvpProxy;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView();
// 创建 P,创建只能交给 子类,每个 Activity 都不一样
mPresenter = createPresenter();
mPresenter.attach(this);
mMvpProxy = createMvpProxy();
mMvpProxy.bindAndCreatePresenter();
initView();
initData();
}
protected ActivityMvpProxy createMvpProxy() {
if (mMvpProxy == null) {
mMvpProxy = new ActivityMvpProxy(this);
}
return mMvpProxy;
}
// 由子类去实现创建
protected abstract P createPresenter();
protected abstract void initData();
protected abstract void initView();
protected abstract void setContentView();
@Override
public void onDestroy() {
super.onDestroy();
mMvpProxy.unbindPresenter();
mPresenter.detach();
}
public P getPresenter() {
return mPresenter;
}
}
补充:GC垃圾回收
对象什么时候回收? 对象有没有死掉? 2种算法(判断对象需不需要回收)1. 引用计数法 ,2. GcRoot 可达分析算法
回收算法: 判断死了,回收(回收算法) 分为两步 (需要回收的对象加入队列,调用对象的 finalize 方法)
1. 标记清楚算法(效率低,节省一些内存)
2. 复制算法 (效率要高,浪费一些内存)
3. 标记整理算法
4. 分代算法
涉及GC 分带年龄,对象有年龄 新生代,老年代,永久代。 Class 头信息