企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
在Java中,我们习惯将常用的代码放到对应的工具类中,例如ToastUtils、NetworkUtils、ImageLaoderUtils等。以NetworkUtils为例,该类中我们通常会放入Android经常需要使用的网络相关方法。比如,我们现在有一个判断手机网络是否可用的方法: ``` public class NetworkUtils { public static boolean isMobileConnected(Context context) { if (context ! = null) { ConnectivityManager mConnectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mMobileNetworkInfo = mConnectivityManager .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); if (mMobileNetworkInfo ! = null) { return mMobileNetworkInfo.isAvailable(); } } return false; } } ``` 在需要调用的地方,我们通常会这样写: ``` Boolean isConnected = NetworkUtils.isMobileConnected(context); ``` 虽然用起来比没封装之前优雅了很多,但是每次都要传入context,造成的烦琐我们先不计较,重要是可能会让调用者忽视context和mobileNetwork间的强联系。作为代码的使用者,我们**更希望在调用时省略NetworkUtils类名,并且让isMobileConnected可以看起来像context的一个属性或方法**。我们期望的是下面这样的使用方式: ``` Boolean isConnected = context.isMobileConnected(); ``` 由于Context是Andorid SDK自带的类,我们无法对其进行修改,在Java中目前只能通过继承Context新增静态成员方法来实现。如果你阅读过前面的内容,应该知道在Kotlin中,我们**通过扩展函数就能简单地实现**: ``` fun Context.isMobileConnected(): Boolean { val mNetworkInfo = connectivityManager.activeNetworkInfo if (mNetworkInfo ! = null) { return mNetworkInfo.isAvailable } return false } ``` 我们只需将以上代码放入对应文件中即可。这时我们已经摆脱了类的束缚,使用方式如下: ``` val isConnected = context.isMobileConnected(); ``` 值得一提的是,在Android中对Context的生命周期需要进行很好地把控。这里我们**应该使用ApplicationContext,防止出现生命周期不一致导致的内存泄漏或者其他问题**。 除了上述方法,我们还有许多这样通用的代码,我们可以将它们放入不同的文件下。包括上面提到的Snackbar,我们也可以为其创建一个SnackbarUtils,这样会提供非常多的便利。但是需要注意的是,我们不能滥用这个特性具体原因在后面(被滥用的扩展函数)这一章节介绍。