我正在使用 Dagger用于在 Android 项目中进行依赖注入(inject),并且可以很好地编译和构建应用程序。对象图看起来是正确的并且可以工作,但是当我添加 dagger-compiler 作为依赖项以在编译时出错时,它会报告一些奇怪的错误:
[ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \
.mgodroid.io.NodeIndexTask> required by com.atami \
.mgodroid.ui.NodeIndexListFragment for com.atami.mgodroid \
.modules.OttoModule
[ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \
.mgodroid.io.NodeTask> required by com.atami \
.mgodroid.ui.NodeFragment for com.atami.mgodroid.modules.OttoModule
[ERROR] error: No injectable members on com.squareup.otto.Bus. Do you want
to add an injectable constructor? required by com.atami. \
mgodroid.io.NodeIndexTaskService for
com.atami.mgodroid.modules.TaskQueueModule
Otto 错误看起来像 Eric Burke 在他的 Android App Anatomy 中提到的错误关于没有 @Provides 注释的演示,但正如您在下面看到的,我有。
我的Otto和TaskQueue模块如下:
@Module(
entryPoints = {
MGoBlogActivity.class,
NodeIndexListFragment.class,
NodeFragment.class,
NodeActivity.class,
NodeCommentFragment.class,
NodeIndexTaskService.class,
NodeTaskService.class
}
)
public class OttoModule {
@Provides
@Singleton
Bus provideBus() {
return new AsyncBus();
}
/**
* Otto EventBus that posts all events on the Android main thread
*/
private class AsyncBus extends Bus {
private final Handler mainThread = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
mainThread.post(new Runnable() {
@Override
public void run() {
AsyncBus.super.post(event);
}
});
}
}
}
...
@Module(
entryPoints = {
NodeIndexListFragment.class,
NodeFragment.class,
NodeIndexTaskService.class,
NodeTaskService.class
}
)
public class TaskQueueModule {
private final Context appContext;
public TaskQueueModule(Context appContext) {
this.appContext = appContext;
}
public static class IOTaskInjector<T extends Task>
implements TaskInjector<T> {
Context context;
/**
* Injects Dagger dependencies into Tasks added to TaskQueues
*
* @param context the application Context
*/
public IOTaskInjector(Context context) {
this.context = context;
}
@Override
public void injectMembers(T task) {
((MGoBlogApplication) context.getApplicationContext())
.objectGraph().inject(task);
}
}
public static class ServiceStarter<T extends Task>
implements ObjectQueue.Listener<T> {
Context context;
Class<? extends Service> service;
/**
* Starts the provided service when a Task is added to the queue
*
* @param context the application Context
* @param service the Service to start
*/
public ServiceStarter(Context context,
Class<? extends Service> service) {
this.context = context;
this.service = service;
}
@Override
public void onAdd(ObjectQueue<T> queue, T entry) {
context.startService(new Intent(context, service));
}
@Override
public void onRemove(ObjectQueue<T> queue) {
}
}
@Provides
@Singleton
TaskQueue<NodeIndexTask> provideNodeIndexTaskQueue() {
ObjectQueue<NodeIndexTask> delegate =
new InMemoryObjectQueue<NodeIndexTask>();
TaskQueue<NodeIndexTask> queue = new TaskQueue<NodeIndexTask>(
delegate, new IOTaskInjector<NodeIndexTask>(appContext));
queue.setListener(new ServiceStarter<NodeIndexTask>(
appContext, NodeIndexTaskService.class));
return queue;
}
@Provides
@Singleton
TaskQueue<NodeTask> provideNodeTaskQueue() {
ObjectQueue<NodeTask> delegate =
new InMemoryObjectQueue<NodeTask>();
TaskQueue<NodeTask> queue = new TaskQueue<NodeTask>(
delegate, new IOTaskInjector<NodeTask>(appContext));
queue.setListener(new ServiceStarter<NodeTask>(
appContext, NodeTaskService.class));
return queue;
}
}
...
/**
* Module that includes all of the app's modules. Used by Dagger
* for compile time validation of injections and modules.
*/
@Module(
includes = {
MGoBlogAPIModule.class,
OttoModule.class,
TaskQueueModule.class
}
)
public class MGoBlogAppModule {
}
最佳答案
Dagger 的全图分析从一个完整的模块开始工作。即@Module(complete = true),这是默认的。因为它是默认设置,所以默认情况下,dagger 将假定所有绑定(bind)都可从该模块或它显式包含的那些模块中获得。
在这种情况下,您已经提供了两个您声称已完成的模块,但 Dagger 无法在没有额外信号的情况下在编译时将它们连接在一起。简而言之,在 OttoModule 不知道 TaskQueueModule 的情况下,编译器将尝试分析 OttoModule 的完整性,但会失败,因为它现在不了解 TaskQueueModule。
修改 OttoModule 的注解:
@Module(
includes = TaskQueueModule.class,
entryPoints = {
MGoBlogActivity.class,
NodeFragment.class,
NodeActivity.class,
NodeCommentFragment.class,
NodeIndexTaskService.class,
NodeTaskService.class
}
)
然后 Dagger 将知道要使 OttoModule 完整,它将另一个模块作为其完整定义的一部分。
注意:dagger-compiler 无法检测到 TaskQueueModule 存在于类路径中,只是“知道”开发人员打算将其与 OttoModule 一起使用而无需那个额外的信号。例如,您可能有多个定义任务队列的模块,它会选择哪一个?声明必须明确。
关于android - Dagger 在模块上找不到可注入(inject)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14695515/
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路