MVP模式的经典封装,android开发面试
先来观察下这个base类:先设置一泛型T,T为与presenter相关的view。BasePresenter中持有一个view的软引用。在关联方法中将view对象传入,并存入软引用中,创建获取、取消关联和判断方法。至于使用软引用,是为了防止所持的view都销毁了,但presenter一直持有,导致内存泄漏。
先来观察下这个base类:
先设置一泛型T,T为与presenter相关的view。BasePresenter中持有一个view的软引用。
在关联方法中将view对象传入,并存入软引用中,创建获取、取消关联和判断方法。
至于使用软引用,是为了防止所持的view都销毁了,但presenter一直持有,导致内存泄漏。
2、view的封装
view的封装,主要是BaseActivity和BaseFragment的封装。
2.1、BaseActivity
public abstract class BaseActivity<V, T extends BasePresenter> extends FragmentActivity {
public String TAG = getClass().getSimpleName() + “”;
protected T mPresenter;
public Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
…
initActivityView(savedInstanceState);
mContext = BaseActivity.this;
//创建presenter
mPresenter = createPresenter();
// presenter与view绑定
if (null != mPresenter) {
mPresenter.attachView((V) this);
}
findViewById();
getData();
}
/**
- 关于Activity的界面填充的抽象方法,需要子类必须实现
*/
protected abstract void initActivityView(Bundle savedInstanceState);
/**
- 加载页面元素
*/
protected abstract void findViewById();
/**
- 创建Presenter 对象
- @return
*/
protected abstract T createPresenter();
protected abstract void getData();
@Override
protected void onDestroy() {
super.onDestroy();
…
if (null != mPresenter) {
mPresenter.detachView();
}
}
}
BaseActivity设置两个泛型——V和P,明显地,分别代表对应的View和Presenter。
其持有一个BasePresenter,在onCreated方法中,使用createPresenter方法返回对应的BasePresenter的子类,我们就可以使用了。
这里注意一下view和presenter的处理:在onCreated中创建Presenter对象,但其内部的view软引用还是空;在onResume中关联view,此时presenter已经持有view的软引用;当然,还需要在onDestroy中取消关联。
至于其他的封装就不再介绍了,相信大家肯定还有更优的封装方法。
2.2 BaseFragment
public abstract class BaseFragment<V, T extends BasePresenter> extends Fragment {
public String TAG = getClass().getSimpleName() + “”;
private static final String STATE_SAVE_IS_HIDDEN = “STATE_SAVE_IS_HIDDEN”;
protected T mPresenter;
//定义一个View用来保存Fragment创建的时候使用打气筒工具进行的布局获取对象的存储
protected View view;
/**
- 当Fragment进行创建的时候执行的方法
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();//创建presenter
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(STATE_SAVE_IS_HIDDEN, isHidden());
}
/**
- 这个方法是关于Fragment完成创建的过程中,进行界面填充的方法,该方法返回的是一个view对象
- 在这个对象中封装的就是Fragment对应的布局
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = initFragmentView(inflater);
return view;
}
/**
- 这个方法当onCreateView方法中的view创建完成之后,执行
- 在inflate完成view的创建之后,可以将对应view中的各个控件进行查找findViewById
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
initFragmentChildView(view);
}
/**
- 这个方法是在Fragment完成创建操作之后,进行数据填充操作的时候执行的方法
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initFragmentData(savedInstanceState);
}
/**
- 完成打气筒操作
*/
protected abstract View initFragmentView(LayoutInflater inflater);
/**
- 进行findViewById的操作
- @param view 打气筒生成的View对象
*/
protected abstract void initFragmentChildView(View view);
/**
- 网络数据填充的操作
- @param savedInstanceState
*/
protected abstract void initFragmentData(Bundle savedInstanceState);
/**
- 创建Presenter对象
*/
protected abstract T createPresenter();
@Override
public void onResume() {
super.onResume();
if (null != mPresenter) {
mPresenter.attachView((V) this);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (null != mPresenter) {
mPresenter.detachView();
}
}
}
BaseFragment与BaseA类似就不再累赘。
3、Contract契约类
契约,顾名思义,规范定义,定义功能和模板。
在契约类中定义View的接口,Model的接口。因为Model将数据返给Presenter是使用回调方式,所以还需要再契约类中定义对应的回调。
具体看示例吧。
实战
这里我们以登录功能模块为例:
1、契约类
/**
- Description:
- Created by jia on 2017/12/20.
- 人之所以能,是相信能
*/
public class LoginContract {
public interface LoginView{
void onCheckFormatSuccess();
void onCheckFormatFail(String info);
void onLoginSuccess(Login login);
void onLoginFail(String errorInfo);
}
public interface LoginModel{
void login(String name,String password,LoginCallBack callBack);
}
public interface LoginCallBack{
void onSuccess(Login login);
void onFail(String errorInfo);
}
}
这里定义了登录页面的view接口、model接口和对应的回调。
在view中,只定义与UI展示的相关方法,如检查账号密码格式成功(失败)、登录成功(失败)等。
model负责数据请求,所以在接口中只定义了登录的方法。
回调定义了登录成功还是失败的方法。
2、Model实现类
/**
- Description: 登录 Model实现类
- Created by jia on 2017/12/20.
- 人之所以能,是相信能
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。



由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后送福利了,现在关注我并且加入群聊可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,欢迎加群探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
点击GitHub领取
330)]
最后送福利了,现在关注我并且加入群聊可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,欢迎加群探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
点击GitHub领取
[外链图片转存中…(img-qpdhKciu-1710669624330)]
更多推荐


所有评论(0)