如何在没有上下文的情况下在演示者层中使用Dagger 2实现sharedPreferences?

时间:2019-03-22 13:53:59

标签: android sharedpreferences dagger-2 mvp

如何使用Dagger和MVP实现共享首选项,大多数教程都是在Activity中编写共享首选项或为演示者提供上下文。

我需要的是看例子:

  • 我应该写些什么presenter以获得sharedPreference 无需使用Context
  • module的外观。
  • 我是否需要从Component或每个地方致电Application 提供上下文的活动。

===更新===

正如 PPartisan 在他的回答中提到的那样,我不应该在sharedPreference中加入 Presenter

那么我该如何在API后面抽象 SharedPreferences

===更新2 ===

感谢您的回答 PPartisan ,它确实很好用,请您检查一下我的代码是否完美,或者是否需要任何调整。

MainActivity

 @Inject
    MainPresenter presenter;

    AppComponent component;

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

        initView();

        component = DaggerAppComponent
                .builder()
                .contextModule(new ContextModule(this))
                .build();

        component.inject(this);

    }

AppModule

@Module
public abstract class AppModule {

    @Binds
    abstract Repository bindRepository(SharedPrefsRepository prefs);

    @Binds
    abstract MainPresenterListener listener(MainPresenterListener mListener);

    @Provides
    static SharedPreferences prefs(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

}

ContextModule

@Module
public class ContextModule {

    private Context context;

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

    @Provides
    Context getContext() {
        return context;
    }

}

AppComponent

@Component (modules = {AppModule.class, ContextModule.class})
public interface AppComponent {
    void inject(MainActivity activity);
}

1 个答案:

答案 0 :(得分:2)

以最简单的形式(并假设Context已成为依赖图的一部分),然后在模块中:

@Provides static SharedPreferences prefs(Context context) {
    return PreferenceManager.getDefaultSharedPreferences(context);
}

在演示者中:

class Presenter {

    private final SharedPreferences prefs;

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

}

但是,您可以做更多的事情。例如,您可以将Presenter的范围限定为View的生命周期(即ActivityFragment)。另外,“ Presenter”以其最纯粹的形式应该对Android组件一无所知,因此您可能希望将SharedPreferences抽象到您自己的API后面。

编辑:下面是一个示例,该示例说明了如何抽象化数据持久性,以便Presenter可以不了解Android组件:

创建一个合适的接口(该接口会持久保存并返回字符串,因此请相应地对其进行修改):

interface Repository {
    String read();
    void write(String value);
}

为此interface创建一个实例,委派给SharedPreferences

class SharedPrefsRespository implements Repository {

    private static final String KEY = "a_key";

    private final SharedPreferences prefs;

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

    @Override
    String read() {
        return prefs.getString(KEY, "");
    }

    @Override
    void write(String value) {
        prefs.edit()
            .putString(KEY, value == null ? "" : value)
            .apply();
    }

}

告诉Dagger,您想通过将以下内容添加到模块中来确保使用Repository的这种实现(确保您的模块为abstract):

@Binds abstract Repository repository(SharedPrefsRepository prefs);

在您的Presenter中,注入Repository而不是SharedPreferences

class Presenter {

    private final Repository repo;

    private View view;

    @Inject
    Presenter(Repository repo) {
       this.repo = repo;
    }

    void attach(View view) {
        this.view = view;
        showUserName();
    }

    //Example of how you might use this repo on something you want to persist
    //Imagine a user has entered their username and clicked save...
    void onSaveUserName(String username) {
        repo.write(username);
    }

    private void showUserName() {
        view.showUsername(repo.read());
    }

}