public class BaseModel extends BaseRetrofit {
private static final String TAG = "BaseModel";
protected CygApi mServletApi; //所有的注解接口
protected Map<String, String> mParams = new HashMap<>();
public BaseModel() {
super();
mServletApi = mRetrofit.create(CygApi.class);
}
//獲取公共參數(shù)
@Override
protected Map<String, String> getCommonMap() {
Map<String, String> commonMap = new HashMap<>();
commonMap.put("user_id", String.valueOf(UserDao.getInstance().getUserId()));
commonMap.put("token", String.valueOf(UserDao.getInstance().getToken()));
return commonMap;
}
//添加一個(gè)參數(shù)
protected void addParams(String key, String value) {
if (TextUtils.isEmpty(key)) {
Log.e(TAG, "the key is null");
return;
}
mParams.put(key, value);
}
//添加多個(gè)參數(shù)
protected void addParams(Map<String, String> params) {
if (null == params) {
Log.e(TAG, "the map is null");
return;
}
mParams.putAll(params);
}
}
這里網(wǎng)絡(luò)請求用的是 Retrofit+RxJava,這一部分我打算放到下一篇再講,在這個(gè) Base 類里面主要添加了公共參數(shù)和添加普通參數(shù)。來看看一個(gè)登錄的 Model
:
public class LoginModel extends BaseModel {
public static LoginModel getInstance() {
return getPresent(LoginModel.class);
}
public void execute(String phone, String password, Observer<User> observer) {
addParams("username", phone);
addParams("password", password);
Observable observable = mServletApi.getUserInfo(mParams).map(new HttpFunction());
toSubscribe(observable, observer);
}
}
(2)、
這里我是用的單例模式(其實(shí)我也不知道這樣寫單例會(huì)不會(huì)有錯(cuò),用類去實(shí)例化一個(gè)對象>_<我覺得沒啥問題,哈哈哈),然后execute
方法就是進(jìn)行網(wǎng)絡(luò)請求了,在Presenter
中調(diào)用這個(gè)方法就行了。然后我們來看一下BasePresenter
:
public class BasePresenter<VIEW> {
private WeakReference<VIEW> mViews;
protected void attachView(VIEW view) {
mViews = new WeakReference<VIEW>(view);
}
protected VIEW getView() {
return isViewAttached() ? mViews.get() : null;
}
private boolean isViewAttached() {
return null != mViews && null != mViews.get();
}
protected void detachView() {
if (null != mViews) {
mViews.clear();
mViews = null;
}
}
}
在 BasePresenter
里面我只是關(guān)注了 View
,按照 MVP
模式的理解,我們應(yīng)該在這個(gè)里面同時(shí)關(guān)注 View
和 Model
,確實(shí),很多 demo 都是這樣干的,但是LZ
前面是用的單例來寫 Model
,所以在 BasePresenter
里面就暫時(shí)先關(guān)注 View
,還有一點(diǎn)需要說明的是,這里對 View
使用的弱引用,我們都知道 View
通常來說都是很大只的存在,為了防止內(nèi)存泄漏,使用弱引用來及時(shí)釋放內(nèi)存。來看看一個(gè)登錄的 LoginPresenter
:
public class LoginPresenter extends BasePresenter<LoginView<User>> {
public LoginPresenter(LoginView<User> loginView) {
attachView(loginView);
}
public void getUserInfo(BaseImpl baseImpl) {
LoginModel.getInstance().execute(getView().getUserName(), getView().getPassword(), new CygBaseObserver<User>(baseImpl, "正在登錄") {
@Override
protected void onBaseNext(User data) {
UserInfo userInfo = new UserInfo();
userInfo.setId(data.getId());
userInfo.setUsername(getView().getUserName());
userInfo.setToken(data.getToken());
UserDao.getInstance().deleteAll(UserInfo.class);
UserDao.getInstance().insertObject(userInfo);
getView().onRequestSuccessData(data);
}
});
}
public void toMainActivity(Activity activity) {
activity.startActivity(new Intent(activity, MainActivity.class));
}
}
(3)、
在登錄的 LoginPresenter
中調(diào)用 LoginModel
進(jìn)行網(wǎng)絡(luò)請求,只返回一個(gè)成功的回調(diào),失敗的回調(diào)我們在內(nèi)部處理掉了,然后在回調(diào)成功之后做相應(yīng)的數(shù)據(jù)操作(該回調(diào)給 View
的就回調(diào)給 View
,該存本地的就存本地)。然后來看看我們的 View
:
public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginView<User> {
@BindView(R.id.al_et_user_name)
TextInputEditText alEtUserName;
@BindView(R.id.al_et_password)
TextInputEditText alEtPassword;
@Override
protected int layoutRes() {
return R.layout.activity_login;
}
@Override
protected LoginPresenter createPresenter() {
return new LoginPresenter(this);
}
@Override
protected void initView() {
}
@Override
public String getUserName() {
return alEtUserName.getText().toString().trim();
}
@Override
public String getPassword() {
return alEtPassword.getText().toString().trim();
}
@OnClick(R.id.al_btn_login)
public void onViewClicked() {
if (TextUtils.isEmpty(getUserName())) {
alEtPassword.setError("用戶名不能為空");
return;
}
if (TextUtils.isEmpty(getPassword())) {
alEtPassword.setError("密碼不能為空");
return;
}
mPresenter.getUserInfo(this);
}
@Override
public void onBackPressed() {
super.onBackPressed();
moveTaskToBack(true);
}
@Override
public void onRequestSuccessData(User data) {
mPresenter.toMainActivity(this);
}
}
在View
中,就是初始化Presenter
,然后各種調(diào)Presenter
中的方法,這里本來是可以在Presenter
中直接調(diào)用toMainActivity()
方法的,為了演示成功回調(diào)之后再回調(diào)給View
,這里我就多做了一步操作。好了,接下來我們來看看接口:
public interface BaseRequestContract<T> {
void onRequestSuccessData(T data);
}
這里寫了一個(gè)Base
接口,由于大多時(shí)候我們只關(guān)注成功的回調(diào)數(shù)據(jù),這里我也只寫了一個(gè)成功回調(diào)的方法(如果你有其他的需求,你可以在這里加一些公共的方法),如果你有需要的話你可以在子類中寫錯(cuò)誤回調(diào)的接口,接著我們來看看登錄的接口有哪些方法:
public interface LoginView<T> extends BaseRequestContract<T>{
String getUserName();
String getPassword();
}
這里我需要獲得用戶的輸入信息,所以只簡單定義了兩個(gè)方法用來獲取用戶名和密碼。到這里我們的MVP
模式就簡單封裝的差不多了,接下來我們來看一下最終的效果吧:

這里用eclipse+tomcat+mysql
簡單寫了一個(gè)登錄接口,這一部分LZ
在之前的博客中有詳細(xì)講解,如有興趣,請移步:
android開發(fā)怎么少的了后端(上)
android開發(fā)怎么少的了后端(中)
android開發(fā)怎么少的了后端(下)
好了,MVP
的基本封裝就講到這里,下一節(jié)我們再來講一下 Retrofit+Rxjava
的簡單封裝及使用,這里先奉上代碼:
MVP 主工程代碼 https://github.com/Jakemesdg/MVPDemo
MVP module工程代碼 https://github.com/Jakemesdg/cygmodule
可能很多人就會(huì)問了,為什么會(huì)有兩份呢,這里我給大家看看我的項(xiàng)目工程
