01-18-01 Public API与SDK设计原则
Public API是什么
Public API是Android SDK中公开给开发者使用的接口。
定义标准:
// Public API:没有@hide注解,开发者可以直接使用publicclassActivityextendsContextThemeWrapper{publicvoidstartActivity(Intentintent){// ...}}API的三个层级
1. Public API
可见性:所有应用可用
// frameworks/base/core/java/android/app/Activity.javapackageandroid.app;/** Public API - 所有应用可用 */publicclassActivityextendsContextThemeWrapper{publicvoidonCreate(BundlesavedInstanceState){// 公开方法,所有应用可调用}publicvoidstartActivity(Intentintent){// 公开方法}}特点:
- 包含在Android SDK中
- API文档公开
- 永久向后兼容(不能随意修改)
2. System API(@SystemApi)
可见性:系统应用、特权应用可用
// frameworks/base/core/java/android/app/ActivityManager.javapackageandroid.app;publicclassActivityManager{/** System API - 只有系统应用可用 */@SystemApipublicvoidforceStopPackage(StringpackageName){// 强制停止应用,普通应用不能调用}}特点:
- 需要系统签名或特权权限
- 普通应用无法调用
- 用于系统级功能
3. Hidden API(@hide)
可见性:框架内部使用
// frameworks/base/core/java/android/app/Activity.javapackageandroid.app;publicclassActivityextendsContextThemeWrapper{/** * @hide Hidden API - 框架内部使用 */publicvoidperformCreate(BundlesavedInstanceState){// 内部方法,开发者不应调用}}特点:
- 不包含在SDK中
- 没有API文档
- 可能随时修改或删除
- Android 9+限制反射访问
Android SDK设计原则
1. 最小化原则(Minimal API Surface)
只暴露必要的API
// [未通过] 错误:暴露过多实现细节publicclassImageLoader{publicHttpClientgetHttpClient(){}publicCachegetCache(){}publicThreadPoolgetThreadPool(){}publicDecodergetDecoder(){}}// [通过] 正确:只暴露必要接口publicclassImageLoader{publicvoidload(Stringurl,ImageViewtarget){}publicvoidpreload(Stringurl){}publicvoidcancel(ImageViewtarget){}}Android实例:
// Activity只暴露必要方法publicclassActivity{// [通过] Public:开发者需要publicvoidstartActivity(Intentintent){}publicvoidfinish(){}// [未通过] Hidden:开发者不需要/** @hide */publicvoidperformCreate(BundlesavedInstanceState){}}2. 稳定性原则(API Stability)
Public API不能随意修改
// [未通过] 错误:修改Public API签名// Android 5.0publicvoidsetData(Stringdata){}// Android 6.0// public void setData(int data) { } // [未通过] 破坏兼容性// [通过] 正确:添加重载方法publicvoidsetData(Stringdata){}publicvoidsetData(intdata){}// [通过] 新增重载实际案例:Notification API演进
// API 1-10:简单通知Notificationn=newNotification(icon,tickerText,when);// API 11+:Builder模式(新增,不删除旧API)Notificationn=newNotification.Builder(context).setContentTitle("Title").setContentText("Text").build();// API 26+:通知渠道(强制要求,但不删除旧API)NotificationChannelchannel=newNotificationChannel("channel_id","Channel",NotificationManager.IMPORTANCE_DEFAULT);notificationManager.createNotificationChannel(channel);Notificationn=newNotification.Builder(context,"channel_id").setContentTitle("Title").build();3. 语义化原则(Semantic Naming)
命名清晰明确
// [未通过] 错误:命名不清publicclassMgr{}publicvoiddoIt(){}publicvoidprocess(){}// [通过] 正确:语义明确publicclassNotificationManager{}publicvoidstartActivity(){}publicvoidregisterReceiver(){}Android命名规范:
// 动词开头:动作startActivity()stopService()registerReceiver()// 名词:获取状态getWindow()getApplicationContext()// is/has:布尔判断isFinishing()hasWindowFocus()// set:设置属性setContentView()setResult()4. 一致性原则(Consistency)
相似功能使用相似模式
// [通过] 一致的命名模式context.startActivity()context.startService()context.stopService()context.bindService()context.registerReceiver()context.unregisterReceiver()// [通过] 一致的参数顺序voidstartActivity(Intentintent)voidstartActivity(Intentintent,Bundleoptions)voidstartActivityForResult(Intentintent,intrequestCode)voidstartActivityForResult(Intentintent,intrequestCode,Bundleoptions)5. 向后兼容原则(Backward Compatibility)
新版本不破坏旧代码
// [通过] 正确:使用targetSdkVersion控制行为if(getApplicationInfo().targetSdkVersion>=Build.VERSION_CODES.M){// Android 6.0+行为:运行时权限checkRuntimePermission();}else{// Android 6.0以前行为:安装时权限grantAllPermissions();}6. 可测试性原则(Testability)
依赖接口而非实现
// [未通过] 错误:依赖具体实现publicclassLocationManager{publicLocationgetLastKnownLocation(){// 直接访问GPS硬件,难以测试returngpsHardware.getLocation();}}// [通过] 正确:依赖接口publicinterfaceLocationProvider{LocationgetLastKnownLocation();}publicclassLocationManager{privatefinalLocationProviderprovider;publicLocationManager(LocationProviderprovider){this.provider=provider;}publicLocationgetLastKnownLocation(){returnprovider.getLastKnownLocation();}}// 测试时可以MockclassMockLocationProviderimplementsLocationProvider{override fungetLastKnownLocation()=Location("mock")}API设计实战
案例1:权限请求API设计
Android 6.0以前:
// Manifest声明即可,但不灵活<uses-permission android:name="android.permission.CAMERA"/>Android 6.0+:
// Activity.java - 运行时权限API设计// [通过] 简洁的请求APIpublicvoidrequestPermissions(String[]permissions,intrequestCode){// ...}// [通过] 统一的回调publicvoidonRequestPermissionsResult(intrequestCode,String[]permissions,int[]grantResults){// ...}// [通过] 检查权限publicintcheckSelfPermission(Stringpermission){// ...}// [通过] 是否应显示解释publicbooleanshouldShowRequestPermissionRationale(Stringpermission){// ...}使用示例:
// 请求相机权限if(checkSelfPermission(Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){// 显示解释UI}requestPermissions(arrayOf(Manifest.permission.CAMERA),REQUEST_CAMERA)}overridefunonRequestPermissionsResult(requestCode:Int,permissions:Array<String>,grantResults:IntArray){if(requestCode==REQUEST_CAMERA){if(grantResults[0]==PackageManager.PERMISSION_GRANTED){// 权限已授予}}}案例2:RecyclerView API设计
设计理念:分离关注点
// RecyclerView.java - 高内聚低耦合的API设计publicclassRecyclerViewextendsViewGroup{// [通过] 核心方法:设置AdapterpublicvoidsetAdapter(Adapteradapter){}// [通过] 核心方法:设置布局管理器publicvoidsetLayoutManager(LayoutManagerlayout){}// [通过] 扩展点:设置装饰器publicvoidaddItemDecoration(ItemDecorationdecor){}// [通过] 扩展点:设置动画publicvoidsetItemAnimator(ItemAnimatoranimator){}// [通过] 抽象类:AdapterpublicstaticabstractclassAdapter<VHextendsViewHolder>{publicabstractVHonCreateViewHolder(ViewGroupparent,intviewType);publicabstractvoidonBindViewHolder(VHholder,intposition);publicabstractintgetItemCount();}// [通过] 抽象类:LayoutManagerpublicstaticabstractclassLayoutManager{publicabstractvoidonLayoutChildren(Recyclerrecycler,Statestate);}}优点:
- 单一职责:Adapter负责数据,LayoutManager负责布局
- 开闭原则:通过继承扩展,无需修改RecyclerView
- 可测试性:各部分可独立测试
案例3:LiveData API设计
设计理念:生命周期感知
// LiveData.java - 生命周期感知的数据容器publicabstractclassLiveData<T>{// [通过] 观察方法:自动管理生命周期publicvoidobserve(@NonNullLifecycleOwnerowner,@NonNullObserver<T>observer){// Activity/Fragment销毁时自动移除Observer}// [通过] 永久观察:手动管理生命周期publicvoidobserveForever(@NonNullObserver<T>observer){// 需要手动removeObserver}// [通过] Protected:子类设置值protectedvoidsetValue(Tvalue){// 主线程设置}protectedvoidpostValue(Tvalue){// 子线程设置}// [通过] Public:获取当前值publicTgetValue(){returnmData;}}使用示例:
classUserViewModel:ViewModel(){privateval_user=MutableLiveData<User>()valuser:LiveData<User>=_user// 对外暴露不可变LiveDatafunloadUser(){_user.value=repository.getUser()}}classUserActivity:AppCompatActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)viewModel.user.observe(this){user->// Activity销毁时自动取消观察,无内存泄漏updateUI(user)}}}API Review流程
Google的API Review
- 设计阶段:编写API设计文档
- 内部Review:团队内部审查
- API Council Review:Android API委员会审查
- 实现阶段:实现并测试
- 文档编写:编写API文档和示例
- 发布前Review:最终审查
API Review检查项
✓ 是否符合最小化原则? ✓ 命名是否清晰? ✓ 是否与现有API一致? ✓ 是否考虑了向后兼容? ✓ 是否易于测试? ✓ 文档是否完善? ✓ 是否有示例代码? ✓ 是否考虑了性能影响? ✓ 是否考虑了安全性?常见错误
错误1:暴露内部实现
// [未通过] 暴露缓存实现classImageLoader{valcache:LruCache<String,Bitmap>get()=mCache// 暴露实现细节}// [通过] 隐藏实现classImageLoader{funclearCache(){mCache.evictAll()}// 只暴露行为}错误2:过度设计
// [未通过] 过度抽象interfaceImageLoadStrategy{}interfaceCacheStrategy{}interfaceDecodeStrategy{}interfaceTransformStrategy{}classImageLoader(valloadStrategy:ImageLoadStrategy,valcacheStrategy:CacheStrategy,valdecodeStrategy:DecodeStrategy,valtransformStrategy:TransformStrategy)// 过于复杂// [通过] 简单直接classImageLoader{funload(url:String):Bitmap{}}错误3:忽略边界情况
// [未通过] 没有参数校验funsetAlpha(alpha:Int){this.alpha=alpha// 如果alpha<0或>255会怎样?}// [通过] 参数校验funsetAlpha(alpha:Int){require(alphain0..255){"Alpha must be between 0 and 255"}this.alpha=alpha}总结
SDK设计六大原则
- 最小化:只暴露必要API
- 稳定性:Public API永久兼容
- 语义化:命名清晰明确
- 一致性:相似功能相似模式
- 兼容性:向后兼容
- 可测试性:依赖接口
API层级
- Public API:所有应用可用,永久兼容
- System API:系统应用专用
- Hidden API:框架内部,随时可变
设计建议
- 设计前充分思考
- 发布后谨慎修改
- 文档和示例完善
- 考虑向后兼容
- 简单胜于复杂
关键要点:API设计是一门艺术,好的API简洁、稳定、易用,一旦发布就很难修改