上一节我们讲到了单例模式,其实上一节的代码例子也用到了观察者模式。也就是用户信息发生变化的时候通知所有注册了用户信息监听接口的人。观察者模式就是这么一个角色,他管理着一类信息,并随时注意着这些信息的变化,一有变化就通知关注了这个观察者的人。
还是上次讲的那个单例模式那个例子

/** 

  * 用户登录信息管理模块 

  * @author LZC  

  */ 

 public class UserManager { 





 private static UserManager mInst = null; 

 private static Object mLock = new Object(); 

 private boolean mHasLogined  = false; 

 private boolean mIsLogining  = false; 

 private String mUserId    = ""; 

 public String  mToken     = "";//登录凭证 

 public String  mNickName  = ""; 

 public String  mUserIcon  = "";//用户头像 

 public String mPhoneNum;//手机号 

 public String mSex;//性别“0”女,“1”代表男 

 public long   mBirth;//生日 

 public String mEmail;//邮箱 

 public String mQQ;//QQ 



 /** 

 *  

 * 监听 

 * 

 */ 

 //登录 

 public interface IOnLogin{ 

 void onLogining(); 

 void onLogined(); 

 void onLoginedFailed(); 

 } 

 //登出 

 public interface IOnLoginOut{ 

 void onLoginOut(); 

 } 

 //登录过期 

 public interface IOnLoginInvalid{ 

 void onLoginInvalid(); 

 } 



 public interface IOnUserInfoChange{ 

 void onIconChange(String userIcon); 

 void onGoldChange(int goldCount); 

 void onNickNameChange(String nickName); 

 } 

 private List<IOnLogin> mLoginListeners = new ArrayList<IOnLogin>(); 

 private List<IOnLoginOut> mOnLoginOuts = new ArrayList<IOnLoginOut>(); 

 private List<IOnUserInfoChange> mOnUserInfoChanges = new ArrayList<IOnUserInfoChange>(); 

 private List<IOnLoginInvalid> mOnLoginInvalids = new ArrayList<IOnLoginInvalid>(); 

 private UserManager(){ 

 } 

 public static UserManager getInst( ){ 

 if(mInst == null){ 

 synchronized(mLock){ 

 if(mInst == null){ 

 mInst = new UserManager(); 

 } 

 } 

 } 

 return mInst; 

 } 

 //添加登录监听 

 public void addLoginListener(IOnLogin listener){ 

 if(mLoginListeners != null && !mLoginListeners.contains(listener)){ 

 mLoginListeners.add(listener); 

 } 

 } 

 //移除登录监听 

 public void removeLoginListener(IOnLogin listener){ 

 if(listener != null && mLoginListeners.contains(listener)) 

 mLoginListeners.remove(listener); 

 } 

 //添加登出监听 

 public void addLoginOutListener(IOnLoginOut onLoginOut){ 

 if(mOnLoginOuts != null && !mOnLoginOuts.contains(onLoginOut)){ 

 mOnLoginOuts.add(onLoginOut); 

 } 

 } 

 //移除登出监听 

 public void removeLoginOutListener(IOnLoginOut onLoginOut){ 

 if(onLoginOut != null && mOnLoginOuts.contains(onLoginOut)){ 

 mOnLoginOuts.remove(onLoginOut); 

 } 

 } 

 //添加用户信息和变化监听 

 public void addUserInfoListener(IOnUserInfoChange onUserInfoChange){ 

 if(onUserInfoChange != null && !mOnUserInfoChanges.contains(onUserInfoChange)){ 

 mOnUserInfoChanges.add(onUserInfoChange); 

 } 

 } 

 //移除用户信息变化监听 

 public void removeUserInfoListener(IOnUserInfoChange onUserInfoChange){ 

 if(onUserInfoChange != null && mOnUserInfoChanges.contains(onUserInfoChange)){ 

 mOnUserInfoChanges.remove(onUserInfoChange); 

 } 

 } 

 //添加登录失效监听 

 public void addLoginInvalidListener(IOnLoginInvalid onLoginInvalid){ 

 if(onLoginInvalid != null && !mOnLoginInvalids.contains(onLoginInvalid)){ 

 mOnLoginInvalids.add(onLoginInvalid); 

 } 

 } 

 //移除登录失效监听 

 public void removeLoginInvalidListener(IOnLoginInvalid onLoginInvalid){ 

 if(onLoginInvalid != null && mOnLoginInvalids.contains(onLoginInvalid)){ 

 mOnLoginInvalids.remove(onLoginInvalid); 

 } 

 } 

 /** 

 *  

 * 设置数据 

 */ 

 //注销 

 public void logout(Context context){ 

 HttpClientInst.removeCookie(); 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 mHasLogined = false; 

 mIsLogining = false; 

 mUserGold      = 0; 

 mUserId       = ""; 

 mNickName     = ""; 

 mUserIcon     = ""; 

 mToken        = ""; 

 mPhoneNum     = "";//手机号 

 mSex          = "0";//性别“0”女,“1”代表男 

 mBirth        = 0;//生日 

 mEmail        = "";//邮箱 

 mQQ           = "";//QQ 

 mIsSign       = 0; 

 UserManager.getInst().updateUserIcon(mUserIcon); 

 preferencesWrapper.setStringValue(Constants.USER_NAME, ""); 

 preferencesWrapper.setStringValue(Constants.USER_PWD, ""); 

 preferencesWrapper.setStringValue(Constants.USER_LOGIN_TYPE, ""); 

 preferencesWrapper.commit(); 

 if(mOnLoginOuts != null){ 

 for(int idx = 0; idx < mOnLoginOuts.size(); ++ idx){ 

 mOnLoginOuts.get(idx).onLoginOut(); 

 } 

 } 

 } 

 /** 

 * 此方法只有登录接口能调用,其他地方不能随便调用 

 * @param userBean 

 * @param hasLogined 

      */ 

 //登录后,设置用户信息 

 public void setUserInfo(UserInfoBean userBean, boolean hasLogined){ 

 saveInfo(userBean); 

 if(hasLogined){ 

 if(!mHasLogined){ 

 mIsLogining = false; 

 mHasLogined = true; 

 if(mLoginListeners != null){ 

 for(int idx = 0; idx < mLoginListeners.size(); ++ idx){ 

 try { 

 mLoginListeners.get(idx).onLogined(); 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } 

 } 

 } 

 } 

 } 

 } 

 //把用户信息保存到本地,只有这三个信息保存到本地,为没登录时登录做准备,其他的都要登录以后才能获得,所以只能放在全局变量里面 

 private void saveInfo( UserInfoBean userBean){ 

 mUserId      = userBean.userId; 

 mUserIcon    = userBean.userIcon; 

 mToken       = userBean.token; 

 mNickName    = userBean.nickName; 

 mPhoneNum    = userBean.phoneNum;//手机号 

 mSex         = userBean.sex;//性别“0”女,“1”代表男 

 mBirth       = userBean.birth;//生日 

 mEmail       = userBean.email;//邮箱 

 mQQ          = userBean.qq;//QQ 

 mIsSign      = userBean.isSign; 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 preferencesWrapper.setStringValue(Constants.USER_NAME,       userBean.userName); 

 preferencesWrapper.setStringValue(Constants.USER_PWD,userBean.password); 

 preferencesWrapper.setStringValue(Constants.USER_LOGIN_TYPE, userBean.loginType); 

 preferencesWrapper.commit(); 

 } 

 //设置当前处于登陆中的状态 

 public void setLogining(){ 

 mIsLogining = true; 

 if(mLoginListeners != null){ 

 for(int idx = 0; idx < mLoginListeners.size(); ++ idx){ 

 try { 

 mLoginListeners.get(idx).onLogining(); 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } 

 } 

 } 

 } 



 //设置登录失败 

 public void setLoginFailed() { 

 mIsLogining = false; 

 mHasLogined = false; 

 if(mLoginListeners != null){ 

 for(int idx = 0; idx < mLoginListeners.size(); ++ idx){ 

 try { 

 mLoginListeners.get(idx).onLoginedFailed(); 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } 

 } 

 } 

 } 

 public void setLoginOutOfDate(){ 

 mHasLogined = false; 

 } 

 /** 

 * 更改用户信息后更新用户数据 

 */ 

 //修改密码后调用 

 public void updateUserPassword(String password,Context context) { 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 preferencesWrapper.setStringValue(Constants.USER_PWD, password); 

 preferencesWrapper.commit(); 

 } 



 //修改头像后调用 

 public void updateUserIcon(String userIcon){ 

 mUserIcon = userIcon; 

 for(int i = 0; i < mOnUserInfoChanges.size(); i ++){ 

 mOnUserInfoChanges.get(i).onIconChange(mUserIcon); 

 } 

 } 

 //修改昵称后调用 

 public void updateNickName(String nickName){ 

 mNickName = nickName; 

 for(int i = 0; i < mOnUserInfoChanges.size(); i ++){ 

 mOnUserInfoChanges.get(i).onNickNameChange(mNickName); 

 } 

 } 

 /*** 

 * 获取数据 

 */ 

 //判断当前是否是正在登陆中的状态 

 public boolean isLogining(){ 

 return mIsLogining; 

 } 

 public boolean isLogined(){ 

 return mHasLogined; 

 } 

 public ProtocolLogin createLoginProtocol(Context context, IProtocolListener listener){ 



 return new ProtocolLogin(context,ProtocolLogin.TYPE_AUTO, getLoginType(), getUserName(), getPassword(), listener); 

 } 



 public String getLoginType() { 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 return preferencesWrapper.getStringValue(Constants.USER_LOGIN_TYPE, ""); 

 } 



 //获取用户名 

 public String getUserName(){ 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 return preferencesWrapper.getStringValue(Constants.USER_NAME, ""); 

 } 



 //获取密码 

 public String getPassword(){ 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 return preferencesWrapper.getStringValue(Constants.USER_PWD, ""); 

 } 



 //是否可以自动登录 

 public boolean canAutoLogin(){ 

 PreferenceWrapper preferencesWrapper = new PreferenceWrapper(); 

 String username = preferencesWrapper.getStringValue(Constants.USER_NAME, ""); 

 String password = preferencesWrapper.getStringValue(Constants.USER_PWD, ""); 

 return !(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)); 

 } 

 //用户id 

 public String getUserId(){ 

 return mUserId; 

 } 



 //用户登录令牌 

 public String getToken(){ 

 return mToken; 

 } 



 //用户图标 

 public String getUserIcon(){ 

 return mUserIcon; 

 } 





 //用户昵称 

 public String getNickName(){ 

 return mNickName; 

 } 





 public String getmPhoneNum() { 

 return mPhoneNum; 

 } 





 public String getmSex() { 

 return mSex; 

 } 





 public long getmBirth() { 

 return mBirth; 

 } 





 public String getmEmail() { 

 return mEmail; 

 } 





 public String getmQQ() { 

 return mQQ; 

 } 

}






 
我们在用户信息发生变更时首先调用UserManager.getInst()初始化UserManager类,
 private static UserManager mInst = null;
 public static UserManager getInst( ){
 if(mInst == null){
 synchronized(mLock){
 if(mInst == null){
 mInst = new UserManager();
 }
 }
 }
 return mInst;
 }


 如果哪个界面需要知道用户信息什么时候会发生变化,并使用这些信息,那么就注册用户信息变化的监听,观察者把这些监听存储载自己的成员变量中


 public void addUserInfoListener(IOnUserInfoChange onUserInfoChange){
      if(onUserInfoChange != null && !mOnUserInfoChanges.contains(onUserInfoChange)){
          mOnUserInfoChanges.add(onUserInfoChange);
      }
 }
 如果头像发生了修改则调用
 public void updateUserIcon(String userIcon){
   mUserIcon = userIcon;
   for(int i = 0; i < mOnUserInfoChanges.size(); i ++){
    mOnUserInfoChanges.get(i).onIconChange(mUserIcon);
   }
 }
 通知所有OnUserInfoChanges接口,头像更新了。这样就通知所有注册了OnUserInfoChanges接口的界面可以刷新数据了。这就是观察者模式的用处。但是需要注意的是当注册了OnUserInfoChanges接口的界面要销毁的时候,就要移除监听
 public void removeUserInfoListener(IOnUserInfoChange onUserInfoChange){
 if(onUserInfoChange != null && mOnUserInfoChanges.contains(onUserInfoChange)){
 mOnUserInfoChanges.remove(onUserInfoChange);
 }
 }


避免因OnUserInfoChanges对象销毁造成空指针或者接口回调中调用了已经释放掉的变量