- 关键字:通用、高效
- Key Word:Universal、Effective
- 本文中提到的“高效”,不特指运行时执行效率高,偏向于开发阶段时调用方便。
一、设计目标和主要突破点
设计目标就是造轮子,但不是在别人造好轮子后的重复劳动,而是把造好的轮子加工成自己的轮子,使其同时具备通用和高效的特点。
从另一方面讲,通用和高效常常是互相矛盾的两个指标。高效的往往是专用的,而通用的往往会牺牲效率,就像婴儿爽身粉比普通爽身粉更适合涂在宝宝的皮肤上,而婴儿爽身粉也只有涂在宝宝的皮肤上时才能充分体现它的优势一样。诚然,想做出一款所有肤质上效果都最优的爽身粉难度很大,但我们的题目是“多个产品”,不是“所有产品”。现在大厂的产品都是成系列的,比如蚂蚁金服的产品如口碑外卖可以嵌套在支付宝内也可以单独成为一个产品,再比如嵌套在美团APP内的美团外卖也可以单独成为一个产品。能做出一款适合且仅适合指定系列产品的轮子,是现阶段的最佳选择。
二、功能分析和关键拔高点
从设计目标的选择中我们可以发现,本文之所以能提高轮子的效率,本质是因为对其适用范围做了调整,专注应用场景中会出现的情况,摒弃实际开发中不会遇到的条件。所以,我们可以通过细化适用范围的方式进一步提高轮子的使用效率。
public static void sendBroadcast(Context context, String action, Bundle bundle) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtras(bundle);
context.sendBroadcast(intent);
}
以Android中发送普通广播为例,影响该功能适用范围的关键点在三个参数(context/action/bundle)上。context确定了广播发送者所在的进程,action确定了广播接收者的过滤条件,bundle确定了广播附带的参数。发出广播的context可以是Application也可以是Activity,而整个项目所在的进程是唯一确认的,我们可以将项目中发送广播的逻辑统一改成由Application作为context发出,这样在发送广播的地方就只需要关注两个参数即可(context/action/bundle),显然需要关注的参数越少,项目开发阶段出现问题的概率就会越小。
public static void sendBroadcast(String action, Bundle bundle) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtras(bundle);
MyApplication.getInstance().sendBroadcast(intent);
}
- 少年,你还记得把context传进网络模块、传进数据模块、传进控制模块,最后引发内存泄漏的恐惧么?
当然,我们可以继续对参数的适用范围进行分级,如果广播的action是根据页面进行划分的,例如支付页发出的广播统一以ACTION_PAY为action,那么我们在发送支付相关的广播时就可以进一步节省一个参数(context/action/bundle)。不过从实际的代码开发总结的经验中可以发现,将action作为统一参数进行封装的收益并不明显,如果以实用价值高为标准的话,建议细分到context层即可。
public static void sendBroadcast(Bundle bundle) {
Intent intent = new Intent();
intent.setAction(ACTION_PAY);
intent.putExtras(bundle);
MyApplication.getInstance().sendBroadcast(intent);
}
三、代码实现和最终得分点
上文以Android中发送普通广播功能为例子提出了通过细化参数适用范围来提高功能库使用效率的技巧,但技巧始终只是技巧,没有足够扎实的功底终究是做不出完美的功能库的。基本功就靠大家积年累月的工作经验吧,以下是本文示例中涉及到的部分代码。
public class MyApplication extends Application {
private static Application instance = new Application();
/**
* 允许从Application中统一获取context。
*/
public static Application getInstance() {
return instance;
}
}
public class Tools {
/**
* 普通方式发送广播,需要传入三个参数,当需要从网络模块/数据模块/控制模块等context
* 概念较弱的模块中发出广播时,需要将context一路传进去,此时发生内存泄漏的风险很大。
*/
public static void sendBroadcast(Context context, String action, Bundle bundle) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtras(bundle);
context.sendBroadcast(intent);
}
/**
* context统一从Application中获取,用完即释放,不用考虑内存泄漏的问题。
*/
public static void sendBroadcast(String action, Bundle bundle) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtras(bundle);
MyApplication.getInstance().sendBroadcast(intent);
}
}
public class PayActivity extends AppCompatActivity {
private static String ACTION_PAY = "ACTION_PAY";
/**
* context和action都用统一的方式获取,但应用面太窄,按个人喜好可以尝试,不推荐。
*/
public static void sendBroadcast(Bundle bundle) {
Intent intent = new Intent();
intent.setAction(ACTION_PAY);
intent.putExtras(bundle);
MyApplication.getInstance().sendBroadcast(intent);
}
}