jjzjj

java - 未在 Android Dagger 项目中注入(inject)字段

coder 2023-12-10 原文

我正在 Android 上玩 Dagger。我创建了一个模型 UserPreference、一个名为 PreferenceModule 的模块和另一个类 UserPreferenceTest,它是 PreferenceModule 的测试。我有以下 3 个 java 文件

UserPreference.java

package com.sigicn.preference;

import javax.inject.Inject;

import com.sigicn.commonmodels.Application;

public class UserPreference {
    public String name, weiboAccount;

    @Inject
    public Application[] frequentlyUsedApps;
}

然后是 PreferenceModule.java

package com.sigicn.preference;

import javax.inject.Singleton;

import com.sigicn.commonmodels.Application;
import com.sigicn.utils.MiscUtils;

import dagger.Module;
import dagger.Provides;

@Module(library = true, complete = true)
public class PreferenceModule {

    @Provides @Singleton UserPreference provideUserPreference() {
        UserPreference userPreference = new UserPreference();
        userPreference.frequentlyUsedApps = provideApplications();
        return userPreference;
    }

    @Provides @Singleton Application[] provideApplications() {
        return new Application[]{
                new Application(
                        MiscUtils.generateUUID(), "Youtube"),
                new Application(
                        MiscUtils.generateUUID(), "Pixi")
            };
    }

}

然后是UserPreferenceTest.java

package com.sigicn.test.preference;

import javax.inject.Inject;

import com.sigicn.preference.PreferenceModule;
import com.sigicn.preference.UserPreference;

import dagger.Module;
import dagger.ObjectGraph;
import android.test.AndroidTestCase;

public class UserPreferenceTest extends AndroidTestCase {
    @Module(injects = {UserPreference.class, UserPreferenceTest.class}, 
            includes = PreferenceModule.class)
    static class TestModule {
    }

    ObjectGraph objectGraph; 

    @Inject
    UserPreference userPreference;

    @Override
    protected void setUp() throws Exception {
        if (objectGraph == null) {
            objectGraph = ObjectGraph.create(new TestModule());
        }
        super.setUp();
    }

    public void testFrequentlyUsedApps()
    { 
        UserPreference localUserPreference = objectGraph.get(UserPreference.class);
        assertNotNull(localUserPreference);
        assertEquals(localUserPreference.frequentlyUsedApps.length, 2);

        objectGraph.inject(this);
        assertNotNull(userPreference);
        assertEquals(userPreference.frequentlyUsedApps.length, 2);
        assertSame(localUserPreference, userPreference);
        assertSame(localUserPreference.frequentlyUsedApps, userPreference.frequentlyUsedApps);
    }
}

但不知道为什么,UserPreferencefrequentlyUsedApps 没有按预期注入(inject)。知道为什么吗?

更新:

我想我已经找到原因了。这是因为我手动创建了 UserPreference 并在提供程序中使用它。如果我删除 UserPreference 的 Provider,并让 Dagger 自动连接它,那么字段 frequentlyUsedApps 就会被注入(inject)。所以,我没有很好地理解 Dagger 是我的错。

最佳答案

我认为您需要添加一些 ObjectGraph#inject 调用。

在每个有 @Inject 注释的类中,您还需要调用您创建的 ObjectGraph 的注入(inject)方法。

我也为此苦苦挣扎了一段时间。我认为基本模式是:

  1. 注释您的字段以表明您想要注入(inject)它们
  2. 创建一个模块来“提供”那些@Injects 的实例
  3. 在某处创建图表(似乎大多数人都在这样做 应用程序类)
  4. 在你想从你的模块中注入(inject)东西的类中,得到一个 图的实例并调用 inject(this)。

我开始使用单例而不是 Application 类,因为至少现在我有一些地方想注入(inject)应用程序本身。

所以这就是我目前正在做的,它似乎工作得很好

public class Injector {

    private static Injector mInjector;
    private ObjectGraph mObjectGraph;
    private MyApp mApp;

    private Injector() {

    }

    public static Injector getInstance() {
        if (mInjector == null) {
            mInjector = new Injector();
        }
        return mInjector;
    }

    protected List<Object> getModules() {
        return Arrays.asList(
                                new ApplicationModule(mApp),
                                new AndroidModule(mApp)
                             );
    }

    public void inject(Object object) {
        getObjectGraph().inject(object);
    }

    public ObjectGraph getObjectGraph() {
        return mObjectGraph;
    }

    public void initialize(MyApp app) {
        mApp = app;
        mObjectGraph = ObjectGraph.create(getModules().toArray());  
        System.out.println(String.format("init object graph = %s",mObjectGraph.toString()));

    }

}

然后在我的应用程序类中,我有一个这样的构造函数:

public MyApp() {
    System.out.println("myapp construtor");  
    Injector.getInstance().initialize(this);
    Injector.getInstance().inject(this);

}

然后当我想注入(inject)一些东西时我会这样做

@Inject Bus mBus;

public GcmBroadcastReceiver() {
    Injector.getInstance().inject(this);

}

我有两个模块,一个用于生产,一个用于测试

生产的有这个

@Provides @Singleton
public Bus provideBus () {
    return BusProvider.getInstance();
}

测试的有这个

@Provides @Singleton
public Bus provideBus () {
    return mock(Bus.class);
}

关于java - 未在 Android Dagger 项目中注入(inject)字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25361454/

有关java - 未在 Android Dagger 项目中注入(inject)字段的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  6. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  9. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐