編輯:關於Android編程
Web的架構經過多年的發展已經非常成熟了,我們常用的SSM,SSH等等,架構都非常標准。個人認為,Web服務邏輯比較清晰,目的明確,流程也相對固定,從服務器收到請求開始,經過一系列的的攔截器,過濾器->被轉發到控制器手中->控制器再調用服務->服務再調用DAO獲取想要的數據->最後把數據返回給web層。哪怕中間增加一些東西,如緩存什麼的。他的模型依然是以用戶請求的線程為生命周期,經過一個個切面(層)的結構,感覺類似於流水線的結構吧。
而Android App則有所不同,他沒有像用戶請求這樣一個統一的出發點,最接近的可能是來自於UI的事件,然而遠不僅僅於此。根據app不同的需求,其結構也會千差萬別,所以很難有較為統一的架構。
但是客戶端類app確實是較為常見的App類型,其結構還是有跡可循的。
一.MVC
mvc現在是用的人最多,同時也是Android官方的設計模式,可以說Android App原本就是MVC的,View對應布局文件xml,Controller對應Activity,Model對應數據模型。
這類App一般會定義一個BaseActivity,BaseActivity內部實現了網絡的異步請求,本地數據的存儲加,數據庫訪問載等復用性較強的邏輯。邏輯控制則在對應的Activity中實現。
MVC的缺點:Activity過於臃腫,往往一個Activity幾百上千行代碼。View層的XML控制力其實非常弱,眾多的View處理還是要放在Activity進行,這樣的話,Activity就既包含了View又包含了Controller,耦合高,不利於測試擴展,可讀性也變差。
二.MVVM
用過VS開發過.net的人肯定知道MVVM的強大之處,僅需要點點鼠標,數據庫裡的信息和View的控件顯示就被簡單的綁定了。
而Android的數據綁定個人認為還是不夠成熟的,用法長這樣android:text=”@{user.username}”/>
在xml裡面配置數據模型。一是控制力不夠,二是部分邏輯需要放到數據Model裡處理。
三.MVP
最近在Android上應用比較火的模式。相較於MVC,MVP將Activity中的業務邏輯抽取出來,將Activity,Fragment等作為View層,專職與界面交互。而Presenter則負責數據Model的填充和View層的顯示。View不直接與Model交互,解耦了Actiity。
這樣可以做到邏輯和界面交互的完全分離,方便測試,界面升級等。代碼的可讀性也大大增加。
對於我自己,在我自己架構項目的時候確實遇到了一些困難,也有選擇障礙,經過一番思考。我有了自己的見解,總體還是偏向於MVP,但又有些不同。可能是MVP+MVVM(偽)吧。
首先是包結構
1.View層
view層按照Android組件的分類,可以使用接口通信,也可以使用類似EventBus的事件框架進行通信
Action包就是事件實體,這裡使用的是我自己實現的事件框架。
2.Model層
model層包含數據模型,實體類,以及dao,http等數據獲取得代碼。回掉的話可以使用接口,也可以使用事件框架。另外緩存也放在這裡。
3.Presenter
包含Base(自己實現的Presenter框架,其實就是將Activity抽取了一層),Service包是Android組件Service
Impl是業務的實現,下面一堆I開頭的是業務接口。
這裡講一下Base,Base相當於控制器,拿登陸來舉例,一個登陸操作可能涉及多個界面,多個業務邏輯單元。比如登陸,首先是請求網絡的邏輯,除此之外,登陸成功後,需要對會話,用戶基礎信息等進行持久化;還有控制器需要控制各個界面的刷新。這些都是在控制器Base中完成的,他是一組邏輯的控制單元,負責一個典型的業務,比如說登陸。
下面的重點是業務接口,例如登陸ILogin,如果自己實現,你需要寫一大堆的東西,網絡請求,異步處理,Handler,異常處理,JSON解析,顯示,洋洋灑灑至少上百行了。如果你的項目需要快速上線怎麼辦?同時你又想保持項目的邏輯結構,以後做更細致的改進,這時候就體現了接口的重要性。這裡安利我一個比較快速的實現鏈接也是我實現的一個小框架。
用起來畫風是這樣的。
public class LoginPresenter extends Presenter implements ActivityOnCreatedListener,ICallBack{ 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業務接口就被框架實現了,簡單的說就是用了動態代理,框架根據你在接口上綁定的注解信息,幫你動態代理處一個業務實現對象。幫你包辦了網絡請求,異步處理,異步回掉,異常處理,JSON解析,顯示等一大堆操作。
如何綁定你的需求?
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比較簡單,我們換一個比較典型的
@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 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 getChild() { return child; } public void setChild(List 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層的視圖顯示等等。
使用這種臨時解決方案之後,後期如有需求,自己再選用其它框架,或者自己實現業務接口即可,根本不需要動其他模塊,從而保證了可擴展性。
ExpandableListView是一個垂直滾動顯示兩級列表項的視圖,與ListView不同的是,它可以有兩層:每一層都能夠被獨立的展開並顯示其子項。好友QQ列表,可以
1.當數據: 2.集成數據: DOS命令: java -jar QuickIntegrater.jar (輸入自己的項目名稱和包名) 把聲成的代碼復制進自
一、效果演示項目中用到了高斯模糊效果,查閱過一些資料,考慮到性能問題最終還是選擇使用Android自帶的RenderScript庫來實現,關於使用Render
手機連接不上刷機精靈,有時候不知道怎麼了手機想刷機,可就是連不上刷機精靈,不知道怎麼辦。是手機壞USB壞了嗎?現在小編來幫大家解答一下。怎麼檢查這手機連接不