美文网首页
Android IOC注入技术—Hilt(二)

Android IOC注入技术—Hilt(二)

作者: 大虾啊啊啊 | 来源:发表于2022-02-20 13:04 被阅读0次

1、Hilt的介绍

Hilt是jetpack里的一个组件、是对Dagger2的二次封装,让使用的时候变的更简单、方便。在Hilt源码中大部分的代码都是Dagger2的代码。

2、Hilt的简单使用

和Dagger2一样,我们先来实现注入一个Dog对象

(1)引入Gradle依赖和插件

和 Dagger2不同的是,除了要引入API支撑以及注解处理器支持之外,Hilt还要引入Gradle插件。可以猜想到Hilt要使用Gradle插件在构建的时候做相应的操作(比如:字节码插桩)

 // hilt 依赖导入
    implementation "com.google.dagger:hilt-android:2.28-alpha" // hilt的支持 百分之八十的代码是来自Dagger2
    annotationProcessor "com.google.dagger:hilt-android-compiler:2.28-alpha" // Dagger的注解处理器APT 依赖使用
// 导入gradle-plugin 字节码插庄
    classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha' 
// 导入gradle-plugin 字节码插庄
    id 'dagger.hilt.android.plugin' // gradle-plugin   

(2)注入一个Dog对象

  • 创建Dog实体类
package com.it.hilt.bean;
public class Dog {
}
  • Application中使用注解
//hilt 基本上都要 用 Application来辅助
@HiltAndroidApp
public class MyAplication extends Application {
}
  • 对象包裹和提供
@InstallIn(ActivityComponent.class)//注入到Activity
@Module
public class DogModule {
    @Provides
    public Dog provideDog() {
        return new Dog();
    }
}
  • 注入到目标Activity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    private final String TAG = getClass().getSimpleName();
    @Inject
    public Dog dog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG, "onCreate: "+dog.hashCode() );
    }
}
MainActivity: onCreate: 75412883

和Dagger不同的是Hilt减少了Companent部分、并且Hilt只能将对象注入到四大组件或者Application中。
在DogModule 中我们看到InstallIn注解,代表要注入到的目标类型,ActivityComponent表示注入到Activity,当然还有ApplicationComponent、ServiceComponent、FragmentComponent等等。

(3)注入接口的实现

  • 创建一个接口和实现类
/**
 * 接口
 */
public interface ITest {
    /**
     * 测试方法
     */
    void testMethod();
}
/**
 * 接口实现类
 */
public class TestImpl implements ITest {
    private final String TAG = getClass().getSimpleName();
    @Inject
    TestImpl() {
    }
    @Override
    public void testMethod() {
        Log.e(TAG, "testMethod: hello" );
    }
}
  • 创建Module
@Module
@InstallIn(ActivityComponent.class)//注入到Activity
public abstract class TestInterfaceModule {
    @Binds
    public abstract ITest binderTestClass(TestImpl test);
}

  • 注入到目标Activity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    private final String TAG = getClass().getSimpleName();
    @Inject
    public ITest test;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test.testMethod();
    }
}
TestImpl: testMethod: hello

3、Hilt实现的简单分析

和Dagger2的使用区别我们发现、Hilt少了Companent类以及不需要在初始化的时候调用inject方法。
事实真的如此吗?
我们来观察Hilt字节码插桩之后的代码

  • MainActivity类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.it.hilt;

import android.os.Bundle;
import android.util.Log;
import com.it.hilt.bean.Dog;
import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;

@AndroidEntryPoint
public class MainActivity extends Hilt_MainActivity {
    private final String TAG = this.getClass().getSimpleName();
    @Inject
    public Dog dog;
    @Inject
    public ITest test;

    public MainActivity() {
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(2131427356);
        Log.e(this.TAG, "onCreate: " + this.dog.hashCode());
        this.test.testMethod();
    }
}

我们发现我们自己写的MainActivity继承类被改成了Hilt_MainActivity ,再来观察Hilt_MainActivity

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.it.hilt;

import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider.Factory;
import dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories;
import dagger.hilt.android.internal.managers.ActivityComponentManager;
import dagger.hilt.internal.GeneratedComponentManager;
import dagger.hilt.internal.UnsafeCasts;

abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManager<Object> {
    private volatile ActivityComponentManager componentManager;
    private final Object componentManagerLock = new Object();

    Hilt_MainActivity() {
    }

    Hilt_MainActivity(int contentLayoutId) {
        super(contentLayoutId);
    }

    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        this.inject();
        super.onCreate(savedInstanceState);
    }

    public final Object generatedComponent() {
        return this.componentManager().generatedComponent();
    }

    protected ActivityComponentManager createComponentManager() {
        return new ActivityComponentManager(this);
    }

    protected final ActivityComponentManager componentManager() {
        if (this.componentManager == null) {
            synchronized(this.componentManagerLock) {
                if (this.componentManager == null) {
                    this.componentManager = this.createComponentManager();
                }
            }
        }

        return this.componentManager;
    }

    protected void inject() {
        ((MainActivity_GeneratedInjector)this.generatedComponent()).injectMainActivity((MainActivity)UnsafeCasts.unsafeCast(this));
    }

    public Factory getDefaultViewModelProviderFactory() {
        Factory factory = DefaultViewModelFactories.getActivityFactory(this);
        return factory != null ? factory : super.getDefaultViewModelProviderFactory();
    }
}

可以看到MainActivity的onCreate方法调用了super.onCreate,因此会触发Hilt_MainActivity 的onCreate方法,而在Hilt_MainActivity 的onCreate方法中调用了inject方法,所以inject方法是Hilt帮我们调用了。来看看inject方法

   protected void inject() {
        ((MainActivity_GeneratedInjector)this.generatedComponent()).injectMainActivity((MainActivity)UnsafeCasts.unsafeCast(this));
    }

调用generatedComponent方法,生成了一个MainActivity_GeneratedInjector对象、再调用injectMainActivity方法,传入当前MainActity的实例。

      private MainActivity injectMainActivity2(MainActivity instance) {
        MainActivity_MembersInjector.injectDog(instance, DogModule_ProvideDogFactory.provideDog(dogModule));
        MainActivity_MembersInjector.injectTest(instance, new TestImpl());
        return instance;
      }
 @InjectedFieldSignature("com.it.hilt.MainActivity.dog")
  public static void injectDog(MainActivity instance, Dog dog) {
    instance.dog = dog;
  }

最后的代码就基本和Dagger2 差不多了,将我们DogModule提供对象的方法赋值给传入的MainActivity的Dog变量。

小结

Hilt是对Dagger2的二次封装、Dagger2是通过APT技术生成相应的代码将对象注入到指定的目标中。由于Dagger2的使用过于繁杂,Hilt在Dagger2的基础上进行二次封装,使用APT生成代码的同时,还使用了字节码插桩的方式,将被注入的类的继承关系修改,继承了Hilt生成的类,在这个生成的类中调用inject方法。

相关文章

网友评论

      本文标题:Android IOC注入技术—Hilt(二)

      本文链接:https://www.haomeiwen.com/subject/dvsylrtx.html