我有一个MainActivity,需要一个MeasurementFragment,而这又需要一个转换器。
问题是:当<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="affiliate-links">
<table class="affiliateLinksTable">
<tbody>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://firstproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> Second Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://secondproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://thirdproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://fourthproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://fifthproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://sixthproduct.html?A="></td>
</tr>
<tr>
<td><label for=""> FIrst Product Name</label></td>
<td><input class="myClass" id="affiliateLinkGenerated" type="text" name="affiliate-link" value="http://seventhproduct.html?A="></td>
</tr>
</tbody>
</table>
<div >
<div class="affiliate-id-form">
<input type="text" name="affiliateID" id="affiliateID" placeholder="Enter your affiliate ID eg. 124531" />
<input type="button" name="generate-links" id="btnGenerateLinks" value="Generate Links">
</div>
注入MesurementFragment时,其自身的依赖关系[1]
converter
将被取消注入。
[2]
有没有办法让注入“级联”,以便在注入class MainActivity extends AppCompatActivity {
@Inject MeasurementFragment measureFrag;
@Override
protected void OnCreate(Bundle b){
//[1]*
DaggerMainActivityComponent().create().inject(this);
}
}
时注入converter
?
我可以在构造函数(measureFrag
)中创建DaggerMainActivityComponent的第二个实例并注入其中,但这听起来不错。
[3]
其他可能相关的代码(组件和模块):
class MeasurementFragment extends Fragment {
// [2]*
@Inject Converter converter;
// required *empty* constructor
MeasrementFragment(){
// [3]*
}
}
有没有更好的设计来实现这一目标?
答案 0 :(得分:1)
有时当我们学习像Dagger 2这样的依赖注入框架时,会产生误解,即不惜一切代价避免使用new
关键字和静态工厂,并且每个对象应该注射。
对于Fragments,实例化的best practice是使用静态工厂方法。尽管之前的DI框架Roboguice鼓励将Fragments注入活动的属性(@Inject MeasurementFragment mf
),但使用Dagger 2尝试不同的方法可能会更好。这样做的原因是我们需要与活动的FragmentManager
进行协调:
对于给定的Activity,片段由FragmentManager
处理。当调用Activity onSaveInstanceState(Bundle outBundle)
时(例如,在内存不足的情况下),FragmentManager
将保存每个Fragment的实例状态以便在onCreate(Bundle savedInstanceState);
内进行恢复。
这就是您经常在Android示例中看到的原因:
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
}
检查saveInstanceState == null
以防FragmentManager中已存在Fragment。如果从已保存的实例状态恢复活动,您可以使用:
fragmentManager.findFragmentByTag(String tag)
获取它的句柄。这意味着使用Dagger 2在Activity内部简单地注入Fragment不足以解释Fragments和Activities的复杂生命周期。
更好的方法可能是放弃在Activity中注入Fragment的属性,并按照Developer's Guide中的建议使用静态工厂。然后,您将在Fragment本身中为Fragment 注入依赖项。像这样:
class MeasurementFragment extends Fragment {
@Inject Converter converter;
static MeasurementFragment instantiate() {
//if MeasurementFragment comes to require params in the future
//you can pass them in here and use setArguments(Bundle params);
return new MeasurementFragment(null);
}
MeasurementFragment(){
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DaggerMainActivityComponent.builder()
.build()
.inject(this);
}
}
现在,当您在Activity中的fragmentManager.beginTransaction().add()
上使用MeasurementFragment
时,当Android系统调用生命周期回调到onActivityCreated(Bundle bundle)
时,将在提交时执行注入。
使用此方法,您的活动可能会是这样的:
class MainActivity extends AppCompatActivity {
public static final String MEASUREMENT_FRAG = "MEASUREMENT_FRAG";
MeasurementFragment measureFrag;
@Override
protected void OnCreate(Bundle b){
super(b);
injectMembers();
if (b == null) {
measureFrag = MeasurementFragment.instantiate();
getFragmentManager().beginTransaction().add(R.id.frag_container, measureFrag, MEASUREMENT_FRAG).commit();
}
else {
//frag is already instantiated and added to container
measureFrag = getFragmentManager().findFragmentByTag(MEASUREMENT_FRAG);
}
}
@VisibleForTesting
void injectMembers() {
DaggerMainActivityComponent().create().inject(this);
}
}
我在这里概述的是在这个流行的Dagger 2 example on Github中演示的片段内注入成员的方法。更进一步的是使Fragments尽可能轻量级,并完全避免在其中注入依赖项,如Google Android Architecture Blueprint for Dagger 2中所示。