【问题标题】:Dagger2 How to inject Objects unique and created once for each Activity?Dagger2 如何为每个 Activity 注入唯一并创建一次的对象?
【发布时间】:2018-07-10 11:33:39
【问题描述】:

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

*编辑:当我开始学习时,我仍然很困惑,Dagger 对于初学者来说似乎太混乱了,我在问你是否可以在创建 Activity 时将相同的用户注入到相同的 Activity。 User 和 Activity 应该是一对一的关系。

  1. Activity1
  2. Activity2
  3. Activity3

这是第一次创建活动的时候。

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

我在想 Dagger 像 Pool 一样保留对象,并将 Activity 实例与对象哈希链接或保留有关注入对象的状态或内部引用,我在问这是否可能。*

如何注入一个 Activity 独有的对象的相同实例,它是在第一次创建该 Activity 时创建的,并在我使用 @ActivityScope 导航到或启动该 Activity 时再次注入?我使用下面的sn-ps来构建这个例子

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。

我的问题是为什么这些类没有让每个活动的用户都是唯一的? 它们被注入了相同的User,即使在它们之间导航之后,我怎样才能让这些类拥有自己的User

【问题讨论】:

  • 您可以在Application 类中添加创建组件的代码吗?
  • @ThiagoPorciúncula 添加了 MyApplication 类。我发现我问的是不可能的。即使在 Activity 被销毁后,您也无法为每个存在的 Activity 获取唯一用户。我只是想知道我是否重新启动 ThirdActivity 并获得上次获得的相同实例,或者我下次获得的实例将与上次使用应用程序类中的组件相同。它的行为与@Singleton 相同,并为 ActivitySecond 和 ActivityThird 返回相同的用户

标签: android dagger-2


【解决方案1】:

我对你的问题感到很困惑。所以我要回答他们两个。

如何将相同的对象实例注入到每个活动中 @活动范围?我使用下面的sn-ps来构建这个例子

要将对象的相同实例注入多个类,您必须使用相同的容器并限定提供程序方法。

我的问题是为什么这些类不让每个类的用户都是唯一的 活动?它们注入了相同的用户,我该如何制作这些 即使在导航之后类也有自己的用户?

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

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

【讨论】:

  • 我的问题是是否可以向 Activity 注入独特的实例,但 Dagger 不是这样。例如,括号内的数字是我写的任意代码,Activity1 -> User(100), Activity2 -> User(101), Activity3 -> 103。当我从 Activity3 导航到 Activity1 时,我问我是否仍然得到 User(100 ) 和其他活动一样......我了解到这是不可能的。如果组件在应用程序中声明,我会得到相同的用户,否则每次导航或创建活动时都会创建新用户。
  • 可以使用单个组件实例注入不同的实例。这就是无范围依赖的用途。现在,如果您想为给定的组件使用相同的实例,那么范围界定就是要走的路。现在,如果您想要一个将不同实例注入不同类的作用域组件(和依赖项),那么您必须为每个类创建一个组件。
  • 我知道,但它返回相同的实例。我的问题是创建 Activity 时创建的用户实例,并在再次创建该 Activity 时注入该 Activity。
【解决方案2】:

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

【讨论】:

  • 我的问题是,每次创建 Activity 时是否有可能获得一个 Activity 唯一的相同用户。你导航回活动,你又得到了同样的一个。您转到第三个活动,您仍然会在活动时获得第一次创建的第三个活动。我了解到这是不可能的。我启动应用程序获取 ActivityMain 的 User(100)、ActivitySecond 中的 User(101) 和 ActivityThird 中的 User(102)。当您浏览这些活动时,我在问 Dagger 是否有任何方法可以一遍又一遍地为这些用户提供服务。单身人士,但活动独有。
  • 正如我所说的 - 每个活动都需要一个单独的组件,每个组件将为每个活动提供不同的用户,组件必须具有不同的范围
  • 我猜这不是我问的结果,它每次调用 onCreate() 时都会向 Activity 注入 new 用户对象。我问的是我是否可以为相同的活动获得相同的对象。如果您再次启动 Activity3,您应该会获得第一次启动 Activity 时获得的实例。
  • 在组件存活之前你会得到相同的对象,只是在activity被销毁时不要销毁组件,每个组件每次都会提供相同的用户
【解决方案3】:

MyApplication 中创建UserComponent 的实例,并使用它在SecondActivity 类中注入User。但是在MainActivity 类中,您正在重新创建UserComponent,这就是为什么您在每个活动中都有不同的User 实例。

您需要使用 ((MyApplication) getApplication()).getUserComponent().inject(this); MainActivity 中也是如此。

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2014-04-09
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多