Android常见基类封装

前段时间一直在忙找工作的事,好久没有写博客了,最近在学习一个实战项目 http://coding.imooc.com/class/evaluation/100.html, 讲到了基类的封装,故在此记录一下。主要涉及到Activity,Fragment和RecyclerView的适配器的封装。

一、Activity基类的封装

由于都有详细的注释,并且代码简单,就不再解释了,文中使用了ButterKnife。

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
public abstract class Activity extends AppCompatActivity {
protected Unbinder mUnbinder;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在界面初始化之前初始化窗口
initWindows();
if (initArgs(getIntent().getExtras())) {
int layoutId = getContentLayoutId();
setContentView(layoutId);
initWidget();
initData();
} else {
finish();
}
}
/**
* 初始化窗口
*/
protected void initWindows(){
}
/**
* 初始化参数
* @param bundle 需要初始化的参数
* @return 如果参数正确返回true,错误返回false
*/
protected boolean initArgs(Bundle bundle) {
return true;
}
/**
* 获得当前界面的资源文件Id
* @return 界面的资源文件Id
*/
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget() {
mUnbinder = ButterKnife.bind(this);
}
/**
* 初始化数据
*/
protected void initData() {
}
@Override
public boolean onSupportNavigateUp() {
//当点击界面导航返回时,finish当前界面
finish();
return super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
//获得当前Activity的所有Fragment
@SuppressWarnings("RestrictedApi")
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
if (fragmentList != null && fragmentList.size() > 0){
for (Fragment fragment : fragmentList) {
//是否是我们自定义的Fragment
if (fragment instanceof cn.codekong.common.app.Fragment){
if (((cn.codekong.common.app.Fragment)fragment).onBackPressed()){
//Fragment处理了返回事件
return;
}
}
}
}
super.onBackPressed();
finish();
}
}

二、Fragment基类的封装

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
public abstract class Fragment extends android.support.v4.app.Fragment {
protected View mRoot;
protected Unbinder mRootUnbinder;
@Override
public void onAttach(Context context) {
super.onAttach(context);
initArgs(getArguments());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mRoot == null){
int layoutId = getContentLayoutId();
//初始化当前的根布局,但是不在创建时就添加到container里面
View root = inflater.inflate(layoutId, container, false);
initWidget(root);
mRoot = root;
}else {
if (mRoot.getParent() != null){
//把当前的根布局从其父控件中移除
((ViewGroup)mRoot.getParent()).removeView(mRoot);
}
}
return mRoot;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//当View创建完成后初始化数据
initData();
}
/**
* 初始化参数
* @param bundle 需要初始化的参数
*/
protected void initArgs(Bundle bundle) {
}
/**
* 获得当前界面的资源文件Id
*
* @return 资源文件Id
*/
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget(View root) {
mRootUnbinder = ButterKnife.bind(this, root);
}
/**
* 初始化数据
*/
protected void initData() {
}
/**
* 返回按键触发时调用
* @return 返回true代表自己处理返回逻辑,Activity不用处理
* 返回false代表没有处理逻辑,交由Activity处理
*/
public boolean onBackPressed(){
return false;
}
}

三、RecyclerView适配器基类的封装

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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
public abstract class RecyclerAdapter<Data> extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>
implements View.OnClickListener, View.OnLongClickListener, AdapetrCallback<Data> {
private final List<Data> mDataList;
private AdapterListener<Data> mAdapterListener;
/**
* 构造函数
*/
public RecyclerAdapter() {
this(null);
}
public RecyclerAdapter(AdapterListener<Data> listener) {
this(new ArrayList<Data>(), listener);
}
public RecyclerAdapter(List<Data> dataList, AdapterListener<Data> listener) {
this.mDataList = dataList;
this.mAdapterListener = listener;
}
/**
* 创建一个ViewHolder
*
* @param parent RecyclerView
* @param viewType 界面的类型,约定为xml布局的Id
* @return
*/
@Override
public ViewHolder<Data> onCreateViewHolder(ViewGroup parent, int viewType) {
//将xml布局初始化为View
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View root = inflater.inflate(viewType, parent, false);
ViewHolder<Data> holder = onCreateViewHolder(root, viewType);
//设置View的Tag将View和Holder进行关联
root.setTag(R.id.tag_recycler_holder, holder);
//设置事件点击
root.setOnClickListener(this);
root.setOnLongClickListener(this);
//进行界面注解绑定
holder.mUnbinder = ButterKnife.bind(holder, root);
//绑定callback
holder.mCallback = this;
return holder;
}
/**
* 获得一个新的ViewHolder
*
* @param root 根布局
* @param viewType 布局类型,其实就是xml的Id
* @return ViewHolder
*/
protected abstract ViewHolder<Data> onCreateViewHolder(View root, int viewType);
/**
* 复写默认的布局类型返回
*
* @param position 坐标
* @return 重写后返回的是xml文件的Id
*/
@Override
public int getItemViewType(int position) {
return getItemViewType(position, mDataList.get(position));
}
/**
* 得到布局的类型
*
* @param position 坐标
* @param data 当前的数据
* @return xml文件的Id, 用于创建ViewHolder
*/
@LayoutRes
protected abstract int getItemViewType(int position, Data data);
/**
* 绑定数据到Holder上
*
* @param holder ViewHolder
* @param position 坐标
*/
@Override
public void onBindViewHolder(ViewHolder<Data> holder, int position) {
//获得需要绑定的数据
Data data = mDataList.get(position);
//触发绑定方法
holder.bind(data);
}
/**
* 得到当前集合的数据量
*
* @return
*/
@Override
public int getItemCount() {
return mDataList.size();
}
/**
* 插入一条数据并通知插入更新
*
* @param data
*/
public void add(Data data) {
mDataList.add(data);
notifyItemInserted(mDataList.size() - 1);
}
/**
* 插入多条数据,并通知这一段集合更新
*
* @param dataList
*/
public void add(Data... dataList) {
if (dataList != null && dataList.length > 0) {
int startPos = mDataList.size();
Collections.addAll(mDataList, dataList);
notifyItemRangeInserted(startPos, dataList.length);
}
}
/**
* 插入多条数据,并通知这一段集合更新
*
* @param dataList
*/
public void add(Collection<Data> dataList) {
if (dataList != null && dataList.size() > 0) {
int startPos = mDataList.size();
mDataList.addAll(dataList);
notifyItemRangeInserted(startPos, dataList.size());
}
}
/**
* 删除操作
*/
public void clear() {
mDataList.clear();
notifyDataSetChanged();
}
/**
* 替换为一个新的集合,其中包括清空
*
* @param dataList
*/
public void replace(Collection<Data> dataList) {
mDataList.clear();
if (dataList == null || dataList.size() == 0) {
return;
}
mDataList.addAll(dataList);
notifyDataSetChanged();
}
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (mAdapterListener != null) {
//得到ViewHolder当前对应的适配器中的坐标
int pos = viewHolder.getAdapterPosition();
//回调方法
mAdapterListener.onItemClick(viewHolder, mDataList.get(pos));
}
}
@Override
public boolean onLongClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (mAdapterListener != null) {
//得到ViewHolder当前对应的适配器中的坐标
int pos = viewHolder.getAdapterPosition();
//回调方法
mAdapterListener.onItemLongClick(viewHolder, mDataList.get(pos));
return true;
}
return false;
}
/**
* 设置监听器
*
* @param adapterListener
*/
public void setAdapterListener(AdapterListener<Data> adapterListener) {
this.mAdapterListener = adapterListener;
}
/**
* 自定义监听器
*
* @param <Data> 泛型
*/
public interface AdapterListener<Data> {
//当Item点击时出发
void onItemClick(RecyclerAdapter.ViewHolder holder, Data data);
//当Item长按时触发
void onItemLongClick(RecyclerAdapter.ViewHolder holder, Data data);
}
/**
* 自定义的ViewHolder
*
* @param <Data> 泛型类型
*/
public static abstract class ViewHolder<Data> extends RecyclerView.ViewHolder {
protected Data mData;
private Unbinder mUnbinder;
private AdapetrCallback<Data> mCallback;
public ViewHolder(View itemView) {
super(itemView);
}
/**
* 用于绑定数据
*
* @param data 需要绑定的数据
*/
void bind(Data data) {
this.mData = data;
onBind(data);
}
/**
* 当数据绑定时进行回调,必须复写
*
* @param data 需要绑定的数据
*/
protected abstract void onBind(Data data);
/**
* holder自己对自己的Data进行更新
*
* @param data 需要更新的数据
*/
public void updateData(Data data) {
if (mCallback != null) {
mCallback.update(data, this);
}
}
}
}
1
2
3
public interface AdapetrCallback<Data> {
void update(Data data, RecyclerAdapter.ViewHolder<Data> holder);
}

四、后记

基类的封装可以有效地提高代码的复用性,减少代码了,希望上面的分享可以帮助到需要的人。

如果博客对您有帮助,不妨请我喝杯咖啡...