0赞
赞赏
更多好文
最近和团队一起重构一个老项目,发现代码里堆满了 findViewById 和 new,连我这个写了5年Android的老手都看不下去了。设计模式不是教科书里的花架子,而是能救命的“代码急救包”。今天不扯理论,就聊我踩过的坑和真·实战用法——保证没有AI那种“首先、其次”的机械感。
1. 单例模式:别让 Application 成为内存泄漏的温床
为什么用?
管理全局状态(比如用户登录信息、配置)时,单例比到处传 Context 省心。但Android里用错,分分钟内存泄漏。
我的血泪教训
之前写了个 UserManager 单例,直接持有 Activity 引用:
class UserManager private constructor() {
private lateinit var context: Activity // 错!
companion object {
val instance = UserManager()
}
}
结果Activity销毁后,单例还挂着,内存泄漏。现在我直接用 枚举单例 + Application Context:
object UserManager {
private var appContext: Context? = null
fun init(context: Context) {
appContext = context.applicationContext
}
fun getCurrentUser(): User? = ... // 用appContext,安全!
}
关键点:永远别在单例里存Activity/Fragment的引用,用 getApplicationContext()。
2. 观察者模式:LiveData才是Android的“真·观察者”
为什么用?
UI和数据状态联动(比如列表刷新、登录状态更新),用观察者比手动注册/注销简单10倍。
我改写的真实案例
以前用 BroadcastReceiver 管登录状态,注册/注销到处写:
// 旧代码:到处注册,容易漏
registerReceiver(...)
现在直接用 LiveData + ViewModel,一招搞定:
class LoginViewModel : ViewModel() {
private val _isLoggedIn = MutableLiveData<Boolean>()
val isLoggedIn: LiveData<Boolean> get() = _isLoggedIn
fun login() {
// ...登录逻辑
_isLoggedIn.value = true
}
}
在Fragment里:
viewModel.isLoggedIn.observe(this) { isLogged ->
if (isLogged) showMainScreen()
}
为什么爽?
生命周期自动管理!Activity销毁时自动取消订阅,再也不用担心内存泄漏。RxJava也是观察者模式的变种,但LiveData更轻量,Android原生支持。
3. 工厂模式:别让 Fragment 创建逻辑烂在Activity里
为什么用?
当需要根据条件创建不同Fragment时(比如不同用户角色),工厂模式能解耦Activity。
我重构的代码
之前写:
// Activity里硬编码
val fragment = if (user.isAdmin) AdminFragment() else UserFragment()
现在用工厂:
class FragmentFactory {
fun createFragment(user: User): Fragment {
return when {
user.isAdmin -> AdminFragment()
user.isGuest -> GuestFragment()
else -> UserFragment()
}
}
}
在Activity里:
val fragment = FragmentFactory().createFragment(currentUser)
supportFragmentManager.beginTransaction().replace(R.id.container, fragment).commit()
好处:
- Activity只负责“要什么”,不关心“怎么造”
- 新增角色只需改工厂,不碰Activity
4. 策略模式:RecyclerView的LayoutManager,你真的懂吗?
为什么用?
当有多种算法(比如列表布局:线性/网格/瀑布流),策略模式让切换更简单。
真实场景
以前写RecyclerView,直接在Activity里写布局逻辑:
// 旧代码:硬编码
val layoutManager = if (isGrid) GridLayoutManager(...) else LinearLayoutManager(...)
现在用策略:
interface LayoutStrategy {
fun createLayoutManager(context: Context): RecyclerView.LayoutManager
}
class GridStrategy : LayoutStrategy {
override fun createLayoutManager(context: Context) =
GridLayoutManager(context, 2)
}
class LinearStrategy : LayoutStrategy {
override fun createLayoutManager(context: Context) =
LinearLayoutManager(context)
}
在Adapter里:
fun setLayoutStrategy(strategy: LayoutStrategy) {
recyclerView.layoutManager = strategy.createLayoutManager(context)
}
为什么值?
- 切换布局只需
adapter.setLayoutStrategy(GridStrategy()) - 未来新增瀑布流,只需加新策略类,不改Adapter
5. 适配器模式:RecyclerView.Adapter的“真谛”
为什么用?
把数据源(List)适配到UI组件(RecyclerView),这是Android最基础的模式,但很多人用得像屎。
我教新人的要点
别用BaseAdapter! 用 RecyclerView.Adapter + ViewHolder,这才是适配器模式的精髓:
class ProductAdapter(private val items: List<Product>) :
RecyclerView.Adapter<ProductAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_product, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position]) // 这里才是适配的核心
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(product: Product) {
itemView.tvName.text = product.name
itemView.ivImage.load(product.image)
}
}
}
关键点:
ViewHolder避免重复findViewByIdonBindViewHolder只处理当前item,性能碾压旧版- 适配器只关心“如何显示数据”,不关心“数据从哪来”
最后说句大实话
设计模式不是为了炫技。我见过太多同学为了用“工厂模式”硬造一个工厂,结果代码比之前更难读。记住:
- 用单例前先问:“真的需要全局唯一吗?”
- 用观察者前先看:“生命周期管理是不是要自己搞?”
- 用适配器前先想:“RecyclerView的ViewHolder模式是不是已经解决了?”
Android的代码,80%的问题都是因为“太懒”——懒得拆分逻辑,懒得写个工厂。设计模式不是答案,而是帮你把“懒”变成“聪明”的工具。
写完这篇,我回头看了眼昨天重构的代码:单例用对了,观察者自动管理生命周期,适配器性能飙升。这才是设计模式的真味儿——它让你写代码时,心里踏实。
