在MVP模式下如何将上下文传递给仓库?
嘿,这个问题问到点子上了——Android里不管是操作SharedPreferences、本地数据库还是文件,都绕不开Context,在MVP架构里怎么优雅又安全地把它传到仓库层,我给你分享几个实用的思路:
1. 沿着MVP调用链手动传递(适合小型项目)
按照你目前的代码结构,Activity已经把自身的Context传给了Presenter,其实可以顺着这条链往下传:从Activity到Model,再由Model把Context传给仓库。不过这里有个关键细节:一定要传递ApplicationContext,而不是Activity的实例,不然很容易因为仓库持有Activity的引用导致内存泄漏。
举个代码例子:
Activity层
// 创建Presenter时,把ApplicationContext传给Model MainPresenter mainPresenter = new MainPresenter(this, new MainModel(getApplicationContext()));
Model层
public class MainModel { private UserRepository userRepository; // Model接收ApplicationContext,再传给仓库 public MainModel(Context appContext) { userRepository = new UserRepository(appContext); } // 业务方法中调用仓库完成数据操作 public void saveUserInfo(String username) { userRepository.saveUsernameToPrefs(username); } }
仓库层
public class UserRepository { private Context appContext; public UserRepository(Context appContext) { this.appContext = appContext; } public void saveUsernameToPrefs(String username) { SharedPreferences prefs = appContext.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE); prefs.edit().putString("username", username).apply(); } }
2. 用依赖注入实现解耦(中大型项目首选)
如果你的项目规模较大,手动传递Context会让代码变得繁琐且耦合度高,这时候用依赖注入框架(比如Hilt、Dagger)会更优雅。这些框架可以帮你自动管理ApplicationContext的传递,不需要手动在各个层之间传参。
比如用Hilt的例子:
仓库层
public class UserRepository { private Context appContext; // 通过Hilt注入ApplicationContext @Inject public UserRepository(@ApplicationContext Context appContext) { this.appContext = appContext; } public void saveUsernameToPrefs(String username) { SharedPreferences prefs = appContext.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE); prefs.edit().putString("username", username).apply(); } }
Model层
public class MainModel { private UserRepository userRepository; // 注入仓库实例,不用手动传Context @Inject public MainModel(UserRepository userRepository) { this.userRepository = userRepository; } // 业务方法调用仓库 public void saveUserInfo(String username) { userRepository.saveUsernameToPrefs(username); } }
Activity层
// Hilt会自动注入Presenter和Model,不用手动传递Context @AndroidEntryPoint public class MainActivity extends AppCompatActivity { @Inject MainPresenter mainPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 直接使用Presenter即可 mainPresenter.saveUser("Taha"); } }
3. 通过自定义Application获取全局Context(简单但要谨慎使用)
如果你的仓库是全局通用的,也可以通过自定义Application类来提供全局的ApplicationContext,这样仓库可以直接获取,不需要层层传递。
自定义Application类
public class MyApp extends Application { private static Context appContext; @Override public void onCreate() { super.onCreate(); appContext = getApplicationContext(); } public static Context getAppContext() { return appContext; } }
记得在AndroidManifest.xml里指定这个Application:
<application android:name=".MyApp" ...> </application>
仓库层直接使用
public class UserRepository { public void saveUsernameToPrefs(String username) { Context appContext = MyApp.getAppContext(); SharedPreferences prefs = appContext.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE); prefs.edit().putString("username", username).apply(); } }
这个方法简单快捷,但要注意不要滥用静态Context——不过这里用的是ApplicationContext,不会持有Activity引用,所以是安全的。
总结一下:如果是小型项目,手动传递ApplicationContext足够用;中大型项目优先考虑依赖注入,能大幅降低耦合度;自定义Application的方式适合全局通用的仓库场景。不管用哪种方式,核心原则都是避免持有Activity的Context,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Taha Kirmani

