JetPack——Hilt
2026/8/29 18:11:37 网站建设 项目流程

手动依赖注入

LoginRetrofitService

public class LoginRetrofitService { }

UserRemoteDataSource

public class UserRemoteDataSource { private final LoginRetrofitService loginService; public UserRemoteDataSource(LoginRetrofitService loginService) { this.loginService = loginService; } }

UserLocalDataSource

public class UserLocalDataSource { }

UserRepository

public class UserRepository { private final UserLocalDataSource localDataSource; private final UserRemoteDataSource remoteDataSource; public UserRepository(UserLocalDataSource localDataSource, UserRemoteDataSource remoteDataSource) { this.localDataSource = localDataSource; this.remoteDataSource = remoteDataSource; } }

LoginViewModelFactory

public class LoginViewModelFactory implements ViewModelProvider.Factory { private final UserRepository userRepository; public LoginViewModelFactory(UserRepository userRepository) { this.userRepository = userRepository; } @NonNull @Override @SuppressWarnings("unchecked") public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { return (T) new LoginViewModel(userRepository); } }

LoginViewModel

public class LoginViewModel extends ViewModel { private final UserRepository userRepository; public LoginViewModel(UserRepository userRepository) { this.userRepository = userRepository; } }

ManualLoginActivity

想要获取LoginViewModel,需要根据依赖关系依次创建LoginRetrofitService、UserLocalDataSource、UserRemoteDataSource、UserRepository、LoginViewModelFactory

public class ManualLoginActivity extends AppCompatActivity { private static final String TAG = ManualLoginActivity.class.getSimpleName(); private LoginViewModel loginViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LoginRetrofitService loginService = new LoginRetrofitService(); UserLocalDataSource localDataSource = new UserLocalDataSource(); UserRemoteDataSource remoteDataSource = new UserRemoteDataSource(loginService); UserRepository userRepository = new UserRepository(localDataSource, remoteDataSource); LoginViewModelFactory factory = new LoginViewModelFactory(userRepository); loginViewModel = new ViewModelProvider(this, factory).get(LoginViewModel.class); String msg = "【手动DI】依赖注入成功,ViewModel = " + loginViewModel; Log.d(TAG, msg); showText(msg); } private void showText(String text) { TextView tv = new TextView(this); tv.setText(text); tv.setGravity(Gravity.CENTER); tv.setTextColor(Color.BLACK); tv.setPadding(32, 200, 32, 32); setContentView(tv); } }

Hilt

实现依赖项注入可为您带来以下优势:

  • 重用代码
  • 易于重构
  • 易于测试

Hilt 是 Android 的依赖项注入库,可减少在项目中执行手动依赖项注入的样板代码

依赖

libs.version.toml

[versions] ...... ksp = "2.0.20-1.0.24" hilt = "2.57.1" [libraries] ...... hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } [plugins] ...... ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }

build.gradle(根目录)

plugins { ...... alias(libs.plugins.ksp) apply false alias(libs.plugins.hilt) apply false }

build.gradle(项目目录)

android { ...... compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = '17' } } plugins { ...... alias(libs.plugins.ksp) alias(libs.plugins.hilt) } dependencies { ...... implementation libs.hilt.android ksp libs.hilt.compiler }

Hilt 依赖注入

MyApplication

@HiltAndroidApp public class MyApplication extends Application { private static MyApplication instance; @Override public void onCreate() { super.onCreate(); instance = this; } public static Context getContext() { return instance; } }

LoginRetrofitService

public class LoginRetrofitService { @Inject public LoginRetrofitService() { } }

UserRemoteDataSource

public class UserRemoteDataSource { private final LoginRetrofitService loginService; @Inject public UserRemoteDataSource(LoginRetrofitService loginService) { this.loginService = loginService; } }

UserLocalDataSource

public class UserLocalDataSource { @Inject public UserLocalDataSource() { } }

UserRepository

@Singleton 全 App 共享一个

@Singleton public class UserRepository { private final UserLocalDataSource localDataSource; private final UserRemoteDataSource remoteDataSource; @Inject public UserRepository(UserLocalDataSource localDataSource, UserRemoteDataSource remoteDataSource) { this.localDataSource = localDataSource; this.remoteDataSource = remoteDataSource; } }

LoginViewModel

@HiltViewModel + 构造函数 @Inject → 依赖自动装配,不再需要手写 Factory。

@HiltViewModel public class LoginViewModel extends ViewModel { private final UserRepository userRepository; @Inject public LoginViewModel(UserRepository userRepository) { this.userRepository = userRepository; } }

HiltLoginActivity

为带有 @AndroidEntryPoint 注解的其他 Android 类提供依赖项,省去new的过程

@AndroidEntryPoint public class HiltLoginActivity extends AppCompatActivity { private static final String TAG = HiltLoginActivity.class.getSimpleName(); private LoginViewModel loginViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 一行搞定:Hilt 已经把 UserRepository 及其下层依赖全部装配好 loginViewModel = new ViewModelProvider(this).get(LoginViewModel.class); String msg = "【Hilt】依赖注入成功,ViewModel = " + loginViewModel; Log.d(TAG, msg); showText(msg); } private void showText(String text) { TextView tv = new TextView(this); tv.setText(text); tv.setGravity(Gravity.CENTER); tv.setTextColor(Color.BLACK); tv.setPadding(32, 200, 32, 32); setContentView(tv); } }

@Module和@InstallIn

  • @Module 注解的类向 Hilt 提供有关如何创建无法通过构造函数注入提供的类型(例如接口或第三方类)的实例
  • @InstallIn 告知 Hilt 每个模块将用在或安装在哪个 Android 类中

@Bind 注入接口

public interface DemoInterface { String demo(); }
public class DemoImpl implements DemoInterface { @Inject public DemoImpl() { } @Override public String demo() { return "DemoImpl"; } }

存在接口和具体实现,创建一个带有 @Binds 注解的抽象函数实现接口的依赖注入

  • 返回值为接口
  • 参数为实现
@Module @InstallIn(SingletonComponent.class) public abstract class DemoModule { @Binds public abstract DemoInterface bind(DemoImpl impl); }
@AndroidEntryPoint public class HiltModuleActivity extends AppCompatActivity { private static final String TAG = HiltModuleActivity.class.getSimpleName(); @Inject DemoInterface mDemo; // 业务用接口 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout root = new LinearLayout(this); root.setOrientation(LinearLayout.VERTICAL); root.setPadding(48, 200, 48, 48); TextView tv = new TextView(this); tv.setGravity(Gravity.CENTER); tv.setTextColor(Color.BLACK); root.addView(tv); setContentView(root); String msg = "当前实现:" + mDemo.demo(); Log.d(TAG, msg); tv.setText(msg); } }

@Provides 注入外部库

@Module @InstallIn(SingletonComponent.class) public class DemoModule { @Provides public Gson provideGson() { return new GsonBuilder().create(); } }
@AndroidEntryPoint public class HiltModuleActivity extends AppCompatActivity { @Inject Gson gson; // @Provides 提供的实例 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText("Gson实例:" + gson.toJson("hello @Provides")); setContentView(tv); } }

@Qualifier和@Retention

  • @Qualifier 为同一类型定义多个绑定
  • @Retention 设置注解声明周期

如下生成@PrettyGson注解,用于Gson实例对象的依赖注入

@Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface PrettyGson { }
@Module @InstallIn(SingletonComponent.class) public class DemoModule { // 默认绑定:压缩输出。 @Provides public Gson provideGson() { return new GsonBuilder().create(); } // 同类型的第二个绑定,靠 @PrettyGson 限定符区分,避免和上面的冲突。 @Provides @PrettyGson public Gson providePrettyGson() { return new GsonBuilder().setPrettyPrinting().create(); } }
@AndroidEntryPoint public class HiltModuleActivity extends AppCompatActivity { @Inject Gson gson; // 默认绑定 @Inject @PrettyGson Gson prettyGson; // 限定符绑定 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 用带字段的对象序列化,才能看出 setPrettyPrinting() 的换行缩进效果; // 序列化单个字符串没有"结构",两种输出会一样。 Map<String, String> data = new HashMap<>(); data.put("name", "Kiro"); data.put("action", "@Provides demo"); String compact = gson.toJson(data); String pretty = prettyGson.toJson(data); TextView tv = new TextView(this); tv.setText("默认Gson: " + compact + "\n\nPrettyGson:\n" + pretty); setContentView(tv); } }

自带的预定义限定符

如下注入ApplicationContext和ActivityContext

@Inject @ApplicationContext Context appContext; @Inject @ActivityContext Context activityContext;

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询