編輯:關於Android編程
用戶在觀看完應用介紹頁面之後,會點擊進入應用按鈕,這時由於用戶是第一次運行,所以會彈出注冊頁面。如果是老用戶,啟動應用時,在Splash頁面之後,如果應用記錄著用戶的登錄信息,測直接進入主頁面,如果從本地取不到用戶登錄信息,則將顯示登錄頁面。
注冊和登錄功能看起來很簡單,但是由於我們這裡需要實現一個完整的應用支撐基礎設施,因此需要分幾個部分來進行。我們首先會討論怎樣創建並使用Activity中會用到的Model類,在這中間我們會采用Application對象作為中心信息倉庫,每個Model類只是中心信息倉庫的視圖,便於對應的Activity類來使用;接著我們會討論Activity類的基類,在其中包裝諸如按回退鍵提示退出等功能;接著我們會討論網絡請求的實現,這裡我們采用異步任務的方式來進行,協議采用Json Over Http,因此會順便介紹Json的解析。
在進入正文之前,首先解釋一個問題,我們什麼時候檢查版本更新。一般你可以在很多點來檢查版本更新,我在這裡采用進入主頁面前檢查版本更新,為什麼這樣做呢?因為在實際項目中,我們可能會有些小范圍測試的版本,我們會采用灰度更新的機制,即只有一部分用戶會收到更新通知,試用最新版本,如果反響很好,我們再向普通用戶推出版本更新,因此檢查版本更新放在了登錄之後。
好了,我們先來看怎樣實現MVC中的Model。我們首先在WkyLib工程中,定義Model的基類WkyModel,代碼如下所示:
public class WkyModel { public static WkyModel getInstance(String objectId, Class cls) { if (models.containsKey(objectId)) { return models.get(objectId); } WkyModel model = (WkyModel)WkyReflection.callPrivateConstructor(cls); model.setObjectId(objectId); Log.e(wky, cls: + cls.getCanonicalName() + !); if (null == model) { model = new WkyModel(); } models.put(objectId, model); return model; } public static void removeObject(String objectId) { models.remove(objectId); } public static void removeInstance(String objectId) { models.remove(objectId); } /** * 在Activity.onDestroy中調用,判斷是否需要將實例從models中移除 * @return * 【闫濤 2015.09.17】初始版本 */ public boolean isShared() { return isShared; } /** * 如果想要在多個界面中使用同一個Model對象,則需要調用此函數, * 將isShared設置為true,這時在Activity.onDestroy中就不會將本實例從models中移除了 * @param isShared * 【闫濤 2015.09.17】初始版本 */ public void setShared(boolean isShared) { this.isShared = isShared; } public String getObjectId() { return objectId; } public void setObjectId(String objectId) { this.objectId = objectId; } private static HashMapmodels = new HashMap (); protected boolean isShared = false; protected String objectId = null; }
假設一個Activity有對應的Model類時,例如JysRegisgetrLoginActivity需要JysRegisterLoginModel類對象時,會通過調用getInstance方法來獲取實例。每個Model類,可以同時存在多個實例,保存在models屬性中。一般情況下,Activity在onCreate或在啟動此Activity時,會生成一個Model類的實例,當該Activity退出時,在onDestroy回調函數中將該實例從models屬性中移除。但是如果設置了isShared為ture時,則onDestroy方法中就不會移除此對象,就可以在不同的Activity實例中使用了。
在上面的代碼中,我們用到了Java的反射機制,根據getInstance方法第二個參數的類,調用該類的私有無參數構造函數,生成該類的對象,我們引入了一個反射工具類WkyReflection,代碼如下所示:
public class WkyReflection { /** * 調用類的私有無參數構造函數,生成該類對象並返回該對角 * 例子: * WkyRegisterLoginModel model = (WkyRegisterLoginModel)WkyReflection.callPrivateConstructor(WkyRegisterLoginModel.class); * @param cls * @return * 【闫濤 2015.09.17】初始版本 */ public static Object callPrivateConstructor(Class cls) { Constructor[] constructor = cls.getDeclaredConstructors(); constructor[0].setAccessible(true); Object rst = null; try { rst = constructor[0].newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return rst; } }
在本節開頭我們就提到,我們的信息保存在應用的中心信息倉庫中,每個Model裡保存的,只是其中的一部分,在Android平台下,我們可以利用Application子類來作為中心信息倉庫,代碼如下所示:
/** * model類將所有信息均保存在HashMap中,這樣信息可以在Model之間共用 * @param key * @param val * 【闫濤 2015.09.17】初始版本 */ public static void putObject(String key, Object val) { params.put(key, val); } /** * 從HashMap中取出相應的信息,調用者需要將其轉化為正確的類 * @param key * @return * 【闫濤 2015.09.17】初始版本 */ public static Object getObject(String key) { return params.get(key); } public void exitApp() { System.exit(1); } public static WkyApplication instance = null; private static HashMapparams = new HashMap ();
下面我們來看注冊登錄的基類WkyRegisterLoginModel類的實現:
public class WkyRegisterLoginModel extends WkyModel { protected WkyRegisterLoginModel() { WkyApplication.putObject(WkyConstants.ROLE_ID, Integer.valueOf(WkyConstants.ROLE_JYS)); WkyApplication.putObject(WkyConstants.REGISTER_LOGIN_STATE, Integer.valueOf(STATE_LOGIN)); roleId = (Integer)WkyApplication.getObject(WkyConstants.ROLE_ID); state = (Integer)WkyApplication.getObject(WkyConstants.REGISTER_LOGIN_STATE); } public int getState() { return state; } public void setState(int state) { this.state = state; } public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } public final static int STATE_REGISTER = 1; public final static int STATE_LOGIN = 2; public final static int STATE_FORGET_PWD = 3; public final static int STATE_ACTIVATE = 4; private int state = STATE_LOGIN; private int roleId = WkyConstants.ROLE_JYS; }在上面的代碼中,裡面有兩個屬性比較重要,第一個state代表注冊登錄Activity所處的狀態,一共有四種:注冊、登錄、忘記密碼、激活,第二個屬性roleId代表用戶的角色,可以是基因師也可以是大眾。需要注意的是,在構造函數中,這兩個屬性的值是存到中心信息倉庫中的。
下面看具體應用WkgJys中,怎樣定義具體的Model類JysRegisterLoginModel:
public class JysRegisterLoginModel extends WkyRegisterLoginModel { protected JysRegisterLoginModel() { super(); isShared = false; } }在這裡,由於沒有特別的需要,沒有定義新的屬性,因此代碼很簡單。但是需要注意的是isShared = false,意味著在onDestroy方法中,這個實例將被移除,不會被共享。
好了,有了上述代碼,Model體系就創建完成了。在下一節中,我們將講到怎樣實現MVC中的C,即Activity的實現方式。
其實可以理解Handler為主線程和另外的線程之間進行數據更新的東東,並且Handler在主線程中,並在Handler直接調用線程的run方法package com.Ha
其實ViewFlipper工作機制很簡單,如上圖,就是將添加到ViewFlipper中的子View按照順序定時的顯示是其中一個子View,其他的子View設置為Gone狀
1、頁面初始化在app開發中,若要使用HTML5+擴展api,必須等plusready事件發生後才能正常使用,mui將該事件封裝成了mui.plusReady()方法,涉
因重定向無法正常goBack()解決方案首先說下問題,初始頁面為A,點擊某個鏈接跳轉到B(http://xxx.com.cn/),B頁面重定向到C頁面(http://xx