字段未在Android Dagger项目中注入

时间:2014-08-18 10:44:19

标签: java android dagger

我在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);
    }
}

但不知道为什么frequentlyUsedApps的{​​{1}}未按预期注入。知道为什么吗?

更新

我想我已经找到了原因。这是因为我手动创建UserPreference并在提供程序中使用它。如果我删除UserPreference的提供程序,并让 Dagger 自动连接,则会注入字段UserPreference。所以我不理解 Dagger

1 个答案:

答案 0 :(得分:8)

我认为你需要添加一些ObjectGraph#inject calls。

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

我一直在努力解决这个问题。我认为基本模式是:

  1. 注释您的字段以表明您想要注入它们
  2. 创建一个模块以提供"提供" @Injects
  3. 的实例
  4. 在某处创建图表(似乎大多数人都是这样做的 应用程序类)
  5. 在您要从模块中注入内容的类中,获取一个 图的实例并调用inject(this)。
  6. 我开始使用单例而不是Application类,因为至少现在我有一些地方是我想注入应用程序本身。

    所以这就是我目前正在做的事情,这似乎很有效。

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