class DemoHolder(itemView: View) : RecyclerView.ViewHolder(itemView), IBlockJoin {
private lateinit var rootBlock: DemoCardRootBlock
private val holderDepend: IBlockDepend = object : IHolderBlockDepend {
override fun enableAsyncBind(): Boolean {
return true
}
}
fun initCardBlock() {
rootBlock = DemoCardRootBlock(itemView, blockContext).apply {
// 注册depend
registerDepend(holderDepend)
}
initRootBlock(itemView.context, rootBlock)
}
}
class MainContentBlock(blockContext: IBlockContext) :
AsyncUIBlock<DemoCardData, DemoModel>(blockContext){
// 获取外部depend
private val holderDepend by findDepend<IHolderBlockDepend>()
override fun layoutResource(): Int {
return R.layout.demo_main_content_block_layout
}
override fun enableAsyncBind(): Boolean {
return holderDepend.enableAsyncBind()
}
}
## Block内部通信
1. **query-serviece**机制:一对一通信机制,各Block可以提供对应的service接口,供其他Block调用
```kotlin
// 定义功能接口
interface IMainContentBlockService {
fun changeMainContent(content: String)
}
// 实现service接口
class MainContentBlock(blockContext: IBlockContext) :
AsyncUIBlock<DemoCardData, DemoModel>(blockContext),
IMainContentBlockService
{
override fun changeMainContent(content: String) {
findViewById<TextView>(R.id.content)?.text = content
}
// 定义Service
override fun defineBlockService(): Class<*>? {
return IMainContentBlockService::class.java
}
}
class RightInfoBlock(blockContext: IBlockContext): AsyncUIBlock<DemoCardData, DemoModel>(blockContext) {
// 获取mainContentBlock的service
private val mainContentBlock: IMainContentBlockService? by blockService()
private fun initView() {
val diggView = findViewById<View>(R.id.digg_container)
diggView?.setOnClickListener {
mainContentBlock?.changeMainContent("Digg Click")
}
}
}
subscribe-event机制:一对多机制,Block可以发送event,监听该event的其他Block均能接收到event并处理
```kotlin
// 定义Event
class AvatarClickEvent(): Event()
class BottomInfoBlock(blockContext: IBlockContext): AsyncUIBlock<DemoCardData, DemoModel>(blockContext) {
private fun initView() {
val avatar = findViewById<View>(R.id.avatar)
avatar?.setOnClickListener {
// 发送Event
notifyEvent(AvatarClickEvent())
}
}
}
class RightInteractBlock(blockContext: IBlockContext): AsyncUIBlock<DemoCardData, DemoModel>(blockContext) {
override fun onRegister() {
// 订阅Event
subscribe(this, AvatarClickEvent::class.java)
}
// 监听Event
override fun onEvent(event: Event): Boolean {
when (event) {
is AvatarClickEvent -> {
onAvatarClick()
}
}
return super.onEvent(event)
}
private val holderDepend by findDepend<IHolderBlockDepend>()
// 表示Block支持异步Bind的状态,支持动态变化
override fun enableAsyncBind(): Boolean {
return holderDepend.enableAsyncBind()
}
// 同步Bind,执行在主线程
override fun syncBind(model: DemoModel?) {
setPageState()
}
// 异步Bind,根据[enableAsyncBind]的返回值决定是否执行在子线程
override fun asyncBind(model: DemoModel?, syncInvoke: SyncInvoke) {
queryPageInfo()
// 切换会主线程,用于执行UI逻辑
syncInvoke {
showPageLoading()
}
}
}
## License
```text
Copyright (C) 2024 Bytedance Ltd. and/or its affiliates
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
BlockFramework
项目简介
在大型 APP 的开发进程中,多个业务方向或团队共同开发同一页面的情形屡见不鲜,若缺乏良好的架构支撑,各业务间的逻辑极易相互耦合,进而致使架构迅速恶化,这无疑会增加业务开发与维护的成本。BlockFramework 作为一套客户端业务解耦框架,具备业务分层、组装以及协同能力,业务方基于此框架能够轻松实现业务解耦,独立开展逻辑迭代,进而提升架构的稳定性,降低维护成本,并提高业务迭代的效率。BlockFramework主要有4大特性:
正在使用 BlockFramework 的应用
快速接入
添加仓库源:
在依赖中添加:
在具体业务场景接入BlockFramework搭建一个页面,只需要简单4步:
在主Activity/Fragment/Holder在实现
IBlockJoin接口,实例化属性IBlockContext和IBlockScene根据不同的逻辑业务创建对应的业务Block,可根据是否为UI场景分别继承自
UIBlock或BaseBlockUIBlock需实现layoutResource()返回Block对应的布局XML ```kotlin class BottomInfoBlock(blockContext: IBlockContext): UIBlock<DemoCardData, DemoModel>(blockContext) {override fun layoutResource(): Int {
}
}
初始化rootBlock,即可生成一个完整页面
生命周期同步
Block的默认生命周期与Android的Lifecycle设计一致,因此可以直接监听对应页面的生命周期分发到各Block
Block通信机制
Block提供了丰富的通信机制,用于实现不同Block之间、Block与非Block场景之间的逻辑通信
Block内外通信
Block内部需要调用非Block场景的外部逻辑时,可以通过在rootBlock中注册
blockDepend的方式实现内外通信IBlockDependregisterDepend,注册dependfindDepend()获得到depend能力 ```kotlin interface IHolderBlockDepend : IBlockDepend { fun enableAsyncBind(): Boolean }class DemoHolder(itemView: View) : RecyclerView.ViewHolder(itemView), IBlockJoin {
}
class MainContentBlock(blockContext: IBlockContext) : AsyncUIBlock<DemoCardData, DemoModel>(blockContext){
}
class BottomInfoBlock(blockContext: IBlockContext): AsyncUIBlock<DemoCardData, DemoModel>(blockContext) {
}
class RightInteractBlock(blockContext: IBlockContext): AsyncUIBlock<DemoCardData, DemoModel>(blockContext) {
}
``` ```kotlin override fun generateSubBlocks(generator: BlockGenerator) { generator.generate { addBlock { instance = { BottomInfoBlock(blockContext) } parentId = R.id.bottom_info_block_container replaceParent = true } } } ``` 3. 异步绑定数据 当继承自`AsyncBaseBlock`/`AsyncUIBlock`时,可以获得异步绑定数据能力,支持开发者将耗时逻辑放到子线程执行,并提供了切换回主线程的回调,让开发者更方便的执行耗时逻辑。 ```kotlin class MainContentBlock(blockContext: IBlockContext) : AsyncUIBlock(blockContext) {减少布局层级 在addBlock时,通过设置
replaceParent = true属性,能够在组装View时,将子Block的View直接替换到父Block中的占位View上,减少布局层级。```xml
…
<LinearLayout
…
}