当前位置: 首页 > 工具软件 > Java Dagger > 使用案例 >

Dagger2对Java多态场景的处理

姬国安
2023-12-01

日常开发过程中,总会遇到一个接口拥有多个子类,同时都需要进行实例化并完成自动依赖注入过程,有些DI框架针对这种场景的问题是通过ByName的方式处理的,也就是说,给实例化后的子类实例一个别名,实际使用过程中通过自动注入到引用别名的地方来使用的。

在Dagger2中也就类似的功能来支撑这种业务场景的对象实例自动依赖注入,接下来,我们将简要说明多态场景下Dagger2的使用。

4.1 Dagger2对简单多态场景的处理

首先定义一个MyBusinessInterface接口,此接口将被多个子类继承:

package com.tc.app.dagger2.di.ext;
​
public interface MyBusinessInterface {
    void display();
}

对应子类的定义如下

MyBusinessA的定义:

package com.tc.app.dagger2.di.ext;
​
import android.util.Log;
​
public class MyBusinessA implements MyBusinessInterface {
​
   MyBusinessA() {
   }
​
   @Override
   public void display() {
      Log.i("[MyBusinessA.display()]", "MyBusinessA.display() called!");
   }
}

MyBusinessB的定义

package com.tc.app.dagger2.di.ext;
​
import android.util.Log;
​
public class MyBusinessB implements MyBusinessInterface {
​
   MyBusinessB() {
   }
​
   @Override
   public void display() {
      Log.i("[MyBusinessB.display()]", "MyBusinessB.display() called!");
   }
}

关键部分来了,我们定义一个MyBusinessModule类来专门处理多态的问题,具体定义如下面代码所示:

package com.tc.app.dagger2.di.ext;
​
import javax.inject.Named;
​
import dagger.Module;
import dagger.Provides;
​
@Module
public class MyBusinessModule {
​
   @Named("myBusinessA")
   @Provides
   public MyBusinessInterface provideMyBusinessA(){
      return new MyBusinessA();
   }
​
   @Provides
   @Named("myBusinessB")
   public MyBusinessInterface provideMyBusinessB(){
      return new MyBusinessB();
   }
}

定义好相应的实例后,开始进行对接:

package com.tc.app.dagger2;
​
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
​
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
​
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.tc.app.dagger2.di.DaggerMyApartComponent;
import com.tc.app.dagger2.di.ext.MyBusinessInterface;
​
import javax.inject.Inject;
import javax.inject.Named;
​
public class MainActivity extends AppCompatActivity {
​
   /** 通过依赖注入的业务服务实例 */
   @Named("myBusinessA")
   @Inject
   MyBusinessInterface myBusinessA;
​
   /** 通过依赖注入的业务服务实例 */
   @Named("myBusinessB")
   @Inject
   MyBusinessInterface myBusinessB;
​
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      this.setContentView(R.layout.activity_main);
      Toolbar toolbar = findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);
​
      FloatingActionButton fab = findViewById(R.id.fab);
      fab.setOnClickListener((view) ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                  .setAction("Action", null).show()
      );
​
      //初始化环境,并完成功能调用
      DaggerMyApartComponent.create().inject(this);
      this.myBusinessA.display();
      this.myBusinessB.display();
   }
​
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
   }
​
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      int id = item.getItemId();
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}

注:对接前,一定要记得执行build操作,否则可能导致中间代码没有生成而报错哦

不失完整性,我们给出MyApartComponent的定义:

package com.tc.app.dagger2.di;
​
import com.tc.app.dagger2.MainActivity;
import com.tc.app.dagger2.di.ext.MyBusinessModule;
​
import dagger.Component;
​
@Component(modules = {MyBusinessApartModule.class, MyBusinessModule.class})
public interface MyApartComponent {
   void inject(MainActivity activity);
}

运行后,如果看到下面的日志,则说明配置成功了

I/[MyBusinessA.display()]: MyBusinessA.display() called!
I/[MyBusinessB.display()]: MyBusinessB.display() called!

4.2 Dagger2对多态场景的集中管理

上面例子中,虽然演示了Dagger2对多态的支持,但场景过于简单,实际使用场景中,我们对多态的应用在命令模式(Command模式)的使用场景中通常会大量应用。为了方便能够通过Dagger2完成多态实例的集中管理,我们再次对MyBusinessModule类进行改造,代码如下:

package com.tc.app.dagger2.di.ext;
​
import java.util.HashMap;
import java.util.Map;
​
import javax.inject.Named;
​
import dagger.Module;
import dagger.Provides;
​
@Module
public class MyBusinessModule {
​
   @Named("myBusinessA")
   @Provides
   public MyBusinessInterface provideMyBusinessA() {
      return new MyBusinessA();
   }
​
   @Provides
   @Named("myBusinessB")
   public MyBusinessInterface provideMyBusinessB() {
      return new MyBusinessB();
   }
​
   @Provides
   public Map<String, MyBusinessInterface> bizCtx(@Named("myBusinessA") MyBusinessInterface myBusinessA, @Named("myBusinessB") MyBusinessInterface myBusinessB) {
      Map<String, MyBusinessInterface> bizCtx = new HashMap<>();
      if (myBusinessA != null) {
         bizCtx.put("myBusinessA", myBusinessA);
      }
​
      if (myBusinessB != null) {
         bizCtx.put("myBusinessB", myBusinessB);
      }
      return bizCtx;
   }
}

注:通过@Provides方式,我们声明一个bizCtx数据实例

使用数据实例的Activity代码如下:

package com.tc.app.dagger2;
​
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
​
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
​
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.tc.app.dagger2.di.DaggerMyApartComponent;
import com.tc.app.dagger2.di.ext.MyBusinessInterface;
​
import java.util.Map;
​
import javax.inject.Inject;
​
public class MainActivity extends AppCompatActivity {
​
   /** 通过依赖注入的业务服务实例 */
   @Inject
   Map<String, MyBusinessInterface> bizCtx;
​
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      this.setContentView(R.layout.activity_main);
      Toolbar toolbar = findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);
​
      FloatingActionButton fab = findViewById(R.id.fab);
      fab.setOnClickListener((view) ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                  .setAction("Action", null).show()
      );
​
      //初始化环境,并完成功能调用
      DaggerMyApartComponent.create().inject(this);
      if (bizCtx != null && bizCtx.size() > 0) {
         bizCtx.get("myBusinessB").display();
      }
   }
​
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
   }
​
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      int id = item.getItemId();
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}

注:通过注入Map<String, MyBusinessInterface> bizCtx数据实例,我们可以随心所欲的取用任意一款心仪的特定实现

运行app后,控制台日志出现如下日志,则说明本次多态的集中管理改造过程已经成功完成:

I/[MyBusinessB.display()]: MyBusinessB.display() called!

 类似资料: