android封装框架入门之从封装确定、取消对话框开始
尊重原创,转载请注明出处:原文查看惊喜更多 http://blog.csdn.net/qq137722697
最近,封装了一个轻量级的网络异步网络请求框架MHttpUtils(传送门),由于非常喜欢RxJava和Retrofit等的链式编程风格,于是自己捣鼓着按这种风格来封装,期间的一些封装思路抽取出来以备记录查阅。
为什么要封装
封装在减少重复代码的同时还能提高开发效率,这便是java中的提高代码重用性的思想,好的封装还能提高app的性能和效率。
封装应有哪些特点
1、易用性
封装的框架应该要容易使用,减少代码量,降低入门的门槛,提供相应的用户操作反馈回调,使用者只用关心经常变动的地方。
2、实用性
封装的框架应该要具有很好的实用性,否则封装就没有了意义
3、尽量保证单例
保持单例主要是为了减少内存资源的占用率,提高app的效率。(这里说的尽量,因为有些东西使用单例模式反而会有诸多限制)
开始封装确定、取消对话框
下面通过封装一个确定、取消对话框的简单例子来看看一种封装的思路。
以前你可能会在每个需要使用对话框的地方写上下面的代码:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
builder.setMessage(message);
builder.setIcon(iconResId);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//取消的逻辑处理
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//确定的逻辑处理
}
});
builder.create().show();
看着不多,如果是同一个类有多处调用的话还可以提为全局变量,但是如果有很多activity都要调用的话就觉得好没意义,必须抽取出来呀。
首先来看如何保证单例(必须单例模式啊):
//确定、取消对话框
public class MDialog {
private static MDialog mDialog;
private MDialog() {
}
public static MDialog build() {
if (mDialog == null) {
mDialog = new MDialog();
}
return mDialog;
}
}
再来考虑一下哪些是用户经常变动的属性,写了那么多builder的你一定知道title、message、icon是由用户决定的,其实既然抽取出来了,在哪里显示的话一定要告诉MDialog,所以还要加上一个上下文对象context。
为MDialog加上title、message、icon、context四个属性,如何赋值呢?又如何像rxjava、retrofit等的一条链的就写完整个调用过程呢?
我猜你肯定想到链式编程了,链式编程的核心思想就是方法的返回值为对象自己,这样每调用一个方法返回的还是对象本身,那么有多少这样的方法就能调多少了。
完善一下代码:
//确定、取消对话框
public class MDialog {
...//省略了上面的代码
//设置上下文对象
public MDialog with(Context context) {
this.context = context;
return this;
}
//设置标题
public MDialog title(String title) {
this.title = title;
return this;
}
// 设置消息
public MDialog message(String message) {
this.message = message;
return this;
}
//设置图标资源id
public MDialog iconResId(int iconResId) {
this.iconResId = iconResId;
return this;
}
}
重点来了,用户点击确定之后的逻辑处理应该由调用者自行处理,这里就要使用非常有用的回调思想了,提供一个接口,用户实现了这个接口,当用户交互的时候触发某个事件而回调给用户实现的这个接口中。
如何定义回调接口?用户交互的无非就是点击确认、取消两个按钮,所以这样定义:
interface IOnClickCallback {
void onOk();//点击确定的时候回调
void onCancel();//点击取消的时候回调
}
细心的你会发现其实很多时候用户点击取消是不需要做任何事的,如何让onCancel方法可以重写但又不是必须重写呢?对,抽象类就可以做到,所以我们改造一下上面的代码(效果在下面给出):
interface IOnClickCallback {
void onOk();//点击确定的时候回调
}
//这里加上static是因为这个接口是写在MDialog中的,属于内部类
public static abstract class OnClickCallback implements IOnClickCallback {
public void onCancel() {//点击取消的时候回调
}
}
最后调用一个show方法即显示对话框:
public void show(final OnClickCallback callback) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (!TextUtils.isEmpty(title)) {
builder.setTitle(title);
}
if (!TextUtils.isEmpty(message)) {
builder.setMessage(message);
}
if (iconResId != 0) {
builder.setIcon(iconResId);
}
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callback.onCancel();//点击取消的时候回调
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callback.onOk();//点击确认的时候回调
}
});
builder.create().show();
}
至此,所有的封装已经完毕,贴一下完整的代码:
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
/**
* 自定义确定取消对话框
* Created by HDL on 2016/11/22.
*/
//确定、取消对话框
public class MDialog {
private static MDialog mDialog;
private String title;//标题
private String message;//提示内容
private int iconResId;//图标
private Context context;//上下文对象
private MDialog() {
}
public static MDialog build() {
if (mDialog == null) {
mDialog = new MDialog();
}
return mDialog;
}
//设置上下文对象
public MDialog with(Context context) {
this.context = context;
return this;
}
// 设置标题
public MDialog title(String title) {
this.title = title;
return this;
}
//设置消息
public MDialog message(String message) {
this.message = message;
return this;
}
//设置图标
public MDialog iconResId(int iconResId) {
this.iconResId = iconResId;
return this;
}
//显示对话框
public void show(final OnClickCallback callback) {
//这里建议使用V7包中的AlertDialog,导包见头文件
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (!TextUtils.isEmpty(title)) {
builder.setTitle(title);
}
if (!TextUtils.isEmpty(message)) {
builder.setMessage(message);
}
if (iconResId != 0) {
builder.setIcon(iconResId);
}
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callback.onCancel();
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callback.onOk();
}
});
builder.create().show();
}
interface IOnClickCallback {
void onOk();//点击确定的时候回调
}
public static abstract class OnClickCallback implements IOnClickCallback {
public void onCancel() {//点击取消的时候回调
}
}
}
使用
下面来看看怎么使用(是不是没有重写):
大多数情况下是这样使用的:
1、设置标题、内容、处理确定逻辑
MDialog.build()
.with(this)
.title("警告")
.message("您确定要删除吗?")
.show(new MDialog.OnClickCallback() {
@Override
public void onOk() {
ToastUtils.showMsg(MDialogDemoActivity.this, "点击确定了");
}
});
是不是没有重写onCancel方法?因为很多时候是不需要处理的,如果需要,重写一下就可以了
2、全部调用
MDialog.build()
.with(this)
.title("警告")
.message("您确定要删除吗?")
.iconResId(R.mipmap.warning)
.show(new MDialog.OnClickCallback() {
@Override
public void onOk() {
ToastUtils.showMsg(MDialogDemoActivity.this, "点击确定了");
}
@Override
public void onCancel() {
ToastUtils.showMsg(MDialogDemoActivity.this, "点击取消了");
}
});
3、只设置内容
注意:当不设置title的时候,设置了icon,icon也是不显示出来的
MDialog.build()
.with(this)
.message("您确定要删除吗?")
.show(new MDialog.OnClickCallback() {
@Override
public void onOk() {
ToastUtils.showMsg(MDialogDemoActivity.this, "点击确定了");
}
});
验证单例
要验证其实很简单,只需将show方法的返回值类型从void改为对象本身即MDialog,然后在三个Activity中调用MDialog,然后答应一下对象就知道是不是同一个对象了。
下图是单例的验证:
是同一个吧,验证搞定。
总结
以上只是我在封装框架过程中使用到的思想,demo也比较简单,有人可能会觉得dialog不会封装这麻烦的,仁者见仁智者见智吧,只是提供一种思路,如果你觉得这篇文章还不错,顶一下