DSL(domain specific language),即领域专用语言:专门解决某一特定问题的计算机语言。由于它是以简洁的形式进行表达,整体上直观易懂,使得调用代码和读代码的成本都得以降低,即使是不懂编程语言的一般人都可以进行使用。比如大家比较熟悉的SQL语句和正则表达式。 所谓领域也就是限定语言是适用于一定范围的。可以看做是封装了一套东西, 用于特定的功能, 优势是复用性和可读性的增强。
(1.)DSL的特点- 用于专门领域,不能用于其他领域。
- 有更高级的抽象,不涉及类似数据结构的细节。
- 表现力有限,其只能描述该领域的模型。
通用编程语言(如 Java、Kotlin、Python等),往往提供了全面的库来帮助开发者开发完整的应用程序,而 DSL 只专注于某个领域,比如 SQL 仅支持数据库的相关处理,而正则表达式只用来检索和替换文本,无法用 SQL 或者正则表达式来开发一个完整的应用。
2.外部 DSL 和内部 DSLDSL分为外部DSL和内部 DSL
(1.)外部DSL在主程序设计语言之外,用一种单独的语言表示领域专有语言。可以是定制语法,或者遵循另外一种语法,如 XML、JSON。(从零开始构建的语言,需要实现语法解析器等)。
(2.)内部 DSL通常是基于通用编程语言实现,具有特定的风格,如Android 的主流编译工具 Gradle。(从一种宿主语言构建而来)。
二.Koltin封装DSL风格d窗许多现代语言为创建内部 DSL 提供了一些先进的方法, Kotlin 也不例外。下面就通过kotlin的高阶函数和扩展方法, 封装一个简单的DSL风格的d窗:
1.编写d窗布局文件2.封装确认d窗
class ConfirmDialogFragment : DialogFragment() { private var titleTv: TextView? = null private var messageTv: TextView? = null private var leftButton: TextView? = null private var rightButton: TextView? = null //左边按钮点击回调 private var leftClicks: (() -> Unit)? = null //右边边按钮点击回调 private var rightClicks: (() -> Unit)? = null //是否可以消失 var cancelOutside: Boolean = true //d窗标题 var title: String? = null //d窗内容 var message: String? = null //左边按钮文字 var leftValue: String? = null //左边按钮点击是否关闭d窗 var leftButtonDismissAfterClick = true //右边按钮文字 var rightValue: String? = null //右边按钮点击是否关闭d窗 var rightButtonDismissAfterClick = true companion object { fun newInstance(): ConfirmDialogFragment { return ConfirmDialogFragment() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Material_Light_Dialog) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.dialog_custom, container).apply { titleTv = findViewById(R.id.title_tv) messageTv = findViewById(R.id.message_tv) leftButton = findViewById(R.id.left_button) rightButton = findViewById(R.id.right_button) } init() return view } private fun init() { dialog?.setCancelable(cancelOutside) title?.let { text -> titleTv?.visibility = View.VISIBLE titleTv?.text = text } message?.let { text -> messageTv?.visibility = View.VISIBLE messageTv?.text = text } leftClicks?.let { onClick -> leftButton?.text = leftValue leftButton?.visibility = View.VISIBLE leftButton?.setonClickListener { onClick() if (leftButtonDismissAfterClick) { dismissAllowingStateLoss() } } } rightClicks?.let { onClick -> rightButton?.text = rightValue rightButton?.setonClickListener { onClick() if (rightButtonDismissAfterClick) { dismissAllowingStateLoss() } } } } fun leftClicks(key: String = "取消", dismissAfterClick: Boolean = true, callback: () -> Unit) { leftValue = key leftButtonDismissAfterClick = dismissAfterClick leftClicks = callback } fun rightClicks(key: String = "确定", dismissAfterClick: Boolean = true, callback: () -> Unit) { rightValue = key rightButtonDismissAfterClick = dismissAfterClick rightClicks = callback } }3.给AppCompatActivity添加扩展方法
inline fun AppCompatActivity.showDialog(settings: /confirm/iDialogFragment.() -> Unit) : ConfirmDialogFragment { val dialog = /confirm/iDialogFragment.newInstance() dialog.apply(settings) val ft = this.supportFragmentManager.beginTransaction() val prev = this.supportFragmentManager.findFragmentByTag("/confirm/i_dialog") if (prev != null) { ft.remove(prev) } ft.addToBackStack(null) dialog.show(ft, "dialog") return dialog }4.在Activity中通过扩展方法使用DSL风格的d窗
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById5.效果展示(R.id.button_dialog).setonClickListener { showDialog { cancelOutside = true //可以取消 title = "我是d窗的标题" message = "我是d窗里面的内容,我是d窗里面的内容,我是d窗里面的内容,我是d窗里面的内容" leftClicks("取消", true) { toast("左边按钮被点击!") } rightClicks("确定", true) { toast("右边按钮被点击!") } } } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)