2014-05-09 101 views
1

好吧,我有一个问题,试图混合框架。 因此,我有一个@SharedPref注释类,它应该从Android Annotations生成一个共享首选项管理器。该类看起来有点像这样:匕首没有注入Android注解类

DownloadPrefs.java

@SharedPref(value= SharedPref.Scope.UNIQUE) 
public interface DownloadPrefs { 

    @DefaultBoolean(false) 
    boolean hasEnabledDownload(); 

    @DefaultBoolean(false) 
    boolean showedDownloadDialog(); 

    @DefaultLong(0) 
    long downloadRefreshedOn(); 
} 

现在,我想结果类(这将是DownloadPrefs_)注入到一个片段利用它。该片段已添加新模块工作注入,所以我只打算在这里写我说什么:

Fragment.java

@Inject DownloadPrefs_ downloadPrefs; 

现在,由于实际DownloadPrefs_类是在运行时产生的,它最有意义的是为它创建一个@Provides注释,因为我不能将构造函数标记为注入。 DownloadPrefs_也没有一个无参数的构造函数。我使用该模块然后接收新@Provides

DownloaderModule.java

@Provides //@Singleton // Does not work with/out @Singleton 
DownloadPrefs_ provideDownloadPrefs() { 
    return new DownloadPrefs_(MinimalBible.getApplication()); 
} 

要技术它,是可以获得由Android批注产生的DownloadPrefs_构造函数需要传递给它一个背景下,我也能猜到应用程序上下文将是合适的。否则,我不知道我怎样才能访问Activity上下文。或者是否真的会破坏ObjectGraph

然而,当我去运行实际注入,我得到以下信息:

Caused by: java.lang.IllegalStateException: Errors creating object graph: 
    org.bspeice.minimalbible.activities.downloader.DownloadPrefs_ has no injectable members. Do you want to add an injectable constructor? required by class org.bspeice.minimalbible.activities.downloader.BookListFragment 

上发生了什么事情的任何线索?似乎并没有在其他SO问题上询问“无注射成员”的问题回答了我的案例。在添加上面的代码之前,我有一个工作应用程序。

UPDATE:做一些仔细检查后,我碰到下面的怪异的行为。如果我将预构建的Android Annotations类复制出来,重新命名并注入,那么一切正常。此外,我可以验证原始的内置Android注释类(DownloadPrefs_.java)确实存在于.dex中,因此Dagger应该没有理由无法找到它。一切都在进行调试构建,所以我无法想象ProGuard会搞乱任何东西。

在这一点上,我将创建一个最小的项目来演示错误,并向Dagger提出问题。与此同时,只需要重写Prefs类,直到我可以把它整理出来。

UPDATE 2014年5月12日

下面是负责喷射模块时:

MinimalBibleModules.java

@Module(
    injects = { 
     MinimalBible.class 
    }, 
    includes = { 
     ActivityModules.class 
    } 
) 
public class MinimalBibleModules { 
} 

ActivityModules。java的

@Module(
    includes = { 
     ActivityDownloaderModule.class 
    } 
) 
public class ActivityModules { 
} 

ActivityDownloaderModule.java

@Module(
     injects = { 
      BookListFragment.class, 
      DownloadManager.class, 
      BookRefreshTask.class 
     } 
) 
public class ActivityDownloaderModule { 

    @Provides @Singleton 
    DownloadManager provideDownloadManager() { 
     return new DownloadManager(); 
    } 

    @Provides 
    EventBus provideBus() { 
     return new EventBus(); 
    } 


    @Provides //@Singleton 
    DownloadPrefs_ provideDownloadPrefs() { 
     return new DownloadPrefs_(MinimalBible.getApplication()); 
    } 
} 

此外,图形创建方式:

MinimalBible.java

public class MinimalBible extends Application { 

    private ObjectGraph graph; 

    private static MinimalBible instance; 

    public MinimalBible() { 
     instance = this;   
    } 

    @Override 
    public void onCreate() { 
     graph = ObjectGraph.create(new MinimalBibleModules()); 
     graph.inject(this); 
    } 
+0

创建Github的问题[#410](https://github.com/square/dagger/issues/410)用匕首,所有进一步的讨论可能将在那里举行。 –

+0

我通常会责怪proguard的 - 尤其是确保它不杀生的事情 - 但如果你说的时候没有proguard的这种情况,我是那么迷茫。 DownloaderModule中的“@ Provide”行是否被编译?如果是这样,那么proguard就不要把它取出来。您是否将DownloaderModule包含在您配置图形的主模块中?可以请你在'@ Module'添加注解你的主要模块的外壳,你创建一个图形的线,和属性设置?这很重要,看看你是否把一切都搞好了。 –

+0

该项目使用AndroidAnnotation并生成类DownloadPrefs_没有任何内部声明注入。 – Mikooos

回答

1

的这里有两个部分。首先,你如何访问Context。你可以像现在这样做静态事物,尽管这不是可取的。一般来说,你应该携带的背景下,这样的状态的模块配置图:

@Module 
class ApplicationModule { 
    private final Application application; 

    public ApplicationModule(Application app) { 
    this.application = app; 
    } 

    // you can mark this singleton, but it's minor overhead 
    // and the fact that you have a single instance stored 
    // means it's semantically equivalent. But for clarity 
    // it's sometimes good to make the point. 
    @Provides 
    @Singleton 
    Application application() { 
    return application; 
    } 

    // optionally: bind it as a Context with a qualifier. 
    // note: never bind Context without a qualifier annotation 
    // as Activity and Application are both Context subtypes. 
    @Provides 
    @Singleton 
    @PerApplication 
    Context appContext(Application app) { 

    // Doing this instead of returning this.application is 
    // semantically equivalent but links @PerApplication Context 
    // to Application, so in graph analysis and error reporting 
    // the link is clearer. That's a personal choice. 
    return app; 
    } 
} 

无论如何,你那么当你创建图形:

Application appInstance = ...; 
ObjectGraph appGraph = ObjectGraph.create(
    MyAppModule.class, 
    new ApplicationModule(appInstance)); 

的应用,然后接种放入图中,并可以由其他类型声明为依赖。