Kotlin-为Android项目生成Doc文档
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin-为Android项目生成Doc文档相关的知识,希望对你有一定的参考价值。
参考技术A 类似于Java中的JavaDoc工具,Kotlin的官方也发布了一款生成Kotlin文档工具。 dokka
不过它确实不是很好用。
坑1:截止在我写这边文档时候,该工具的最新版本为0.10.0。在这个版本中,作者将两个插件进行了合并(一个适用于Android项目的插件,一个则用于通用Kotlin项目插件)。导致了出现了一个大坑。详情请见这里 [ https://github.com/Kotlin/dokka/issues/213(https://github.com/Kotlin/dokka/issues/213) 。
经过一早上的踩坑折腾,发现在回退到上一个版本,0.9.17版本没出现类似问题。
然后同步项目之后,该插件会为项目添加一个dokka的task。
坑3:GC overhead limit exceeded。解决了上一个问题,又出现了一个oom的问题。这个问题也算是常见,不过我这个总共不超过十个class文件,居然翻车了。。好吧,果断在根目录下gradle.properties文件中配置扩大一下堆栈大小
在成功构建完所有的构建变体任务后,终于看到了在输出目录 outputDirectory 中的出现了javadoc文件夹。
打开index页面,你就可以看到dokka为项目生成的文档了。
在以上声明中,dokka就不会为androidx作为包名前缀的类生成文档。问题似乎得到了解决。但是这是一种舍近求远的方法。就好比你去一家店想买一杯奶茶,老板居然问你不想喝什么口味的。。因为在后续的开发中你可能还会引入新的包,dokka可能会为其他R文件生成以其他报名开头的文档。那么此时你必须继续添加packageOptions配置。。
Android Jectpack-ViewBinding 实践(kotlin实现)
文章目录
I. 文档
id kotlin-android-extensions
插件过时了,官方推荐 ViewBinding
。
以下为官方文档中的一段话:
与 findViewById 的区别
与使用 findViewById 相比,视图绑定具有一些很显著的优点:
Null 安全:由于视图绑定会创建对视图的直接引用,因此不存在因视图 ID 无效而引发 Null 指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。
类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。
这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。
II. 配置及简要说明
[application Module]/build.gradle
android
//viewBinding
// enabled = true
// //本写法已在 stuido4.0过时 换成如下
buildFeatures
viewBinding = true
-
插件会将 ab_cd_ef.xml 生成一个 AbCdEfBinding 的类(即去掉下划线,并驼峰式)。
-
会对布局xml中的view id 生成 驼峰式类名。
源码位置:build/generated/data_binding_base_class_source_out/debug/out/[package name]/databinding/PrintDialogPrinterConnectBinding.java
-
对
<include id="@+id/includeLayout"../>
,要想访问include layout 内的子view,子view id为 “testTv”,只需:XxxBinding.IncludeLayout.testTv。
-
若不想生成 Binding 文件。在根视图中使用
tools:viewBindingIgnore="true"
III. 源码
public interface ViewBinding
/**
* Returns the outermost @link View in the associated layout file. If this binding is for a
* @code <merge> layout, this will return the first view inside of the merge tag.
*/
@NonNull
View getRoot();
所有生成的 Binding类都实现了该接口。
IV. 一个生成类的源码
public final class PrintDialogPrinterConnectBinding implements ViewBinding
@NonNull
public ConstraintLayout getRoot()
return rootView;
@NonNull
public static PrintDialogPrinterConnectBinding inflate(@NonNull LayoutInflater inflater
return inflate(inflater, null, false);
@NonNull
public static PrintDialogPrinterConnectBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent)
View root = inflater.inflate(R.layout.print_dialog_printer_connect, parent, false);
if (attachToParent)
parent.addView(root);
return bind(root);
@NonNull
public static PrintDialogPrinterConnectBinding bind(@NonNull View rootView)
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
int id;
missingId:
id = R.id.dialog_printer_connect_close;
ImageView dialogPrinterConnectClose = rootView.findViewById(id);
if (dialogPrinterConnectClose == null)
break missingId;
if ...
- getRoot() 获取根视图 view
- inflate(@NonNull LayoutInflater inflatere) ==> inflate(inflate, null, false)
- inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, boolean attachToParent) ==> bind(root)
- bind(@NonNull View rootView)
外部使用时,通常用 inflate() 的两个函数。
最终都会调用 bind()。
所以可以 不使用Binding类的 inflate(),而通过其它方式 inflate 出 rootView, 再调用XxxBinding.bind(rootView) 。
V. 使用方法
通过 XxxBinding.getRoot() ,获取到根视图,然后 被 setContentView(root)、被Fragment#onCreateView() 用作返回值…
VI. 封装
基于ViewBind使用反射方式;
import android.app.Dialog
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
/**
* AppCompatActivity#onCreate()使用
*/
inline fun <reified VB: ViewBinding> AppCompatActivity.inflate(): VB
return inflateBinding<VB>(layoutInflater).apply
setContentView(this.root)
/**
* Dialog#onCreate() 使用
*/
inline fun <reified VB: ViewBinding> Dialog.inflate(): VB
return inflateBinding<VB>(layoutInflater).apply
setContentView(this.root)
/**
* 继承自 ViewGroup 使用
*/
inline fun <reified VB: ViewBinding> ViewGroup.inflate(viewGroup: ViewGroup, attachToRoot: Boolean = true): VB
return inflateBinding(LayoutInflater.from(context), viewGroup, attachToRoot)
/**
* Recycler.Adapter#onCreateViewHolder() 使用
*/
inline fun <reified VB: ViewBinding> inflate(parent: ViewGroup): VB
return inflateBinding(LayoutInflater.from(parent.context), parent, false)
/**
* 这是一个基础方法。所有创建ViewBinding对象的地方都可以直接调用。
* 反射调用 ViewBinding.inflate(layoutInflater, viewGroup, attachToRoot) 。
* 对于 Fragment、DialogFragment 都直接使用本方法。
* 调用时,viewGroup可以不传,默认为null。
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified VB: ViewBinding> inflateBinding(layoutInflater: LayoutInflater, viewGroup: ViewGroup? = null, attachToRoot: Boolean = false): VB
return VB::class.java.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
.invoke(null, layoutInflater, viewGroup, attachToRoot) as VB
VI.i. 一个DialogFragment例子
class TestDialogFragment : DialogFragment()
private lateinit var mViewBind: DialogFragmentTestBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View
mViewBind = inflateBinding(inflater)
//mViewBind = inflateBinding(inflater, container)
return mViewBind.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
mViewBind.tvTest.setOnClickListener
Toast.makeText(requireContext(), "test msg", Toast.LENGTH_SHORT).show()
//activity 中启动
TestDialogFragment().show(suuportFragmentManager, "tag-test")
//fragment 中启动
TestDialogFragment().show(childFragmentManager, "tag-test")
VI.ii. 强制Fragment子类实例化ViewBinding对象
abstract class BaseExtendFragment: Fragment()
private var mBinding: ViewBinding? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
mBinding = (getViewBind(inflater, container, savedInstanceState) as ViewBinding)
return mBinding?.root
abstract fun <VB: ViewBinding> getViewBind(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): VB
override fun onDestroyView()
super.onDestroyView()
mBinding = null
官方文档中示例是要在 onDestroyView() 中 置空 ViewBinding 对象的。
这样抽象,还是需要每个子Fragment , 声明自己的 XxxViewBinding 对象。
/**
* desc:
* author: stone
* email: aa86799@163.com
* time: 3/10/21 15:59
*/
class MeFragment : BaseExtendFragment()
private lateinit var mViewBind: FragmentMeBinding
@Suppress("UNCHECKED_CAST")
override fun <VB : ViewBinding> getViewBind(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): VB
mViewBind = inflateBinding(inflater, container)
return mViewBind as VB
尝试过 在 BaseExtendFragment<T: ViewBinding> 这样声明。是会精简一些重复代码,然而在多重Fragment抽象与继承,加 permisstion-diapster 框架时,无法通过编译。
开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系
以上是关于Kotlin-为Android项目生成Doc文档的主要内容,如果未能解决你的问题,请参考以下文章
idea生成java Doc文档和cmd生成java Doc文档
Android Studio 生成doc文档错误: 程序包android.content不存在?
无法让 dokka 在 gradle/android 项目上生成 kotlin 文档