在上一篇文章中我們介紹了在android產品研發過程中,啟動頁的優化工作,比如啟動頁性能優化,啟動頁漸進動畫效果,啟動頁屏蔽返回按鍵等等,而在本文中我們將要介紹一下在App產品研發中都會復寫的基類Activity。
在實際的android產品研發中,一般的我們在寫Activity的時候都會繼承于一個基類Activity,該Activity是所有的Activity的基類。在該基類中我們主要用于重寫一些共有的邏輯。好處是顯而易見的對于一些Activity的共有邏輯我們不必要在每個Activity中都重新寫一遍,只需要在基類Activity中寫一遍就好了。
下面我就講解一下在產品研發過程中我對基類Activity的設計。
(一)基類Activity是如何使用的?
定義一個BaseActivity,讓App中所有的Activity都繼承于BaseActivity;
(二)基本Activity包含的內容
* 在BaseActivity的生命周期中復寫友盟數據統計方法。 用過友盟數據統計的同學應該知道,為了統計每個頁面的點擊事件,頁面訪問路徑,異常信息等我們需要在Activity的生命周期方法中添加友盟的API,這些都是一些相同的邏輯,難道我們需要在每個Activity中都重寫這些友盟API么?答案當然是否定的,友盟官方也不建議我們這么做,我們可以在一個基類Activity的生命周期方法中重寫這些友盟API,并讓我們需要統計的頁面繼承于該基類Activity。
~~~
@Override
protected void onResume() {
MobclickAgent.onResume(this);
}
@Override
protected void onPause() {
MobclickAgent.onPause(this);
}
(其他生命周期方法暫略)
...
~~~
由于我們需要統計不同的Activity頁面的數據,所以我們需要在各個Activity的生命周期中都要重寫友盟的API,那么這里我們就完全可以將這種重復性的動作下發到BaseActivity中,而讓所有的Activity都繼承于BaseActivity,進而我們的Activity就在生命周期方法中重寫了友盟的API。
* 在生命周期方法中保存Context對象,保存Activity棧
~~~
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
Config.setActivityState(this);
...
}
public static void setActivityState(Activity activity) {
currentContext = activity;
// 設置App只能豎屏顯示
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// 向自身維護的Acitivty棧(數據類型為List)中添加Activity
UUApp.getInstance().addActivity(activity);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 在BaseActivity中的Activity棧中移除Activity
UUApp.getInstance().removeActivity(this);
}
~~~
因為我們在Activity頁面中經常需要使用“this”,但是到處都是用this顯得不太好,這時候我們可以在BaseActivity中定義一個Actiivty類型的mContext成員變量并在BaseActivity中的onCreate方法中賦值為this,這樣我們在子Activity中需要使用this的地方直接使用mContext成員變量就好了。
并且我們在內存中保存了一個Activity的自定義棧,正常的做法是在Activity的onCreate方法中執行入棧操作,在Activity的onDestory方法中執行出棧操作,由于這些都是共有的邏輯因此我們把這兩個操作放到BaseActivity中。
- 在生命周期方法中對事件總線框架EventBus進行注冊和反注冊
使用過EventBus的同學應該知道其能夠實現事件傳遞的核心機制就是將Activity對象“注冊”到EventBus中,但是有注冊也必須要有反注冊的機制,因為Activity不是常駐內存的,Activity也有銷毀的時候,這時候就需要從EventBus中“反注冊”,一個比較好的方式就是在Activity
~~~
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
EventBus.getDefault().register(this);
...
}
@Override
protected void onDestroy() {
super.onDestroy();
...
EventBus.getDefault().unregister(this);
...
}
/**
* event 更改顯示登陸狀態
*/
public void onEventMainThread(BaseEvent event) {
...doSomething...
}
~~~
這樣我們就不必要單獨在Activity中重寫EventBus的注冊和反注冊邏輯了。
- 在onResume方法中執行更新登錄用戶票據更新的操作
在App端保存了用戶的token信息,但是這里的token信息不是一直有效的,有效期為30天,所以這里就需要有一個更新token的操作,App現在的更新操作是判斷token的有效期是否過了一半,即15天,若過了一半了,則在新打開的Activity時執行更新票據操作,所以這也是共有的邏輯,即在BaseActivity的onResume中執行更新票據的操作。
~~~
@Override
protected void onResume() {
super.onResume();
/**
* 驗證用戶票據是否失效,失效的話則默認執行更換票據操作
* startActivity中不需要更新票據,否則起始頁有可能會彈出登陸提示框
*/
if (UserConfig.isNeedUpdateTicket() && (!(this instanceof StartActivity) || !this.getClass().getName().equals(StartActivity.class.getName()))) {
if (!UserConfig.isUpdateTicketing) {
L.d("onResume 中更新用戶票據");
UserConfig.requestUpdateTicket();
}
}
...
}
~~~
- 在setContentView方法中,重寫加載布局文件的邏輯,統一App頁面布局
~~~
@Override
public void setContentView(int layoutResID) {
View view = getLayoutInflater().inflate(R.layout.activity_base_layout, null);
super.setContentView(view);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
view.setFitsSystemWindows(true);
setTranslucentStatus(true);
SystemBarTintManager tintManager = new SystemBarTintManager(this);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(R.color.colorPrimaryDark);
}
initDefaultView(layoutResID);
initDefaultToolBar();
}
/**
* 初始化默認的布局組件
*
* @param layoutResID
*/
private void initDefaultView(int layoutResID) {
mProgressLayout = (ProgressLayout) findViewById(R.id.progress_layout);
mProgressLayout.setAttachActivity(this);
mProgressLayout.setUseSlideBack(false);
mToolbarContainer = (FrameLayout) findViewById(R.id.toolbar_container);
mDefaultToolBar = (Toolbar) findViewById(R.id.default_toolbar);
mToolbarTitle = (TextView) findViewById(R.id.toolbar_title);
mRvRight = (RippleView) findViewById(R.id.rv_right);
mRightOptButton = (TextView) findViewById(R.id.right_opt_button);
mContentContainer = (FrameLayout) findViewById(R.id.fl_content_container);
View childView = layoutInflater.inflate(layoutResID, null);
mContentContainer.addView(childView, 0);
}
/**
* 初始化默認的ToolBar
*/
private void initDefaultToolBar() {
if (mDefaultToolBar != null) {
String label = getTitle().toString();
setTitle(label);
setSupportActionBar(mDefaultToolBar);
mDefaultToolBar.setNavigationIcon(R.mipmap.toolbar_back_icn_transparent);
}
}
~~~
在BaseActivity中重寫了setContentView方法,然后統一布局文件,即讓我們調用setContentView傳遞的layoutId加載到我們自定義的ViewContain中,這樣我們就統一了Activity的布局文件,當然了這也是共有的邏輯,我們可以卸載BaseActivity中。
- 執行共有的UI操作,比如顯示Toast,顯示SnakeBar,顯示Progress,顯示Dialog等
~~~
public void showToast(String text) {
if (text != null && !text.trim().equals("")) {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
}
public void showProgress(boolean canCancled, final Config.ProgressCancelListener listener) {
Config.showProgressDialog(mContext, canCancled, listener);
}
public void dismissProgress() {
Config.dismissProgress();
}
public void showResponseCommonMsg(HeaderCommon.ResponseCommonMsg msg) {
if (msg.getMsg() != null && msg.getMsg().length() > 0) {
if (msg.hasShowType()) {
if (msg.getShowType().equals(HeaderCommon.ResponseCommonMsgShowType.TOAST)) {
showSnackBarMsg(msg.getMsg());
} else if (msg.getShowType().equals(HeaderCommon.ResponseCommonMsgShowType.WINDOW)) {
showResponseCommonMsg(msg, null);
}
} else {
showSnackBarMsg(msg.getMsg());
}
}
}
~~~
我們可以在BaseActivity中重寫了一些顯示Toast,Dialog,SnakeBar的操作,這樣我們在Activity中顯示這些UI的時候可以統一調用方法與UI風格。
從上面我們分析的基類內容可以知道一般在涉及Activity的時候都需要重寫一個基類Activity,用于重寫Activity中的共有邏輯,避免我們在每個Activity中都重寫相關的重復邏輯。
另外對產品研發技術,技巧,實踐方面感興趣的同學可以參考我的:
[android產品研發(一)-->實用開發規范 ](http://blog.csdn.net/qq_23547831/article/details/51534013)
[android產品研發(二)-->啟動頁優化 ](http://blog.csdn.net/qq_23547831/article/details/51541277)
[android產品研發(三)-->基類Activity](http://blog.csdn.net/qq_23547831/article/details/51546974)
- 前言
- (一)–>實用開發規范
- (二)-->啟動頁優化
- (三)-->基類Activity
- (四)-->減小Apk大小
- (五)-->多渠道打包
- (六)-->Apk混淆
- (七)-->Apk熱修復
- (八)-->App數據統計
- (九)-->App網絡數據解析
- (十)-->盡量不使用靜態變量保存數據
- (十一)-->應用內跳轉Scheme協議
- (十二)-->App長連接實現
- (十三)-->App輪詢操作
- (十四)-->App升級與更新
- (十五)-->內存對象序列化
- (十六)-->開發者選項
- (十七)-->Hybrid開發
- (十八)-->webview問題集錦
- (十九)-->Android studio中的單元測試
- (二十)-->代碼Review
- (二十一)-->Android中的UI優化
- (二十二)-->Android實用調試技巧
- (二十三)-->Android中保存靜態秘鑰實踐
- (二十四)-->內存泄露場景與檢測
- (二十五)-->MVC/MVVM/MVP簡單理解