編輯:關於Android編程
前面一篇博客是用簡單java例子來熟悉狀態設計模式,而這篇我將以android登錄的例子繼續講解狀態設計模式。
一.android中狀態設計模式應用場景
在android開發中,我們遇到登錄界面是十分常見的,而狀態設計模式在登錄界面的應用十分廣泛,用戶在登錄狀態下和未登錄狀態下,對邏輯的操作是不一樣的。例如最常見的情況就是在玩新浪微博的時候,用戶在登錄的情況下才能完成評論和轉發微博的操作;而當用戶處於未登錄的情況下要執行轉發和評論微博的操作需要進入登錄界面登錄以後才能執行,所以面對這兩者不同的狀況,利用狀態設計模式來設計這個例子最好不過。
二.設計流程
下面我們利用狀態設計模式來簡單的實現這個過程首先我們創建一個android項目,此項目的裡面有兩個Activity,分別是LoginActivity和MainActivity,其中入口Activity是LoginActivity,當用戶登錄成功就進入MainActivity,裡面包含轉發,評論,注銷等操作。下面是整個項目的截圖:

由於最近在學習javaweb,正好想到可以結合狀態模式做一個登錄的操作,這裡順便貼一下javaweb端的代碼吧,服務器用的是Tomcat 8; 數據庫用的是mysql;下面是servlet端的代碼。利用prepareStatement可以防止SQL注入,具體使用請百度一下,我這裡不做多的講解,大致流程:
1,android客戶端通過post請求加上username和passwZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcmTV4sG9uPayzsr9o7s8YnIgLz4NCjKjrLf+zvHG97bLxMO1vdXiwb249sfrx/Oyzsr9yLu687Lp0a/K/b7dv+KjrLWxsunRr8r9vt2/4rTm1Nq0y9PDu6ejrNTywPvTw3Jlc3BvbnNlLmdldFdyaXRlcigpyuSz9tK7uPYyMDC1xGNvZGU7PGJyIC8+DQrPwsPmuL3Jz87Ssb612Mr9vt2/4rXEzbzGrKO6PGJyIC8+DQo8aW1nIGFsdD0="這裡寫圖片描述" src="/uploadfile/Collfiles/20160919/20160919093627316.png" title="\" />
public class LoginServlet extends HttpServlet {
private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
private PrintWriter writer;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("username");
String pwd = request.getParameter("password");
try {
writer = response.getWriter();
conn = DBUtils.getConnection();
String sql = "select username,password from t_user where username=? and password=?";
ps = conn.prepareStatement(sql);
ps.setString(1, name);
ps.setString(2, pwd);
rs = ps.executeQuery();
while(rs.next()){
writer.write("200");
writer.flush();
break;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(writer!=null){
writer.close();
writer = null;
}
//DBUtils.closeResources(conn, ps, rs);
}
}
三.android客服端的代碼實現
1.狀態基類
前面我們講過狀態設計模式的原理實則是多態,在這裡我們用UserState接口表示此基類,包換轉發操作和評論這兩種狀態,代碼如下:
public interface UserState {
/**
* 轉發操作
* @param context
*/
public void forword(Context context);
/**
* 評論操作
* @param context
*/
public void commit(Context context);
}
2.用戶在登錄和未登錄兩種狀況下的實現類LoginState和LogoutState;代碼如下:
在LoginState.java中,用戶是可以執行轉發和評論操作。
public class LoginState implements UserState{
@Override
public void forword(Context context) {
Toast.makeText(context, "轉發成功", Toast.LENGTH_SHORT).show();
}
@Override
public void commit(Context context) {
Toast.makeText(context, "評論成功", Toast.LENGTH_SHORT).show();
}
}
在LogoutState.java中,用戶在未登錄的情況下不允許執行操作,而是應該跳轉到登錄界面執行登錄以後才可以執行。
public class LogoutState implements UserState{
/**
* 跳轉到登錄界面登錄以後才能轉發
*/
@Override
public void forword(Context context) {
gotoLohinActivity(context);
}
/**
* 跳轉到登錄界面登錄以後才能評論
*/
@Override
public void commit(Context context) {
gotoLohinActivity(context);
}
/**
* 界面跳轉操作
* @param context
*/
private void gotoLohinActivity(Context context){
context.startActivity(new Intent(context,LoginActivity.class));
}
}
3.操作角色LoginContext
這裡的LoginContext就是在狀態模式的Context角色,是用戶操作對象和管理對象,LoginContext委托相關的操作給狀態對象,在其中狀態的發生改變,LoginContext的行為也發生改變。LoginContext的代碼如*下:
溫馨提示:
這裡我們用到單例就是為了全局只有一個LoginContext去控制用戶狀態;
public class LoginContext {
//用戶狀態默認為未登錄狀態
UserState state = new LogoutState();
private LoginContext(){};//私有構造函數,避免外界可以通過new 獲取對象
//單例模式
public static LoginContext getInstance(){
return SingletonHolder.instance;
}
/**
*靜態代碼塊
*/
private static class SingletonHolder{
private static final LoginContext instance = new LoginContext();
}
public void setState(UserState state){
this.state = state;
}
//轉發
public void forward(Context context){
state.forword(context);
}
//評論
public void commit(Context context){
state.commit(context);
}
}
4,界面展示
LoginActivity.java,此界面執行登錄操作,登錄成後把 LoginContext.getInstance().setState(new LoginState());設置為登錄狀態,在MainActivity中就執行的是登錄狀態下的操作,即可以轉發可評論;
public class LoginActivity extends Activity implements OnClickListener{
private static final String LOGIN_URL = "http://10.10.200.193:8080/Day01/servlet/LoginServlet";
private EditText et_username;
private EditText et_password;
private Button btn_login;
private String username;
private String password;
private KJHttp http;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
initData();
}
private void initView() {
et_username = (EditText) findViewById(R.id.et_username);
et_password = (EditText) findViewById(R.id.et_password);
btn_login = (Button) findViewById(R.id.btn_login);
btn_login.setOnClickListener(LoginActivity.this);
}
private void initData() {
http = new KJHttp();
}
/**
* 執行登錄操作
*
* @param username2
* @param password2
*/
protected void sendLogin(String username2, String password2) {
HttpParams params = new HttpParams();
params.put("username", "user1");
params.put("password", "123456");
http.post(LOGIN_URL, params, new HttpCallBack() {
@Override
public void onSuccess(String t) {
if ("200".equals(t)) {
//設置為登錄狀態
LoginContext.getInstance().setState(new LoginState());
startActivity(new Intent(LoginActivity.this,MainActivity.class));
finish();
Toast.makeText(LoginActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
username = et_username.getEditableText().toString().trim();
password = et_password.getEditableText().toString().trim();
if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
Toast.makeText(LoginActivity.this, "用戶名密碼不能為空", Toast.LENGTH_SHORT).show();
return;
}
sendLogin(username, password);
break;
}
}
}
MainActivity.java,在用戶登錄成功後,點擊轉發和評論執行的是登錄狀態下的操作,而當用戶注銷時,我們把LoginContext的狀態設置為未登錄狀態;LoginContext.getInstance().setState(new LogoutState());此時在點擊轉發和評論操作時就會跳到用戶登錄界面。
public class MainActivity extends Activity {
private Button btn_forward;
private Button btn_commit;
private Button btn_logout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
}
private void initView() {
btn_forward = (Button) findViewById(R.id.btn_forward);
btn_commit = (Button) findViewById(R.id.btn_commit);
btn_logout = (Button) findViewById(R.id.btn_logout);
}
private void initListener() {
//轉發操作
btn_forward.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//調用LoginContext裡面的轉發函數
LoginContext.getInstance().forward(MainActivity.this);
}
});
//評論操作
btn_commit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//調用LoginContext裡面的轉發函數
LoginContext.getInstance().commit(MainActivity.this);
}
});
//注銷操作
btn_logout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//設置為注銷狀態
LoginContext.getInstance().setState(new LogoutState());
}
});
}
}
6.圖片展示


到此狀態模式分析完畢。。。。。。
逆風的方向,更適合飛翔。
android 動態創建Fragment
前一遍文章我們講了靜態創建Fragment,這個在實際的開發中幾乎不用,都是動態創建的,所謂動態創建就是根據某個條件動態創建Fragment, 現在創建一個android
編寫原生看書頁面 輪播圖模塊時遇到的fragment問題
書籍頁面需要顯示輪播圖組件down下來用到看書中,是封裝在fragment裡的,我是在BookView中動態調用的,調用方式:LayoutInflater lif = (
Android學習筆記(十四)——在運行時添加碎片(附源碼)
在運行時添加碎片 點擊獲取源碼 將UI分割為多個可配置的部分是碎片的優勢之一,但其真正強大之處在於可在運行時動態地把它們添加到活動中。 1、使用上一篇創建的F
【Android】Android自定義帶board的圓角控件
介紹圓角控件常用於頭像,按鈕,圖標等,用途十分廣泛,而且常常配合board使用。在IOS中,UIVIew的CALayer層已經提供了圓角和board的方法,所以圓角控件的