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

How to implement sharedPreferences with dagger 2 in presenter layer without context?

如何用 dagger 和 MVP 实现 sharedpreferences,大多数教程都是在 Activity 中编写 sharedpreferences 或向演示者提供上下文。

我需要的是看例子:

===更新===

正如 PPartisan 在他的回答中提到的,我不应该在 Presenter 中包含 sharedPreference .

那么我如何抽象SharedPreferences后面的API

===更新2===

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

主要Activity

 @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);
    }

}

上下文模块

@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);
}

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

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

在您的 Presenter 中:

class Presenter {

    private final SharedPreferences prefs;

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

}

不过,您还可以用它做更多的事情。例如,您可以将 Presenter 的范围限定为 View 的生命周期(即 ActivityFragment)。此外,最纯粹形式的 "Presenter" 应该对 Android 组件一无所知,因此您可能想要抽象出您自己的 API 背后的 SharedPreferences

编辑: 下面是一个示例,说明如何抽象化数据持久性,以便 Presenter 可以保持对 Android 组件的感知:

创建一个合适的接口(这只是持久化和 returns 字符串,因此相应地修改它):

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();
    }

}

通过将以下内容添加到您的模块(确保您的模块是 abstract)来告诉 Dagger Repository 的这个实现是您想要使用的那个:

@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());
    }

}