編輯:關於Android編程
在上一節中,我們講述了如何在Android平台下,以MVC架構為指導,實現模型類的方法。在本節中,我們要重點討論一下,怎樣設計Activity類,作為MVC中的控制器,並在其中使用我們在上節所講述的模型類。在這裡我們只討論重要的代碼,對於資源文件及Activity頁面設計及實現細節,由於篇幅所限,就只能略過了,大家可以在稍後公布的項目下載包中查看相應的代碼。
我們以具體項目WkgJys項目為例,項目在首次運行時,Splash頁面之後,會進入JysAppTourActivity,在看完所有介紹頁面之後,點擊進入應用按鈕,由於是程序第一次運行,為進入JysRegisterLoginActivity對應的頁面,並且狀態為注冊狀態。我們就從這裡開始討論。
首先,有一些公共功能,如按回退鍵提示用戶是否退出系統等功能,我們需要定義一個項目中所有Activity的基類WkyActivity,代碼如下所示:
/**
* 所有Activity的基類
* @author 闫濤 2015.09.18
*
*/
public class WkyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // 不顯示TitleBar
// 連屏幕上的狀態欄也不顯示
//getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 在manifest文件中對每個activity android:theme=@android:style/Theme.NoTitleBar.Fullscreen
handler = new Handler();
}
/**
* Activity在onCreate時會初始化其對應的Model類,因此在銷毀時也需要移除該對象
* 【闫濤 2015.09.17】初始版本
*/
@Override
public void onDestroy() {
super.onDestroy();
if (!model.isShared()) {
WkyModel.removeObject(model.getObjectId());
}
}
/**
* 用戶點擊回退按鈕時,提示用戶是否退出應用,如果選擇確定,則退出應用
* 【闫濤 2015.09.18】實始版本
*/
@Override
public void onBackPressed() {
new AlertDialog.Builder(this).setTitle(確定退出嗎?)
.setNeutralButton(確定, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.exit(1);
//myApplication.closeApp();
}
})
.setNegativeButton(取消, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).show();
}
protected Handler handler = null; // 用於響應消息總線
protected WkyModel model = null;
protected Activity thisActivity = null;
}
在上面的代碼中,提醒大家注意handler屬性,這是為了後面將要討論到的消息總線機制設計的。如果某些Activity需要響應消息總線上的消息,就需要將該handler注冊到消息總線上去,這部分內容我們會在以後談到。
在用戶浏覽完應用介紹頁面之後,會調用JysAppTourActivity的這個函數:
/**
* 啟動注冊登錄頁面,並關閉本頁
* 【闫濤 2015.09.11】初始版本
*/
@Override
protected void goRegisterLoginActivity() {
JysRegisterLoginModel model = (JysRegisterLoginModel)WkyModel.getInstance(
JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT,
JysRegisterLoginModel.class);
model.setObjectId(JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT);
model.setState(JysRegisterLoginModel.STATE_REGISTER);
Intent intent = new Intent(this, JysRegisterLoginActivity.class);
startActivity(intent);
finish();
}
在這個函數中,會首先初始化一個JysRegisterLoginModel類的實例,方法為調用基類WkyModel.getInstance方法,當生成JysRegisterLoginModel類實例後,將標識設置為類的全名加default(在後面JysRegisterLoginActivity中會根據這個ID來獲取本實例,同時會在onDestroy回調中,刪除此ID的對象),將界面狀態置為注冊。
下面是JysRegisterLoginActivity類,由於該類中有很大一部分代碼是用於實現界面的,這裡就不重點介紹了。這裡只重點介紹與MVC架構相關的內容。要理解本類,我們需要從其基類入手。
首先是WkyRegisterLoginModel.onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_register_login);
moveHeight = DensityUtil.dip2px(this, 50);
inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
model = getRegisterLoginModel();
wkyRegisterLoginModel = (WkyRegisterLoginModel)model;
thisActivity = this;
int state = wkyRegisterLoginModel.getState();
}
這裡首先通過調用具體應用中的子類(JysRegisterLoginModel類)的getRegisterLoginModel方法,取出先前生成的模型類對象,並取出保存在其中的狀態。
在具體應用中,如JysRegisterLoginModel.onCreate中,進行具體的初始化操作:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.weikangyun.wkylib.R.layout.activity_register_login);
getViewObjects();
setupGuis();
setupActionListeners();
}
/**
* 生成並獲取本Activity對應的模型類實例
* 【闫濤 2015.09.18】初始版本
*/
protected WkyModel getRegisterLoginModel() {
return WkyModel.
getInstance(JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT,
JysRegisterLoginModel.class);
}
上面代碼首先設置布局文件,然後獲取界面上View對象,然後根據模型類內容,初始化界面,最後是設置界面上事件響應函數。上述步驟與IOS中的基本相同,其中getViewObjects在IOS中是設置IBOutlets,而setupActionListeners對應IOS中的IBAction。
下面來看getViewObjects方法實現:
/**
* 獲取界面上所有View對象
* 【闫濤 2015.09.12】初始版本
*/
protected void getViewObjects() {
contentView = (View)findViewById(R.id.content_view);
rootView = (WkyKbRelativeLayout)findViewById(R.id.registerLoginRoot);
scrollView = (ScrollView)findViewById(R.id.scrollview);
loginNameEdtt = (WkyEditText)findViewById(R.id.login_name_edtt);
loginPwdEdtt = (WkyEditText)findViewById(R.id.login_pwd_edtt);
loginTempEdtt = (WkyEditText)findViewById(R.id.login_temp_edtt);
forgetPwdTxtv = (TextView)findViewById(R.id.forget_pwd_txtv);
userAgreementTxtv = (TextView)findViewById(R.id.user_agreement_txtv);
switchStateTxtv = (TextView)findViewById(R.id.switch_state_txtv);
clearLoginNameImgv = (ImageView)findViewById(R.id.clear_login_name_imgv);
clearLoginPwdImgv = (ImageView)findViewById(R.id.clear_login_pwd_imgv);
registerOrLoginImgv = (ImageView)findViewById(R.id.register_or_login_imgv);
userAgreementLrlt = (LinearLayout)findViewById(R.id.user_agreement_lrlt);
switchStateLabelTxtv = (TextView)findViewById(R.id.switch_state_label_txtv);
}
實際上就是將頁面上的View保存到對應的屬性中。下一步是根據模型類中的數據,通過setupGuis方法來設置顯示界面,代碼如下所示:
/**
* 根據狀態設置界面元素是否顯示
* 【闫濤 2015.09.12】初始版本
*/
protected void setupGuis() {
switch (wkyRegisterLoginModel.getState()) {
case WkyRegisterLoginModel.STATE_REGISTER:
forgetPwdTxtv.setVisibility(View.GONE);
userAgreementLrlt.setVisibility(View.VISIBLE);
switchStateTxtv.setText(登錄);
switchStateLabelTxtv.setText(已有帳號?點擊 );
registerOrLoginImgv.setImageResource(R.drawable.register);
break;
case WkyRegisterLoginModel.STATE_LOGIN:
forgetPwdTxtv.setVisibility(View.VISIBLE);
userAgreementLrlt.setVisibility(View.INVISIBLE);
switchStateTxtv.setText(注冊);
switchStateLabelTxtv.setText(沒有帳號?點擊 );
registerOrLoginImgv.setImageResource(R.drawable.login);
loginPwdEdtt.setHint(密碼);
forgetPwdTxtv.setText(忘記密碼);
break;
case WkyRegisterLoginModel.STATE_FORGET_PWD:
registerOrLoginImgv.setImageResource(R.drawable.reset_password);
loginPwdEdtt.setHint(設置一個新密碼,6-15位);
forgetPwdTxtv.setText(返回登錄);
userAgreementLrlt.setVisibility(View.INVISIBLE);
break;
case WkyRegisterLoginModel.STATE_ACTIVATE:
break;
}
clearLoginNameImgv.setVisibility(View.GONE);
clearLoginPwdImgv.setVisibility(View.GONE);
}
在本方法中,根據模型類JysRegisterLoginModel對象中保存的狀態信息,顯示相應的內容。這裡一共有四種狀態:注冊、登錄、忘記密碼和激活。
接下來我們在setupActionListeners方法中,添加界面事件響應函數的定義:
/**
* 設置界面上各個View的消息響應函數
* 【闫濤 2015.09.12】初始版本
*/
protected void setupActionListeners() {
listenSoftKeyboardState();
setUserAgreementLrltOnClickListener();
setClearLoginNameImgvOnClickListener(); // 清空登錄名內容
setClearLoginPwdImgvOnClickListener(); // 清空密碼
setLoginNameEdttOnFocusChangeListener(); // 登錄名失去獲取焦點時顯示或隱藏清除圖標
setLoginPwdEdttOnFocusChangeListener(); // 密碼失去焦點時顯示或隱藏右側清除圖標
addLoginNameEdttTextChangedListener();
addLoginPwdEdttTextChangedListener();
setSwitchStateTxtvOnClickListener();
setForgetPwdTxtvOnClickListener();
setRegisterOrLoginImgvOnClickListener();
}
分別作如下操作:
監聽軟鍵盤狀態用戶點擊用戶協議的消息響應函數,利用WebView來顯示用戶協議登錄名清空圖標的消息響應函數登錄密碼清空圖標的消息響應函數登錄名失去焦點的消息響應函數登錄密碼失去焦點的消息響應函數登錄名內容改變消息響應函數登錄密碼內容改變消息響應函數狀態切換(注冊、登錄、忘記密碼、激活)消息響應函數忘記密碼點擊的消息響應函數注冊或登錄按鈕消息響應函數完成這些工作後,當用戶點擊注冊時,就可以進入注冊流程了。在下一節中,我們將首先講一下Android平台下網絡請求的實現方式,我們這裡采用異步任務的方式來處理網絡請求。
小米手環來電不震動解決辦法
大家購買小米手環之後使用最多的大概就是來電提醒和檢測運動量這兩個功能了,但是很多朋友說小米手環經常抽風,來電不震動。那麼小米手環來電不震動這種情況是怎麼回事
Android 存儲學習之保存系統短信到SD卡(使用XML序列化器)
上節中我們是手動拼接xml文件,但是上節中那樣的做法會有一個問題,比如: //插入消息的內容sBuffer.append(); sBuffer.append(s
android 日常迭代與維護總結二
android 迭代開發中陸續遇到各種問題,我們要善於總結,歸類。現在記錄一下這幾個月遇到的問題匯總。1、android fragment中onActivityResul
Android筆記十一.ListView+Adapter
深入理解Adapter 一、ListView ListView是Android開發過程中較為常見的組件之一,它將數據以列表的形式展現出來。一般而言,一個ListView由