Android使用依赖注入来处理简单的自定义类

时间:2016-10-23 06:23:52

标签: java android dependency-injection

在网上搜索了解此功能后,大多数主题或帖子都使用依赖注入Retrofit或其他Android有用的库,但我有一些自定义类,我想用DI和我可以&# 39;完成它,例如我有一个简单的自定义类用于使用SharePreference并且我使用它作为Singleton类

在我的代码中,我无法为SpApplication类上的组件分配正确的Dagger,以便在活动或片段上使用它

public class SP {

    private SharedPreferences preferences;
    private Context context;

    public SP(Context context) {
        this.context = context;
    }

    private SharedPreferences getPrefs() {
        return preferences = PreferenceManager.getDefaultSharedPreferences(context);
    }

    public String getString(SharedPrefsTypes propertyName) {
        return getPrefs().getString(propertyName.toString(), "");
    }


    public int getInt(SharedPrefsTypes propertyName) {
        return getPrefs().getInt(propertyName.toString(), 0);
    }
    ...
    public enum SharedPrefsTypes {
        Login
    }
}

现在我正在尝试使用DI:

AppModules类:

@Module
public class AppModules {
    private Context context;

    public AppModules(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    SP provideSharePreferences() {
        SP sharePreference = new SP(context);
        return sharePreference;
    }
}

ApplicationComponent上课:

@Component(modules = AppModules.class)
public interface ApplicationComponent {
    void inject(ActivityMain activity);
}

SpApplication上课:

public class SpApplication extends Application {
    private static SpApplication self;
    private ApplicationComponent component;

    @Override
    public void onCreate() {
        super.onCreate();

        self = this;
        component = DaggerApplicationComponent.builder().build();
    }


    public static SpApplication get(Context context) {
        return (SpApplication) context.getApplicationContext();
    }

    public static SpApplication getInstance() {
        return self;
    }

    public ApplicationComponent getComponent() {
        return component;
    }
}

和我的ActivityMain班级:

public class ActivityMain extends AppCompatActivity {
    @Inject
    SP sharePreference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((SpApplication) getApplication()).getComponent().inject(this);
        sharePreference.setInt(SP.SharedPrefsTypes.Login, 0);
    }
}

我收到此错误:

android.app.Application cannot be cast to com.pishguy.yendir.SpApplication

提前致谢

1 个答案:

答案 0 :(得分:2)

我猜你试图注入ActivityMain,但由于你没有提供它的来源,让我告诉你如何注入SpApplication。然后只需将相关部分复制到Activity

我认为你需要改变的事情很少。

<强>模块:

您的AppModules课程通常没问题,但我建议您改变使用Context的方式 - 不要将其用作字段,而是将其注入其他任何字段服务。它看起来像这样:

@Module
public class AppModules {
    private Context context;

    public AppModules(Context context) {
        this.context = context;
    }

    @Provides // this can be non-scoped because anyway the same instance is always returned
    Context provideContext() {
        return this.context;
    }

    @Provides
    @Singleton
    SP provideSharePreferences(Context context) {
        return new SP(context); // use method-local Context
    }
}

<强>组件:

  1. 如果组件注入作用域服务(@Singleton是作用域),则组件本身必须是作用域
  2. 如果要注入SpApplication类,则将其声明为组件
  3. 中的注入客户端

    考虑到这两点,ApplicationComponent应如下所示:

    @Singleton // injects @Singleton scoped services
    @Component(modules = AppModules.class)
    public interface ApplicationComponent {
        void inject(SpApplication application); // SpApplication is DI client (injection target)
    }
    

    <强>客户端:

    我改变了SpApplication课程中的一些内容:

    1. 实例化ApplicationComponent的方式不正确
    2. 这不是错误,但您并不需要get(Context)getInstance()方法
    3. 此外,由于我展示了如何注入SpApplication,我还将添加注入逻辑(您应该将其复制到实际客户端)。

      因此,SpApplication(DI客户端)看起来应该类似于:

      public class SpApplication extends Application {
      
          @Inject SP sp; // the dependency that should be injected
      
          private ApplicationComponent component;
      
          @Override
          public void onCreate() {
              super.onCreate();
      
              getComponent().inject(this); // this is when the actual injection takes place
          }
      
      
          public ApplicationComponent getComponent() {
              if (component == null) {
                  // this is the way Dagger components should be instantiated
                  component = DaggerApplicationComponent.builder()
                      .appModules(new AppModules(this))
                      .build();
              }
              return component;
          }
      }
      

      如果您执行上述更改,我倾向于相信您会没事。

      顺便说一句,我最近完成了关于Dagger 2范围的blog post。如果你要认真对待依赖注入,你可能想检查它。