You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BaseActivity与BaseFragment中Toolbar冗余代码优化方案咨询

Great question! Duplicating toolbar logic across BaseActivity and BaseFragment is such a common pain point—having to update the same code in two places is a recipe for bugs and extra work. Let’s walk through two clean, maintainable solutions to consolidate all that toolbar boilerplate into a single spot:

1. Create a Standalone Toolbar Manager Class

The simplest approach is to extract all toolbar-related logic into a dedicated utility class. This class will handle view lookup, title setting, navigation icon setup, and any other toolbar operations you need. All your base components will then delegate to this manager instead of implementing the logic themselves.

Step 1: Build the ToolbarManager

class ToolbarManager(private val context: Context) {
    private var toolbar: Toolbar? = null

    // Initialize the toolbar by finding it in the root view
    fun init(rootView: View) {
        toolbar = rootView.findViewById(R.id.toolbar)
        // Add any universal toolbar setup here (e.g., default text styles)
    }

    // Set toolbar title
    fun setTitle(title: String) {
        toolbar?.title = title
    }

    // Configure navigation icon and click listener
    fun setNavigationIcon(iconRes: Int, onClick: () -> Unit) {
        toolbar?.setNavigationIcon(iconRes)
        toolbar?.setNavigationOnClickListener { onClick() }
    }

    // Inflate menu and handle menu interactions
    fun inflateMenu(menuRes: Int, menuCallback: (Menu) -> Unit) {
        toolbar?.inflateMenu(menuRes)
        toolbar?.menu?.let(menuCallback)
    }

    // Expose the toolbar instance for Activity-specific setup (like setting as ActionBar)
    fun getToolbar(): Toolbar? = toolbar
}

Step 2: Integrate with BaseActivity

abstract class BaseActivity : AppCompatActivity() {
    protected val toolbarManager by lazy { ToolbarManager(this) }

    override fun setContentView(layoutResID: Int) {
        super.setContentView(layoutResID)
        // Initialize toolbar using the root content view
        toolbarManager.init(findViewById(android.R.id.content))
        // Set toolbar as ActionBar (Activity-specific logic)
        toolbarManager.getToolbar()?.let {
            setSupportActionBar(it)
            supportActionBar?.setDisplayHomeAsUpEnabled(false)
        }
    }

    // Convenience method for subclasses to set title
    protected fun setToolbarTitle(title: String) {
        toolbarManager.setTitle(title)
    }
}

Step 3: Integrate with BaseFragment

abstract class BaseFragment : Fragment() {
    protected val toolbarManager by lazy { ToolbarManager(requireContext()) }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // Initialize toolbar using the fragment's root view
        toolbarManager.init(view)
    }

    protected fun setToolbarTitle(title: String) {
        toolbarManager.setTitle(title)
    }
}

Now all your toolbar logic lives in one place—any updates or fixes only need to be made to ToolbarManager, and both your activities and fragments will automatically get the changes.

2. Use Kotlin Delegation (For Cleaner Interface Implementation)

If you prefer a more interface-driven approach, you can define a ToolbarHandler interface and use Kotlin's class delegation to reuse the implementation across your base classes.

Step 1: Define the ToolbarHandler Interface

interface ToolbarHandler {
    fun init(rootView: View)
    fun setTitle(title: String)
    fun setNavigationIcon(iconRes: Int, onClick: () -> Unit)
    fun getToolbar(): Toolbar?
}

Step 2: Implement the Default Handler

class DefaultToolbarHandler(private val context: Context) : ToolbarHandler {
    private var toolbar: Toolbar? = null

    override fun init(rootView: View) {
        toolbar = rootView.findViewById(R.id.toolbar)
    }

    override fun setTitle(title: String) {
        toolbar?.title = title
    }

    override fun setNavigationIcon(iconRes: Int, onClick: () -> Unit) {
        toolbar?.setNavigationIcon(iconRes)
        toolbar?.setNavigationOnClickListener { onClick() }
    }

    override fun getToolbar(): Toolbar? = toolbar
}

Step 3: Delegate in Base Classes

For BaseActivity:

abstract class BaseActivity : AppCompatActivity(), ToolbarHandler {
    private val toolbarHandler by lazy { DefaultToolbarHandler(this) }

    override fun init(rootView: View) = toolbarHandler.init(rootView)
    override fun setTitle(title: String) = toolbarHandler.setTitle(title)
    override fun setNavigationIcon(iconRes: Int, onClick: () -> Unit) = toolbarHandler.setNavigationIcon(iconRes, onClick)
    override fun getToolbar(): Toolbar? = toolbarHandler.getToolbar()

    override fun setContentView(layoutResID: Int) {
        super.setContentView(layoutResID)
        init(findViewById(android.R.id.content))
        getToolbar()?.let {
            setSupportActionBar(it)
            supportActionBar?.setDisplayHomeAsUpEnabled(false)
        }
    }
}

For BaseFragment:

abstract class BaseFragment : Fragment(), ToolbarHandler {
    private val toolbarHandler by lazy { DefaultToolbarHandler(requireContext()) }

    override fun init(rootView: View) = toolbarHandler.init(rootView)
    override fun setTitle(title: String) = toolbarHandler.setTitle(title)
    override fun setNavigationIcon(iconRes: Int, onClick: () -> Unit) = toolbarHandler.setNavigationIcon(iconRes, onClick)
    override fun getToolbar(): Toolbar? = toolbarHandler.getToolbar()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        init(view)
    }
}

This approach keeps your base classes clean and adheres to the interface segregation principle—you can even create different ToolbarHandler implementations if you need specialized behavior for certain screens.

Bonus Tips

  • Make sure all your layouts use the same ID for the toolbar (e.g., R.id.toolbar) so the manager can reliably find it.
  • Add a flag in your base classes (like shouldShowToolbar()) to skip initialization for screens that don't need a toolbar.
  • Keep Activity-specific logic (like setting the toolbar as an ActionBar) confined to BaseActivity—fragments shouldn't modify the ActionBar directly.

内容的提问来源于stack exchange,提问作者Nagesh Jatagond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:53:32