使用Dagger 2进行共享偏好管理

时间:2018-01-10 16:12:34

标签: java android dagger-2 dagger

我有这个简单的模块 SharePreferencesModule.java

@Module(includes = ApplicationModule.class)
public class SharedPreferencesModule {
    @Provides
    SharedPreferences sharedPreferences(MyApp app) {
        return app.getSharedPreferences("...", Context.MODE_PRIVATE);
    }

    @Provides
    @Named("firstname")
    static String getFirstname(SharedPreferences preferences) {
        return preferences.getString("firstname", "");
    }
}

使用此组件 SharedPreferencesComponent.java

@Component(modules = SharedPreferencesModule.class)
public interface SharedPreferencesComponent {
    void inject(MyFragment myClass);
}

这个类正在使用模块:

public MyFragment extends Fragment {
    @Inject
    @Name("firstname")
    String firstname;

    @Override
    public void onAttach(Context context) {
        // Not posting "Injector" code in the snippet because it is irrelevant
        Injector.getSharedPreferencesComponent().inject(this);
    }
}

创建MyFragment后,我成功注入了firstname,但是如果编辑了共享的prefs,我仍然引用firstname的旧值。这是正常的,因为只有当MyFragment附加时,Dagger才会提供名字。

如何与共享的首选项保持同步?

每次更新共享首选项时,是否应该重新注入MyFragment?对我来说似乎很麻烦。 或者我可以以某种方式迫使Dagger为我取这些数据?

2 个答案:

答案 0 :(得分:3)

  

每次更新共享首选项时,是否应该重新注入MyFragment?

你应该只注射一次,就像你不多次调用构造函数一样。

可能会有一些例外,确实需要(或者更喜欢)再次注入,但所有这些注入都应该在开始使用你的对象之前发生。多次注入会导致不一致的状态,即不清楚哪个对象引用了注入对象的哪个版本 这可能在某些情况下有效,但会导致其他人遇到困难,无论哪种方式,您都很难设置它,确保更新所有内容。每当发生变化时,你最好只是摧毁并重新创建整个片段。

注入一个对象应该是一次完成的初始设置,之后该类应该可以使用了。

如果事情不断变化,那么Dagger并不是最适合提供它的人。你的名字可能会更好地放在一些NameSettings

class NameSettings {
  private SharedPreferences prefs;

  @Inject NameSettings(SharedPreferences prefs) {
    this.prefs = prefs;
  }

  String getName() { return /* load from prefs */ }
  void setName(String name) { /* save to prefs */ }
}

而不是直接注入名称,您现在可以注入NameSettings并调用get / set来更新您的名字。这样您就可以随时读取和写入最新值,而无需直接处理SharedPreferences。

现在你的NameSettings不会改变,也不需要重新注射它。 您甚至可以继续返回Observable(例如RxJava或可观察模式的某些自定义实现),然后您可以随时监听更改并动态更新UI。

答案 1 :(得分:1)

我会@Provide SharedPreferences对象本身。这最小化了依赖图,使您可以读/写任何首选项。