Fork me on GitHub

手把手教你如何搭建一个自己的安卓快速开发框架之BaseActivity(一)

继上一篇博客已经好几个月没发布新博客了,中间因为教研室项目原因转手C#几个月,然后又加上各种事情(再加上懒 - -!)就落下了,并且有好多小伙伴给我留言上一篇播客的问题我都没能解答,在此给各位小伙伴说声抱歉了。 今天,又重拾安卓,准备慢慢构建一个自己的安卓快速开发框架,算是经验的总结和积累。网上这种东西很多,但是对于很多初学者而言需要的是动手实践,与此同时,不免就有自己 的感想,因此呢,我也动手并分享出来和大家一起学习。


为什么我们要构建一个BaseActivity呢,无非因为以下两点:

  • 1、避免重复代码
  • 2、统一管理

那么OK,我们构建一个自己的BaseActivity首先有什么需求呢?

  • 1、透明状态栏
  • 2、生命周期监控
  • 3、顶部统一的ToolBar

这是一个简单的Base,方便我们其他的Activity直接继承使用。

从上面可以看出,我们有3个需求,那么我们都放到一个BaseActivity就OK了,在这一个Activity写状态栏、toolbar、日志。但是,这样的话我们如果某个Activity不需要toorbar或者状态栏了怎么办呢?是不是又不能继承了。所以,我们可以将这两个功能拆开,写两个Activity,如果不需要其中一个功能,继承另一个就OK了。

经上面分析,我们此刻需要3个Activity,一个SuperActivity,一个StatusActivity,一个ToolBarActivity就OK了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package com.android.qht.BaseActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.android.qht.Util.LogUtil;
public abstract class superActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
LogUtil.e("--->onCreate");
}
public abstract int getContentViewId();
@Override
protected void onStart() {
super.onStart();
LogUtil.e("--->onStart");
}
@Override
protected void onStop() {
super.onStop();
LogUtil.e("--->onStop");
}
@Override
protected void onRestart() {
super.onRestart();
LogUtil.e("--->onRestart");
}
@Override
protected void onPause(){
super.onPause();
LogUtil.e("--->onpause");
}
@Override
protected void onResume() {
super.onResume();
LogUtil.e("--->onResume");
}
@Override
protected void onDestroy() {
super.onDestroy();
LogUtil.e("--->onDestroy");
}
}
这儿我用了一个日志工具类,先不管。
先看下我们的superActivity
1、重写了所有的生命周期,加上了日志监控
保证我们实时监控Activity的生命周期,这很必要,并且我们还可以在生命周期中加入butterKnife等的绑定和解绑等操作。
2、重写setContentView()方法,并加入了getContentViewId()抽象方法
重写这个方法保证每次初始化布局时传入我们子Activity的布局ID,然后这个抽象方法强制子类重写,传入布局ID,SonActivity->ToolBarActivity->SuperActivity,这样就保证了我们的每个界面只听从一个布局,而不是掺杂了父类Activity的布局。
OK,下来再看下我们的statusActivity:
package com.android.qht.BaseActivity;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.android.qht.myandroid.R;
public abstract class statusActivity extends superActivity {
private View statusView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setstatusColor(this, getResources().getColor(R.color.colorPrimary));//和toolbar一个颜色
}
/**
* 设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
public void setstatusColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 生成一个状态栏大小的矩形
// 添加 statusView 到布局中
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
if (statusView != null) {
decorView.removeView(statusView);
}
statusView = createStatusView(activity, color);
decorView.addView(statusView);
// 设置根布局的参数
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
rootView.setFitsSystemWindows(true);
rootView.setClipToPadding(true);
}
}
/**
* 生成一个和状态栏大小相同的矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @return 状态栏矩形条
*/
private View createStatusView(Activity activity, int color) {
// 获得状态栏高度
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
// 绘制一个和状态栏一样高的矩形
View statusView = new View(activity);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
statusBarHeight);
statusView.setLayoutParams(params);
statusView.setBackgroundColor(color);
return statusView;
}
/**
* 提供remove方法,在不需要状态栏时可以移除
*/
public void removeView(Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
if (statusView != null) {
decorView.removeView(statusView);
}
}
}

在这个Activity中,我们在子类传递的布局上面添加了一个头部状态栏,颜色和ToolBar一样。先别着急,再看一下我们的ToolBarActivity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.android.qht.BaseActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.android.qht.Util.ToastUtil;
import com.android.qht.myandroid.R;
/**
* ToolBar Activity.
*/
public abstract class ToolBarActivity extends statusActivity {
private TextView mToolbarTitle;
private TextView mToolbarSubTitle;
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
/*
toolbar.setLogo(R.mipmap.ic_launcher);
toolbar.setTitle("Title");
toolbar.setSubtitle("Sub Title");
*/
mToolbarTitle = (TextView) findViewById(R.id.toolbar_title);
mToolbarSubTitle = (TextView) findViewById(R.id.toolbar_subtitle);
if (mToolbar != null) {
//将Toolbar显示到界面
setSupportActionBar(mToolbar);
}
if (mToolbarTitle != null) {
//getTitle()的值是activity的android:lable属性值
mToolbarTitle.setText(getTitle());
//设置默认的标题不显示
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_tool_bar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.action_item1:
ToastUtil.showToastShort("回到首页");
break;
case R.id.action_item2:
ToastUtil.showToastShort("分享");
break;
case R.id.action_item3:
ToastUtil.showToastShort("扫一扫");
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onStart() {
super.onStart();
/**
* 判断是否有Toolbar,并默认显示返回按钮
*/
if(null != getToolbar() && isShowBacking()){
showBack();
}
}
/**
* 获取头部标题的TextView
* @return
*/
public TextView getToolbarTitle(){
return mToolbarTitle;
}
/**
* 获取头部副标题的TextView
* @return
*/
public TextView getSubTitle(){
return mToolbarSubTitle;
}
/**
* 设置头部标题
* @param title
*/
public void setToolBarTitle(CharSequence title) {
if(mToolbarTitle != null){
mToolbarTitle.setText(title);
}else{
getToolbar().setTitle(title);
setSupportActionBar(getToolbar());
}
}
/**
* this Activity of tool bar.
* 获取头部.
* @return support.v7.widget.Toolbar.
*/
public Toolbar getToolbar() {
return (Toolbar) findViewById(R.id.toolbar);
}
/**
* 版本号小于21的后退按钮图片
*/
private void showBack(){
//setNavigationIcon必须在setSupportActionBar(toolbar);方法后面加入
getToolbar().setNavigationIcon(R.mipmap.back);
getToolbar().setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
}
/**
* 是否显示后退按钮,默认显示,可在子类重写该方法.
* @return
*/
protected boolean isShowBacking(){
return true;
}
}

我们在ToorBarActivity中写了ToorBar的实现,因为我们的ToolBar是include方式加入到子Activity中的,所以我们是按照正常的方式初始化ToolBar并写了它的一些方法。

最终我们的加载顺序是这样的:

1、先加载子Activity的Layout(包括ToolBar)
2、再加载顶部状态栏
3、再初始化ToolBar(findviewbyid)
4、再初始化其他控件(findviewbyid)

总体的过程就是这样,我这个BaseActivity比较简单,只是帮助入门者建立一个这样的构建思想,建立自己的框架概念和体系。

下一篇我会带大家一起封装一些常用的工具类+ButterKnife+retrofit+RXJava,敬请期待。

csdn地址:http://blog.csdn.net/u012534831
github地址:https://github.com/qht1003077897/AppFrame
个人博客地址:https://qht1003077897.github.io/
QQ:1003077897

欢迎交流。