Introducing BlockFramework: A Mobile UI Decoupling Architecture for Android
BlockFramework is an open‑source Android client‑side framework that decouples business logic into reusable Blocks, offering clear separation, tree‑based UI assembly, rich communication patterns, unified development standards, and high‑performance features such as asynchronous view inflation and data binding.
In large‑scale Android applications, multiple teams often work on the same page, which can quickly lead to tightly coupled code and increased maintenance costs. BlockFramework addresses this problem by providing a client‑side business decoupling framework with four key characteristics: a clear decoupling mechanism, high‑performance UI assembly, rich communication mechanisms, and a unified development paradigm.
A Block is the fundamental unit of BlockFramework; complex pages are composed of multiple Blocks that align with the Android View tree, allowing each Block to independently fetch data, render views, and be reused across different scenarios.
Blocks are organized in a tree structure, where each scene corresponds to a Block tree. This hierarchical arrangement mirrors the view hierarchy, simplifies management, reduces the manager’s complexity, and helps maintain a balanced tree for optimal page structure.
Developers assemble Blocks by overriding the assembleSubBlocks method, adding child Blocks to a parent container:
override fun assembleSubBlocks(assembler: BlockAssembler) {
assembler.assemble {
addBlock {
instance = { MainContentBlock(blockContext) }
parentId = R.id.main_content_block_container
}
addBlock {
instance = { BottomInfoBlock(blockContext) }
parentId = R.id.bottom_info_block_container
}
addBlock {
instance = { RightInteractBlock(blockContext) }
parentId = R.id.right_interact_block_container
}
}
}Each Block follows the Jetpack Lifecycle, implementing methods such as onCreate , onStart , onResume , etc., which makes migration from legacy code straightforward:
open class BaseBlock
>(val blockContext: IBlockContext) : AbstractLifecycleBlock() {
open fun onRegister() {}
override fun onCreate() {}
override fun onStart() {}
override fun onResume() {}
override fun onPause() {}
override fun onStop() {}
override fun onDestroy() {}
override fun onUnRegister() {}
}Communication within the framework is handled by a MessageCenter that supports one‑to‑one (SPI‑based interface exposure) and one‑to‑many (observer‑pattern event broadcasting) interactions, while inter‑Block communication uses BlockDepend to inject dependencies and query services up the tree.
BlockFramework also includes high‑performance optimizations. Asynchronous view assembly splits view inflation into background threads, reducing overall UI construction time by about 20%. Asynchronous data binding moves heavy logic off the main thread and posts results back to the UI thread:
override fun bindModel(model: MODEL?) {
if (enableAsyncBind()) {
syncBind(model)
Executor.work().post {
asyncBind(model) {
Executor.main().post { it.invoke() }
}
}
} else {
syncBind(model)
asyncBind(model) { it.invoke() }
}
}Since its open‑source release on GitHub, BlockFramework has been adopted in several ByteDance products such as Xigua Video detail pages, horizontal streams, feed lists, and the core player, delivering measurable performance and efficiency gains. The team continues to evolve the framework and encourages community contributions.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.