Web的架構經過量年的發展已非常成熟了,我們經常使用的SSM,SSH等等,架構都非常標準。個人認為,Web服務邏輯比較清晰,目的明確,流程也相對固定,從服務器收到要求開始,經過1系列的的攔截器,過濾器->被轉發到控制器手中->控制器再調用服務->服務再調用DAO獲得想要的數據->最后把數據返回給web層。哪怕中間增加1些東西,如緩存甚么的。他的模型仍然是以用戶要求的線程為生命周期,經過1個個切面(層)的結構,感覺類似于流水線的結構吧。
而Android App則有所不同,他沒有像用戶要求這樣1個統1的動身點,最接近的多是來自于UI的事件,但是遠不單單于此。根據app不同的需求,其結構也會千差萬別,所以很難有較為統1的架構。
但是客戶端類app確切是較為常見的App類型,其結構還是有跡可循的。
1.MVC
mvc現在是用的人最多,同時也是Android官方的設計模式,可以說Android App本來就是MVC的,View對應布局文件xml,Controller對應Activity,Model對應數據模型。
這類App1般會定義1個BaseActivity,BaseActivity內部實現了網絡的異步要求,本地數據的存儲加,數據庫訪問載等復用性較強的邏輯。邏輯控制則在對應的Activity中實現。
MVC的缺點:Activity過于臃腫,常常1個Activity幾百上千行代碼。View層的XML控制力其實非常弱,眾多的View處理還是要放在Activity進行,這樣的話,Activity就既包括了View又包括了Controller,耦合高,不利于測試擴大,可讀性也變差。
2.MVVM
用過VS開發過.net的人肯定知道MVVM的強大的地方,僅需要點點鼠標,數據庫里的信息和View的控件顯示就被簡單的綁定了。
而Android的數據綁定個人認為還是不夠成熟的,用法長這樣android:text=”@{user.username}”/>
在xml里面配置數據模型。1是控制力不夠,2是部份邏輯需要放到數據Model里處理。
3.MVP
最近在Android上利用比較火的模式。相較于MVC,MVP將Activity中的業務邏輯抽取出來,將Activity,Fragment等作為View層,專職與界面交互。而Presenter則負責數據Model的填充和View層的顯示。View不直接與Model交互,解耦了Actiity。
這樣可以做到邏輯和界面交互的完全分離,方便測試,界面升級等。代碼的可讀性也大大增加。
對我自己,在我自己架構項目的時候確切遇到了1些困難,也有選擇障礙,經過1番思考。我有了自己的見解,整體還是偏向于MVP,但又有些不同。多是MVP+MVVM(偽)吧。
首先是包結構
1.View層
view層依照Android組件的分類,可使用接口通訊,也能夠使用類似EventBus的事件框架進行通訊
Action包就是事件實體,這里使用的是我自己實現的事件框架。
2.Model層
model層包括數據模型,實體類,和dao,http等數據獲得得代碼?;氐舻脑捒墒褂媒涌?,也能夠使用事件框架。另外緩存也放在這里。
3.Presenter
包括Base(自己實現的Presenter框架,其實就是將Activity抽取了1層),Service包是Android組件Service
Impl是業務的實現,下面1堆I開頭的是業務接口。
這里講1下Base,Base相當于控制器,拿登陸來舉例,1個登陸操作可能觸及多個界面,多個業務邏輯單元。比如登陸,首先是要求網絡的邏輯,除此以外,登陸成功后,需要對會話,用戶基礎信息等進行持久化;還有控制器需要控制各個界面的刷新。這些都是在控制器Base中完成的,他是1組邏輯的控制單元,負責1個典型的業務,比如說登陸。
下面的重點是業務接口,例如登陸ILogin,如果自己實現,你需要寫1大堆的東西,網絡要求,異步處理,Handler,異常處理,JSON解析,顯示,洋洋灑灑最少上百行了。如果你的項目需要快速上線怎樣辦?同時你又想保持項目的邏輯結構,以后做更細致的改進,這時候候就體現了接口的重要性。這里安利我1個比較快速的實現鏈接也是我實現的1個小框架。
用起來畫風是這樣的。
public class LoginPresenter extends Presenter implements ActivityOnCreatedListener,ICallBack<User,Throwable>{
private ILogin ILogin;
@Override
protected void onContextChanged(ContextChangeEvent event) {
}
@Override
public void OnPresentInited(Context context) {
ILogin = HttpProxyFactory.With(ILogin.class).setCallBack(this).setViewContent(getActivityRaw()).establish();
getActivityInter().setOnCreateListener(this);
}
@Override
public void ActivityOnCreated(Bundle savedInstanceState, final Activity activity) {
getActivityInter().getView(R.id.btn_login)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginActivity ac = (LoginActivity) activity;
ac.progressDialog.show();
getActivityInter().getView(R.id.btn_login).setClickable(false);
EditText name = getActivityInter().getView(R.id.login_name);
EditText pass = getActivityInter().getView(R.id.login_pass);
ILogin.login(name.getText().toString(),pass.getText().toString());
}
});
}
@Override
public void onSuccess(User user) {
Log.e("gy",user.toString());
getActivityRaw().finish();
navTo(HomeActivity.class);
}
@Override
public void onFailed(Throwable throwable) {
ILoginCallBack callBack = (ILoginCallBack) getContext();
callBack.onLogFailed(throwable.getMessage());
}
}
你可以發現ILogin = HttpProxyFactory.With(ILogin.class).setCallBack(this).setViewContent(getActivityRaw()).establish();
這么簡單,你的ILogin業務接口就被框架實現了,簡單的說就是用了動態代理,框架根據你在接口上綁定的注解信息,幫你動態代理處1個業務實現對象。幫你包辦了網絡要求,異步處理,異步回掉,異常處理,JSON解析,顯示等1大堆操作。
如何綁定你的需求?
ILogin接口張這樣的
public interface ILogin {
@HttpSrcMethod(url = "/store/login",session = Global.SKEY_UNLOGIN,filters = ResultFilter.class)
public User login(@Param("tel")String name,@Param("password")String passwd);
}
返回值模型Model User比較簡單,我們換1個比較典型的
@JsonOrm
public class ResultArea implements IHandler{
@JsonString("name")
private String name;
@JsonString("id")
private String id;
@BindListView(CityPickerActivity.ListViewId)
@JsonSet(name = "areas",clazz = Area.class)
private List<Area> child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Area> getChild() {
return child;
}
public void setChild(List<Area> child) {
this.child = child;
}
@Override
public void handler() throws Exception {
if (child == null)
child = new ArrayList<>();
child.add(0,new Area(name,id));
}
}
注解幾近映照了你所有的業務接口協議,包括要求參數,URL,頭,返回值的json映照,對應View層的視圖顯示等等。
使用這類臨時解決方案以后,后期如有需求,自己再選用其它框架,或自己實現業務接口便可,根本不需要動其他模塊,從而保證了可擴大性。
上一篇 仿映客送禮特效