or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assisted-injection.mdcomponent-framework.mdindex.mdmodule-system.mdmultibindings.mdutility-types.md

utility-types.mddocs/

0

# Utility Types

1

2

Dagger provides several utility types and interfaces that enhance the dependency injection experience, offering lazy evaluation, members injection, and other advanced features.

3

4

## Capabilities

5

6

### Lazy<T> Interface

7

8

Provides a handle to a lazily-computed value that is computed on the first call to get() and remembered for subsequent calls. Each Lazy<T> instance works independently.

9

10

```java { .api }

11

/**

12

* Handle to lazily-computed value - computes on first get(), remembers result

13

*/

14

interface Lazy<T> {

15

/**

16

* Returns the underlying value, computing it if necessary

17

* @return the lazily-computed value

18

*/

19

T get();

20

}

21

```

22

23

**Key Features:**

24

- Thread-safe: value computed at most once even with concurrent access

25

- Each Lazy<T> instance is independent (not singleton behavior)

26

- Different from @Singleton which shares the same instance across all clients

27

- Useful for expensive-to-create objects that may not be needed

28

29

**Usage Examples:**

30

31

```java

32

public class ExpensiveServiceClient {

33

private final Lazy<ExpensiveService> expensiveService;

34

private final RegularService regularService;

35

36

@Inject

37

public ExpensiveServiceClient(

38

Lazy<ExpensiveService> expensiveService,

39

RegularService regularService

40

) {

41

this.expensiveService = expensiveService;

42

this.regularService = regularService;

43

}

44

45

public void performOperation() {

46

// RegularService created immediately during injection

47

regularService.doSomething();

48

49

// ExpensiveService only created when first accessed

50

if (shouldUseExpensiveFeature()) {

51

expensiveService.get().performExpensiveOperation();

52

}

53

}

54

}

55

56

// Module providing lazy dependency

57

@Module

58

public class ServiceModule {

59

@Provides

60

@Singleton

61

ExpensiveService provideExpensiveService() {

62

// This won't be called until Lazy.get() is invoked

63

return new ExpensiveService();

64

}

65

}

66

```

67

68

### MembersInjector<T> Interface

69

70

Injects dependencies into the fields and methods of existing instances. Used when Dagger cannot create the object directly but needs to inject dependencies into it.

71

72

```java { .api }

73

/**

74

* Injects dependencies into fields and methods of instances

75

*/

76

interface MembersInjector<T> {

77

/**

78

* Injects dependencies into the given instance

79

* @param instance the instance to inject dependencies into

80

*/

81

void injectMembers(T instance);

82

}

83

```

84

85

**Key Features:**

86

- Injects @Inject-annotated fields and methods

87

- Does not perform constructor injection (object must already exist)

88

- Components automatically perform members injection after constructor injection

89

- Useful for framework integration where object creation is external

90

91

**Usage Examples:**

92

93

```java

94

// Class with members injection

95

public class ExternallyCreatedActivity {

96

@Inject UserService userService;

97

@Inject DatabaseService databaseService;

98

99

private String activityData;

100

101

// Constructor not managed by Dagger

102

public ExternallyCreatedActivity(String data) {

103

this.activityData = data;

104

}

105

106

@Inject

107

void init(ConfigService configService) {

108

// Method injection - called after field injection

109

configure(configService.getActivityConfig());

110

}

111

}

112

113

// Component with members injection

114

@Component(modules = ServiceModule.class)

115

public interface ActivityComponent {

116

// Members injection method

117

void inject(ExternallyCreatedActivity activity);

118

119

// Alternative: return injected instance

120

ExternallyCreatedActivity inject(ExternallyCreatedActivity activity);

121

122

// Direct MembersInjector access

123

MembersInjector<ExternallyCreatedActivity> activityInjector();

124

}

125

126

// Usage

127

public class ActivityManager {

128

private final ActivityComponent component;

129

130

@Inject

131

public ActivityManager(ActivityComponent component) {

132

this.component = component;

133

}

134

135

public void setupActivity(String data) {

136

// Create instance externally

137

ExternallyCreatedActivity activity = new ExternallyCreatedActivity(data);

138

139

// Inject dependencies

140

component.inject(activity);

141

142

// Alternative using MembersInjector directly

143

MembersInjector<ExternallyCreatedActivity> injector =

144

component.activityInjector();

145

injector.injectMembers(activity);

146

}

147

}

148

```

149

150

### Provider<T> Interface (JSR-330)

151

152

Standard JSR-330 interface for providing instances of a type. Every dependency in Dagger can be injected as Provider<T> to get new instances on each call.

153

154

```java { .api }

155

/**

156

* JSR-330 interface for providing instances of a type

157

*/

158

interface Provider<T> {

159

/**

160

* Provides an instance of type T

161

* @return an instance of T

162

*/

163

T get();

164

}

165

```

166

167

**Key Features:**

168

- Part of javax.inject standard

169

- get() may return different instances depending on scope

170

- Allows deferred/repeated instance creation

171

- Useful for factory patterns and optional dependencies

172

173

**Usage Examples:**

174

175

```java

176

public class UserController {

177

private final Provider<UserSession> sessionProvider;

178

private final UserService userService;

179

180

@Inject

181

public UserController(

182

Provider<UserSession> sessionProvider,

183

UserService userService

184

) {

185

this.sessionProvider = sessionProvider;

186

this.userService = userService;

187

}

188

189

public void handleRequest() {

190

// Get fresh session for each request

191

UserSession session = sessionProvider.get();

192

userService.processRequest(session);

193

}

194

}

195

196

// Scoped vs Unscoped behavior

197

@Module

198

public class SessionModule {

199

// Unscoped: Provider.get() returns new instance each time

200

@Provides

201

UserSession provideUserSession() {

202

return new UserSession();

203

}

204

205

// Scoped: Provider.get() returns same instance within scope

206

@Provides

207

@Singleton

208

UserPreferences provideUserPreferences() {

209

return new UserPreferences();

210

}

211

}

212

```

213

214

### Optional Injection

215

216

Dagger supports Optional<T> injection for dependencies that may or may not be present:

217

218

```java

219

public class FeatureService {

220

private final CoreService coreService;

221

private final Optional<AnalyticsService> analyticsService;

222

223

@Inject

224

public FeatureService(

225

CoreService coreService,

226

Optional<AnalyticsService> analyticsService

227

) {

228

this.coreService = coreService;

229

this.analyticsService = analyticsService;

230

}

231

232

public void performFeature() {

233

coreService.execute();

234

235

// Analytics may or may not be available

236

analyticsService.ifPresent(analytics ->

237

analytics.trackFeatureUsage("feature_performed"));

238

}

239

}

240

241

// Module declaring optional binding

242

@Module

243

public abstract class OptionalModule {

244

@BindsOptionalOf

245

abstract Optional<AnalyticsService> optionalAnalytics();

246

}

247

```

248

249

### Lazy Provider Combinations

250

251

Dagger supports combinations of lazy evaluation and provider patterns:

252

253

```java

254

public class ComplexDependencyClient {

255

private final Lazy<Provider<ExpensiveService>> lazyProvider;

256

private final Provider<Lazy<AnotherService>> providerLazy;

257

258

@Inject

259

public ComplexDependencyClient(

260

Lazy<Provider<ExpensiveService>> lazyProvider,

261

Provider<Lazy<AnotherService>> providerLazy

262

) {

263

this.lazyProvider = lazyProvider;

264

this.providerLazy = providerLazy;

265

}

266

267

public void complexOperation() {

268

// Lazy<Provider<T>>: Lazy evaluation of provider itself

269

Provider<ExpensiveService> provider = lazyProvider.get();

270

ExpensiveService service1 = provider.get();

271

ExpensiveService service2 = provider.get(); // May be different instance

272

273

// Provider<Lazy<T>>: Provider of lazy instances

274

Lazy<AnotherService> lazy1 = providerLazy.get();

275

Lazy<AnotherService> lazy2 = providerLazy.get(); // Different lazy instances

276

}

277

}

278

```

279

280

### Qualifier Integration

281

282

All utility types work with qualifiers:

283

284

```java

285

@Qualifier

286

@Retention(RetentionPolicy.RUNTIME)

287

public @interface Background {}

288

289

public class QualifiedUtilityExample {

290

@Inject

291

public QualifiedUtilityExample(

292

@Background Lazy<ExecutorService> backgroundExecutor,

293

@Background Provider<WorkerThread> backgroundWorkers,

294

@Background Optional<CacheService> backgroundCache

295

) {

296

// All utilities respect qualifiers

297

}

298

}

299

```

300

301

### Utility Types Best Practices

302

303

**Use Lazy for Expensive Objects:**

304

```java

305

// Good: Lazy evaluation for expensive creation

306

@Inject Lazy<DatabaseConnection> dbConnection;

307

308

// Avoid: Immediate creation if not always needed

309

@Inject DatabaseConnection dbConnection;

310

```

311

312

**Provider for Multiple Instances:**

313

```java

314

// Good: When you need fresh instances

315

@Inject Provider<UserSession> sessionProvider;

316

317

// Avoid: Provider when singleton behavior is desired

318

@Inject Provider<ApplicationConfig> configProvider; // Use direct injection

319

```

320

321

**MembersInjector for Framework Integration:**

322

```java

323

// Good: Framework objects Dagger can't create

324

public void onCreate(Bundle savedInstanceState) {

325

component.inject(this); // Android Activity

326

}

327

328

// Avoid: MembersInjector for regular objects

329

// Use constructor injection instead

330

```

331

332

**Optional for Truly Optional Dependencies:**

333

```java

334

// Good: Feature may not be available

335

@Inject Optional<AnalyticsService> analytics;

336

337

// Avoid: Required dependencies as Optional

338

@Inject Optional<DatabaseService> database; // Should be required

339

```