最近接手了一个新项目,在项目中看着繁重的BaseActivity不禁让我开始思考。
在开发中Activity中承担着繁重的任务
- 组件绑定
- 事件跳转
- 网络请求
- 业务逻辑
- 动画
- 窗口管理(横竖屏。沉浸式,Theme)
- 生命周期
其中大多数都是重复繁重的内容,所以我们才去考虑减少Activity的负担。
目前的方式有
1.采用MVP,MVVM模式通过分层解耦
2.利用baseActivity抽象重复内容
3.利用自定义组件重用
当然还有很多其他的方法水平有限就不一一列出!
现在开始整理出一个自己的BaseActivity
首先我们来分解一个Activity中任务
组件绑定、事件跳转、窗口管理(横竖屏。沉浸式,Theme)、生命周期这三个是每个Activity必有的,我们开始一一分解
1.组件绑定、事件跳转我们抽象出三个方法分别用于获取组件、给组件赋值、绑定数据(注:可以继承Activity,或者FragmentActivty或者AppCompatActivity,但是现在都是Activity+Fragment模式开发 所以推荐用AppCompatActivity ,FragmentActivty不支持tooslBar….)
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
/**
* context
*/
protected Context ctx;
/**
* 初始化界面
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
/**
* 绑定事件
*/
protected abstract void setEvent();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initData();
setEvent();
ctx = this;
}
}
2.窗口管理(横竖屏。沉浸式,Theme)
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
/**
* 是否沉浸状态栏
**/
private boolean isSetStatusBar = true;
/**
* 是否允许全屏
**/
private boolean isAllowFullScreen = true;
/**
* 是否禁止旋转屏幕
**/
private boolean isAllowScreenRoate = false;
/**
* context
**/
protected Context ctx;
/**
* 初始化界面
**/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
/**
* 绑定事件
*/
protected abstract void setEvent();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initData();
setEvent();
ctx = this;
if (isSetStatusBar) {
steepStatusBar();
}
if (isAllowFullScreen) {
setFullScreen();
}
if (!isAllowScreenRoate) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
/**
* 窗口全屏
*/
private void setFullScreen() {
this.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
/**
* [沉浸状态栏]
*/
private void steepStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 透明状态栏
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 透明导航栏
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
/**
* [是否允许全屏]
*
* @param allowFullScreen
*/
public void setAllowFullScreen(boolean allowFullScreen) {
this.isAllowFullScreen = allowFullScreen;
}
/**
* [是否设置沉浸状态栏]
*
* @param allowFullScreen
*/
public void setSteepStatusBar(boolean isSetStatusBar) {
this.isSetStatusBar = isSetStatusBar;
}
/**
* [是否允许屏幕旋转]
*
* @param isAllowScreenRoate
*/
public void setScreenRoate(boolean isAllowScreenRoate) {
this.isAllowScreenRoate = isAllowScreenRoate;
}
}
好吧现在我们的BaseActivity已经很乱了,有什么周期要处理。。。肿么办?
3.生命周期
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
/**
* 是否输出日志信息
**/
private boolean isDebug;
/**
* 是否沉浸状态栏
**/
private boolean isSetStatusBar = true;
/**
* 是否允许全屏
**/
private boolean isAllowFullScreen = true;
/**
* 是否禁止旋转屏幕
**/
private boolean isAllowScreenRoate = false;
/**
* context
**/
protected Context ctx;
/**
* 初始化界面
**/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
/**
* 绑定事件
*/
protected abstract void setEvent();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "--->onCreate()");
initView();
initData();
setEvent();
ctx = this;
isDebug = MApplication.isDebug;
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "--->onStart()");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "--->onResume()");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "--->onRestart()");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "--->onPause()");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "--->onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "--->onDestroy()");
}
}
别问我打印这样多干嘛 有时候开发中会遇到打印生命周期的情况,先写了吧!下面还有自己维护Activity栈和跳转Activity封装!!!
好吧!已经150行代码了,怎么一不小心就写这样多了 !不行太乱了,又变成一个繁重杂乱的baseActivity咯!我们把Activity栈和窗口管理分别抽出!
import android.app.Activity;
import java.util.Stack;
/**
* Activity管理类
*/
public class ActivityStackManager {
private static Stack<Activity> activityStack;
private static ActivityStackManager instance;
private ActivityStackManager() {
}
public synchronized static ActivityStackManager getActivityStackManager() {
if (instance == null) {
instance = new ActivityStackManager();
}
return instance;
}
/**
* 关闭activity
* finish the activity and remove it from stack.
*
* @param activity
*/
public void popActivity(Activity activity) {
if (activityStack == null) return;
if (activity != null) {
activity.finish();
activity.overridePendingTransition(0, 0);
activityStack.remove(activity);
activity = null;
}
}
/**
* 获取当前的Activity
* get the current activity.
*
* @return
*/
public Activity currentActivity() {
if (activityStack == null || activityStack.isEmpty()) return null;
Activity activity = (Activity) activityStack.lastElement();
return activity;
}
/**
* 获取最后一个的Activity
* get the first activity in the stack.
*
* @return
*/
public Activity firstActivity() {
if (activityStack == null || activityStack.isEmpty()) return null;
Activity activity = (Activity) activityStack.firstElement();
return activity;
}
/**
* 添加activity到Stack
* add the activity to the stack.
*
* @param activity
*/
public void pushActivity(Activity activity) {
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* remove所有Activity
* remove all activity.
*/
public void popAllActivity() {
if (activityStack == null) return;
while (true) {
if (activityStack.empty()) {
break;
}
Activity activity = currentActivity();
popActivity(activity);
}
}
/**
* remove所有Activity但保持目前的Activity
* remove all activity but keep the current activity.
*/
public void popAllActivityWithOutCurrent() {
Activity activity = currentActivity();
while (true) {
if (activityStack.size() == 1) {
break;
}
if (firstActivity() == activity) {
break;
} else {
popActivity(firstActivity());
}
}
}
}
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.view.Window;
import android.view.WindowManager;
/**
* 屏幕管理类
*/
public class ScreenManager {
private static ScreenManager instance;
private ScreenManager() {
}
public synchronized static ScreenManager getInstance() {
if (instance == null) {
instance = new ScreenManager();
}
return instance;
}
/**
* 窗口全屏
*/
public void setFullScreen(boolean isChange,BaseActivity mActivity) {
if(!isChange){
return;
}
mActivity.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
mActivity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
/**
* [沉浸状态栏]
*/
public void setStatusBar(boolean isChange,BaseActivity mActivity) {
if (!isChange){
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 透明状态栏
mActivity.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 透明导航栏
mActivity.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
/**
* 旋转屏幕
**/
public void setScreenRoate(boolean isChange, BaseActivity mActivity) {
if (!isChange) {
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
我们的BaseActivity就成这样了!
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
/**
* 是否沉浸状态栏
**/
private boolean isStatusBar = true;
/**
* 是否允许全屏
**/
private boolean isFullScreen = true;
/**
* 是否禁止旋转屏幕
**/
private boolean isScreenRoate = false;
/**
* context
**/
protected Context ctx;
/**
* 是否输出日志信息
**/
private boolean isDebug;
/**
* 初始化界面
**/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
/**
* 绑定事件
*/
protected abstract void setEvent();
private ScreenManager screenManager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "--->onCreate()");
initView();
initData();
setEvent();
ctx = this;
ActivityStackManager.getActivityStackManager().pushActivity(this);
screenManager = ScreenManager.getInstance();
screenManager.setStatusBar(isStatusBar, this);
screenManager.setScreenRoate(isScreenRoate, this);
screenManager.setFullScreen(isFullScreen, this);
}
/**
* 跳转Activity
* skip Another Activity
*
* @param activity
* @param cls
*/
public static void skipAnotherActivity(Activity activity,
Class<? extends Activity> cls) {
Intent intent = new Intent(activity, cls);
activity.startActivity(intent);
activity.finish();
}
/**
* 退出应用
* called while exit app.
*/
public void exitLogic() {
ActivityStackManager.getActivityStackManager().popAllActivity();//remove all activity.
System.exit(0);//system exit.
}
/**
* [是否设置沉浸状态栏]
* @param statusBar
*/
public void setStatusBar(boolean statusBar) {
isStatusBar = statusBar;
}
/**
* [是否设置全屏]
* @param fullScreen
*/
public void setFullScreen(boolean fullScreen) {
isFullScreen = fullScreen;
}
/**
* [是否设置旋转屏幕]
* @param screenRoate
*/
public void setScreenRoate(boolean screenRoate) {
isScreenRoate = screenRoate;
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "--->onStart()");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "--->onResume()");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "--->onRestart()");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "--->onPause()");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "--->onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "--->onDestroy()");
ActivityStackManager.getActivityStackManager().popActivity(this);
}
}
贴上一张使用效果:
import android.os.Bundle;
import android.support.annotation.Nullable;
import net.lililearn.baseproject.R;
import net.lililearn.baseproject.base.BaseActivity;
import net.lililearn.baseproject.ui.fragment.HomeFragment;
public class MainActivity extends BaseActivity {
private HomeFragment mHomeFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void initView() {
setFullScreen(false);
removeAllStackFragment();
mHomeFragment = new HomeFragment();
replaceContent(mHomeFragment, false);
}
@Override
protected void initData() {
}
@Override
protected void setEvent() {
}
}
最后终于完成了一个BaseActivity,感觉还不错!!后面继续BaseFragment