Dagger2如何为每个Activity注入唯一且创建一次的对象?

时间:2018-07-10 11:33:39

标签: android dagger-2

我正在学习Dagger2,并尝试保持简单的示例并尽可能地隔离其他功能,以了解所需的部分。

*编辑:当我开始学习时,我仍然感到困惑,对于初学者来说,匕首似乎太令人困惑,我在问您是否可以在创建该活动时向同一活动注入同一用户。用户和活动应具有1到1的关系。

  1. 活动1 <-用户(100)数字是任意哈希
  2. Activity2 <-User(101)
  3. Activity3 <-用户(102)

这是第一次创建活动。

我的问题是您从Activity3导航回到Activity2,那么是否有可能仅使用Dagger再次注入User(101)?您回到Activity1,并从Application内部创建的组件中获得User(100)而不是新User或Singleton对象。

我在想Dagger像Pool一样保持对象,并将Activity实例与对象散列联系起来,或者保持有关注入对象的状态或内部引用,我问这是否可能。*

我该如何注入一个Activity特有的对象的同一实例,它是在首次创建该Activity时创建的,当我使用@ActivityScope导航到或启动该Activity时又重新注入的?我使用下面的代码片段构建此示例

public class User {

    private String name;

    private String email;

    public User() {
        name = "Unknown";
        email = "abc@xyz.com";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

范围

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

模块类

@Module
public class UserModule {

    @ActivityScope
    @Provides
    User provideUser() {
        return new User();
    }
}

组件

@ActivityScope
@Component(modules = {UserModule.class})
public interface UserComponent {
    void inject(MainActivity mainActivity);

    void inject(SecondActivity secondActivity);

    void inject(ThirdActivity thirdActivity);
}

我从MyApplication和MainActivity内部获取组件,以使用userComponent = DaggerUserComponent.create();

测试注入的对象
public class MainActivity extends AppCompatActivity {

    @Inject
    User user;

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

        UserComponent daggerUserComponent =  DaggerUserComponent.create();
        daggerUserComponent.inject(this);

        TextView textView = findViewById(R.id.textView);
        textView.setText("Main User: " + user.hashCode());


        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

    }

}

每次旋转设备时,此操作都会返回不同的User,这是自每次创建新的UserComponent以来的预期行为。

public class SecondActivity extends AppCompatActivity {

    @Inject
    User user;

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

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(SecondActivity.this, ThirdActivity.class);
                startActivity(intent);
            }
        });


        ((MyApplication) getApplication()).getUserComponent().inject(this);


        TextView textView = findViewById(R.id.textView);
        textView.setText("Second User: " + user.hashCode());
    }

}

应用程序类

public class MyApplication extends Application {

    private UserComponent userComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        userComponent = DaggerUserComponent.create();
    }


    public UserComponent getUserComponent() {
        return userComponent;
    }
}

SecondActivity和ThirdActivity使用MyApplication中的UserComponent。

我的问题是,为什么这些类不能使每个Activity的用户唯一? 它们被注入相同的User,即使在它们之间导航后,如何使这些类具有自己的User

3 个答案:

答案 0 :(得分:0)

我很困惑你的问题。所以我要回答这两个问题。

  

我怎样才能将对象的相同实例注入到每个活动中   @ActivityScope?我使用下面的代码片段构建此示例

要将对象的相同实例注入多个类,必须使用相同的容器并确定provider方法的作用域。

  

我的问题是,为什么这些类不能使每个类的用户唯一   活动?他们注入了相同的用户,我该怎么做   类之间甚至在导航之后也拥有自己的用户?

这是因为provideUser的范围是@ActivityScope。由于您正在使用应用程序中的相同组件,因此每次都将获得该对象的相同实例。

总而言之,作用域表示使用同一容器的所有类的相同实例。无作用域意味着每次注入总是一个新的对象实例。

答案 1 :(得分:0)

您需要为每个活动使用不同的组件,然后它们将为每个活动提供不同的用户,如果在活动被销毁之前将组件保持活动状态-即使更改了配置,它也将为同一活动提供相同的用户。您可以通过使用ViewModel并销毁方法onCleared()

中的组件来实现

答案 2 :(得分:0)

require 'sinatra/base' module Tir class App < Sinatra::Base # code end end 中创建一个configure_options的实例,并使用该实例将MyApplication注入UserComponent类中。但是在User类中,您正在重新创建SecondActivity,这就是为什么每个活动中都有不同的MainActivity实例的原因。

您需要使用UserComponentUser中也是如此。