Android Jetpack 的 Hilt依赖注入框架的使用介绍

Hilt依赖注入框架的使用介绍

引入Hilt

1. 在项目根目录的build.gradle文件中配置Hilt的插件路径:

buildscript {
    
    
    ...
    dependencies {
    
    
        ...
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
    }
}

2. 在app/build.gradle文件中,引入Hilt的插件并添加Hilt的依赖库:

...
//apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
    
    
    ...
}

dependencies {
    
    
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    //kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}

这里同时还引入了kotlin-kapt插件,是因为Hilt是基于编译时注解来实现的,而启用编译时注解功能一定要先添加kotlin-kapt插件。如果你还在用Java开发项目,则可以不引入这个插件,同时将添加注解依赖库时使用的kapt关键字改成annotationProcessor即可

3. 在项目中启用 Java 8,请将以下代码添加到 app/build.gradle 文件中:

android {
    
    
  ...
  compileOptions {
    
    
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

.

.

Hilt的简单使用

使用步骤:

1. 创建MyApplication类

@HiltAndroidApp
public class MyApplication extends Application {
    
    
 ... 
}

注:

所有使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注释的 Application 类

  • @HiltAndroidApp : 会触发 Hilt 的代码生成操作,生成的代码包括应用的一个基类,该基类充当应用级依赖项容器

2. 将MyApplication注册到你的AndroidManifest.xml文件当中

<application
    android:name=".MyApplication"
    ...>
    
</application>

3. 将依赖项注入 Android 类

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
    }

}

在 Application 类中设置了 Hilt 且有了应用级组件后,Hilt 可以为带有 @AndroidEntryPoint 注释的其他 Android 类提供依赖项

Hilt 目前支持以下 Android 类:

  • Application(通过使用 @HiltAndroidApp)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

注意:
在 Hilt 对 Android 类的支持方面还要注意以下几点:

  • Hilt 仅支持扩展 ComponentActivity 的 Activity,如 AppCompatActivity

  • Hilt 仅支持扩展 androidx.Fragment 的 Fragment

  • Hilt 不支持保留的 Fragment

4. 创建需要被注入的类

public class MyClass {
    
    
	
	@Inject
	public void MyClass(){
    
    
	
	}		

	public void addLog(){
    
    
		Log.d("TAG","我是需要被注入的类");
	}

}

向 Hilt 提供绑定信息的一种方法是构造函数注入在某个类的构造函数中使用 @Inject 注释,以告知 Hilt 如何提供该类的实例

注意:

  • Hilt注入的字段是不可以声明成private的

补充: 如果构造函数携带参数,那么需要对参数的类也要依赖注入的相关处理;

例如 :就是MyClass的构造函数中所依赖的所有其他对象都支持依赖注入了,那么MyClass才可以被依赖注入

5. 把创建的类注入到Activity中

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    

	@Inject
	MyClass myclass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
		
		//调用MyClass里的方法
		myclass.addLog();
    }

}

.

.

接口的依赖注入(使用 @Binds )

1. 创建一个接口

public interface MyInterface {
    
    

	//定义抽象方法
	void addLog();
}

2. 创建实现接口的实体类

public class MyClass implements MyInterface {
    
    
	
	@Inject
	public void MyClass(){
    
    
	
	}	

	@Override
	public void addLog(){
    
    
		Log.d("TAG","我是需要被注入的类");
	}

}

3. 创建抽象类

@Module
@InstallIn(ActivityComponent.class)
public abstract class MyModule {
    
    

	@Binds
	 public abstract MyInterface bindMyClass(
	    MyClass myclass
  );
 
}

说明:
因为接口无法通过构造函数注入它,而没有办法向 Hilt 提供绑定信息。解决方法是在 Hilt 模块内创建一个带有 @Binds 注释的抽象函数
@Binds注释作用 :会告知 Hilt 在需要提供接口的实例时要使用哪种实现

带有注释的函数会向 Hilt 提供以下信息

  • 函数返回类型会告知 Hilt 函数提供哪个接口的实例

  • 函数参数会告知 Hilt 要提供哪种实现

@InstallIn(ActivityComponent.class)作用 :意味着,MyModule中的所有依赖项都可以在应用的所有 Activity 中使用

4. 把接口的实现类注入到Activity中

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    

	@Inject
	MyInterface myInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
		
		//调用接口实现类里的方法
		myInterface.addLog();
    }

}

.

.

给相同类型注入不同的实例

1. 创建一个接口

public interface MyInterface {
    
    
	//定义抽象方法
	void addLog();
}

2. 创建两个类

public class MyClass1 implements MyInterface {
    
    
	
	@Inject
	public void MyClass1(){
    
    
	
	}	
	
	@Override
	public void addLog(){
    
    
		Log.d("TAG","我是类1");
	}
}

//定义注解
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface bindMyClass1 {
    
    }

public class MyClass2 implements MyInterface {
    
    
	
	@Inject
	public void MyClass2(){
    
    
	
	}	

	@Override
	public void addLog(){
    
    
		Log.d("TAG","我是类2");
	}
}

//定义注解
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface bindMyClass2 {
    
    }
  • Qualifier注解作用: 给相同类型的类或接口注入不同的实例

  • @Retention注解作用: 用于声明注解的作用范围

注: AnnotationRetention.BINARY表示该注解在编译之后会得到保留,但是无法通过反射去访问这个注解

3. 创建抽象类

@Module
@InstallIn(ActivityComponent.class)
public abstract class MyModule {
    
    
	
   @bindMyClass1
   @Binds
   public abstract MyInterface bindMyClass1(MyClass1 myclass);
 
   @bindMyClass2
   @Binds
   public abstract MyInterface bindMyClass2(MyClass2 myclass);
}

@InstallIn(ActivityComponent.class)作用 :把这个模块安装到Activity组件当中

注:
Activity中包含的Fragment和View也可以使用,但是除了Activity、Fragment、View之外的其他地方就无法使用了

Hilt一共内置了7种组件类型,分别用于注入到不同的场景,如下表
在这里插入图片描述

使用的时候只需要替换@InstallIn(类型.class)里的类型就OK了

4. 把接口的实现类注入到Activity中

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    
	
	@bindMyClass1
	@Inject
	MyInterface myInterface1;

	@bindMyClass2
	@Inject
	MyInterface myInterface2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
		
		//调用接口实现类里的方法
		myInterface1.addLog();
		myInterface2.addLog();
    }

}

.

.

第三方类库的依赖注入

以Retrofit为例

1. 添加Retrofit和相关的依赖

dependencies {
    
    
	// Retrofit库
    implementation 'com.squareup.retrofit2:retrofit:2.0.2'
    // Okhttp库
    implementation 'com.squareup.okhttp3:okhttp:3.1.2' 
	//Gson库
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
}

2. 添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

3. 创建NetworkModule的类

@Module
@InstallIn(ActivityComponent.class)
public  class NetworkModule  {
    
    

  @Singleton
  @Provides
  public static Retrofit provideRetrofit() {
    
    
      return new Retrofit.Builder()
               .baseUrl("请求地址的域名部分")
			   .addConverterFactory(GsonConverterFactory.create())
	           .build()
	  }
}

注:
provideRetrofit()这个方法名是随便定义的,Hilt不做任何要求;记得要在provideRetrofit()方法的上方加上@Provides注解,这样Hilt才能识别它

@Provides注释作用 :向 Hilt 提供以下信息:

  • 函数返回类型会告知 Hilt 函数提供哪个类型的实例

  • 函数参数会告知 Hilt 相应类型的依赖项

  • 函数主体会告知 Hilt 如何提供相应类型的实例。每当需要提供该类型的实例时,Hilt 都会执行函数主体

@Singleton注解作用 :可以保证Retrofit在全局都只会存在一份实例

Hilt一共提供了7种组件作用域注解如下表所示:

使用的时候只需要把 @Singleton注解 替换到对应的注解就行了

在这里插入图片描述

4. 创建 接收服务器返回数据 的类

public class Users {
    
    

    private String userName;

    public String getUserName(){
    
    
		return userName;
	}
    
	public void setUserName(String userName){
    
    
		this.userName=userName;
	}
    
}

5. 创建 用于描述网络请求 的接口

public interface GetRequest_Interface {
    
    
   
	 @GET("地址域名后的一部分")
	 Call<Users> getCall();

}

6. 在Activity中发起请求

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    
	

	@Inject
	Retrofit retrofit;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
		
		 //网络请求接口 的实例
		 GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
		
		//对发送请求进行封装
		Call<Users> call = request.getCall();

		//发送网络请求(异步)
		call.enqueue(new Callback<Users>() {
    
    
            //请求成功时回调
            @Override
            public void onResponse(Call<Users> call, Response<Users> response) {
    
    

                //处理返回的数据结果
                response.body().show();

            }

            //请求失败时回调
            @Override
            public void onFailure(Call<Users> call, Throwable throwable) {
    
    

                System.out.println("连接失败");

            }
    	});
    }
}

.

.

Hilt 中的预定义限定符(传递Context)

由于您可能需要来自应用或 Activity 的 Context 类,因此 Hilt 提供了 @ApplicationContext 和 @ActivityContext 限定符

  • 获取 Activity 的上下文
public class AnalyticsAdapter {
    
    

  private final Context context;

  @Inject
  AnalyticsAdapter(@ActivityContext Context context) {
    
    
    this.context = context;
  }
}

public class AnalyticsAdapter {
    
    

  private final FragmentActivity activity;

  @Inject
  AnalyticsAdapter(FragmentActivity activity) {
    
    
    this.activity = activity;
  }
}
  • 获取 应用上下文 的上下文
public class AnalyticsServiceImpl implements AnalyticsService {
    
    

	  private final Context context;
	
	  @Inject
	  AnalyticsAdapter(@ApplicationContext Context context) {
    
    
	    this.context = context;
	  }
	}

	public class AnalyticsServiceImpl implements AnalyticsService {
    
    
	
	  private final Application application;
	
	  @Inject
	  AnalyticsAdapter(Application application) {
    
    
	    this.application = application;
	  }
}

.

.

ViewModel的依赖注入

1. 添加依赖

dependencies {
    
    
  implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
  annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}

2. 创建ViewModel类

public class MyViewModel extends ViewModel {
    
    

  private final ExampleRepository repository;
  private final SavedStateHandle savedStateHandle;

  @ViewModelInject
  MyViewModel(ExampleRepository repository,@Assisted SavedStateHandle savedStateHandle)
    {
    
    
    this.repository = repository;
    this.savedStateHandle = savedStateHandle;
  }
  ...
}

在 ViewModel 对象的构造函数中使用 @ViewModelInject 注释来提供一个 ViewModel。您还必须使用 @AssistedSavedStateHandle 依赖项添加注释

3. 在Activity中获取ViewModel

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    
    

  private MyViewModel ViewModel;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    
	ViewModel = new ViewModelProvider(this).get(MyViewModel.class);

  }
  ...
}

.

.

WorkManager的依赖注入

1. 添加依赖

dependencies {
    
    
  implementation 'androidx.hilt:hilt-work:1.0.0-alpha01'
  annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}

2. 创建Worker类

public class MyWorker extends Worker {
    
    

  private final WorkerDependency workerDependency;

  @WorkerInject
  MyWorker(@Assisted @NonNull Context context,@Assisted @NonNull WorkerParameters params,WorkerDependency workerDependency) {
    
    
    super(context, params);

    this.workerDependency = workerDependency;

  }
  ...
}

3. 在Application中获取MyWorker

@HiltAndroidApp
public class MyApplication extends Application implements Configuration.Provider {
    
    

  @Inject HiltWorkerFactory workerFactory;

  @Override
  public Configuration getWorkManagerConfiguration() {
    
    
    return Configuration.Builder()
             .setWorkerFactory(workerFactory)
             .build();
  }
}

参考资料

猜你喜欢

转载自blog.csdn.net/weixin_42324979/article/details/110391155