Android 列出模块函数,Android Dagger-没有no-args构造函数的模块

博客围绕Android开发中,将没有无参构造函数的模块组合在一起的问题展开。作者有含多个需参数模块的库,在应用中重用时不知如何组合。最后给出解决办法,可将模块实例传递给相关方法,还对一些参数使用给出建议。

如何将没有no-args构造函数的模块组合在一起.我有一个包含多个模块的库,我想在我的应用程序中重用它们.但是,这些模块需要一些参数.以下示例描述了我的设置:

图书馆:

@Module(

library = true

)

public class LibModule1 {

private final String mString;

public LibModule1(String string) {

mString = string;

}

//... provide methods

}

@Module(

library = true,

addsTo = LibraryModule1.class

)

public class LibModule2 {

private final String mString;

public LibModule2(String string) {

mString = string;

}

//... provide methods

}

注意,LibModule2依赖于LibModule1中提供的一些对象.

应用程式:

在我的应用程序中,我将LibModule1和LibModule2中的对象注入到一个类中.但是我不知道如何组合这些模块. include参数不起作用,因为两个模块都没有no-args构造函数. addTo无效,因为我需要两个库模块,但是参数让我们仅设置一个类.创建两个注入我的类MyClass.class的应用程序模块不起作用(一个类只能由一个模块注入,对吗?!).

@Module(

injects = MyClass.class

)

public class AppModule {

}

我该如何解决这个问题?

解决方法:

您完全可以将模块的实时实例传递给ObjectGraph.create()和graph.plus().如果您有状态模块,则应执行以下操作:

ObjectGraph graph =

ObjectGraph.create(new LibraryModule1("foo"), LibraryModule2("bar));

就是说,如果您以这种方式实例化在问题中描述的库模块,它们将在编译时仍然失败,因为除非您彼此包括(或标记为complete-false),否则它们将失败.您可以简单地让LibModule2包含LibModule1,因为您说它具有依赖于后者提供的对象的对象.

@Module(library = true)

public class LibModule1 {

private final String mString;

public LibModule1(String string) {

mString = string;

}

//... provide methods

}

@Module(includes = LibraryModule1.class)

public class LibModule2 {

private final String mString;

public LibModule2(String string) {

mString = string;

}

//... provide methods

}

我建议您在问题中描述的场景中不要使用complete = false,因此您最终不会避免进行图分析.仅在创建可重用的模块时才应使用complete = false,该模块期望图形状态不能直接通过另一个模块包含,因为它将与在编译时身份未知的模块结合在一起.

如果计划在LibModule1的替代方案中使用LibModule2,则只应执行此处的操作.在上述情况下,没有特别的理由不包括LibModule2中的LibModule1.

complete = false模块从所有图分析中排除,因为它们没有断言其完整性.但是,如果给出了包含,则这两个模块都可以完整.但是您必须将这些模块作为实例传递,因为它们没有no-args构造函数.

您应该只使用library = true来指示提供的某些绑定是供其他依赖项使用的,而不是通过graph.get(Foo.class)作为图的入口点获得的.本质上,库= true模块从孤立绑定分析中排除.

标签:dagger,dependency-injection,android

来源: https://codeday.me/bug/20191122/2057459.html

<think>我们讨论的是Android中的静态工厂模式。静态工厂模式是一种创建型设计模式,它通过一个静态方法来创建对象,而不是使用构造函数。这种模式的优势在于:1.可以隐藏对象创建的细节,尤其是当创建过程比较复杂时。2.可以返回不同类型的子类实例(基于不同的条件),提高代码的灵活性。3.可以控制实例的创建,比如实现单例或缓存机制。 在Android中,静态工厂模式常用于创建Fragment(通过newInstance方法传递参数)、创建View对象、或者创建复杂的数据模型等。下面,我们通过一个Android中创建Fragment的典型例子来展示静态工厂模式。###示例:使用静态工厂模式创建Fragment(传递参数)在Android中,Fragment通常需要传递参数。最佳实践是使用静态工厂方法(通常命名为newInstance)来创建Fragment实例,并设置Bundle参数。这样做的原因是可以避免在Fragment的构造函数中传递参数(因为系统在重建Fragment时会调用无参构造函数),并且可以集中管理参数的设置。 ```javapublic classMyFragmentextends Fragment{private staticfinal StringARG_PARAM1 ="param1";privatestatic finalString ARG_PARAM2= "param2";private StringmParam1;privateint mParam2;//私有或无参构造函数(必须提供)public MyFragment(){// Requiredempty publicconstructor}//静态工厂方法public staticMyFragmentnewInstance(String param1,int param2){MyFragmentfragment =new MyFragment();Bundle args= newBundle();args.putString(ARG_PARAM1, param1);args.putInt(ARG_PARAM2,param2);fragment.setArguments(args);return fragment;}@Overridepublic voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() !=null){mParam1 =getArguments().getString(ARG_PARAM1);mParam2 =getArguments().getInt(ARG_PARAM2);}}//...其他代码,如onCreateView等} ```###代码解释1. **静态工厂方法`newInstance`**:-这是一个公共静态方法,用于创建Fragment实例。-方法接收所需的参数(这里是一个String和一个int),然后创建Bundle对象,将参数放入Bundle中。-将Bundle设置为Fragment的参数(通过`setArguments`方法),然后返回Fragment实例。 2. **为什么使用Bundle传递参数?**:-当系统销毁并重建Fragment(例如配置更改)时,它会调用无参构造函数重新创建Fragment,然后自动恢复之前保存的Bundle(即参数)。这样保证了参数不会丢失。3.**在onCreate中获取参数**:-在Fragment的`onCreate`生命周期方法中,我们可以通过`getArguments()`获取Bundle,并从中取出参数。 ###静态工厂模式的其他应用场景1.**创建View**:```javapublicclass CustomView extendsView{//私有构造函数private CustomView(Contextcontext){super(context);//初始化}//静态工厂方法,可以处理不同的属性设置publicstatic CustomView create(Context context, AttributeSet attrs){CustomViewview =new CustomView(context);//处理自定义属性TypedArraya =context.obtainStyledAttributes(attrs, R.styleable.CustomView);//...解析属性a.recycle();returnview;}}```2.**创建复杂对象**:比如一个网络请求的配置对象,需要多个步骤设置参数,使用静态工厂方法可以简化创建过程。###静态工厂模式与构造函数的对比|特性|静态工厂方法|构造函数| |--------------------|----------------------------------|----------------------||方法名|有名字(如newInstance)|只能与类名相同| |返回类型|可以返回子类或接口实现|只能返回当前类| |每次调用是否新对象 |不一定(可控制,如单例)|总是新对象||可读性|更好(方法名可表达含义)|较差| ###注意事项-Android中使用静态工厂方法创建Fragment时,必须保留一个公共的无参构造函数,因为系统在恢复Fragment时会调用它。 -静态工厂方法通常返回的是具体类的实例,但也可以返回接口类型,这样更符合面向接口编程的原则。§§相关问题§§: 1.静态工厂模式和工厂方法模式有什么区别?2.在Android中,除了Fragment,还有哪些地方适合使用静态工厂模式? 3.静态工厂方法如何实现单例模式?4.使用静态工厂方法创建对象与使用依赖注入(如Dagger)相比,各有什么优缺点?</think># Android 静态工厂模式详解 静态工厂模式是一种创建型设计模式,它通过静态方法创建对象,而不是使用构造函数。在Android开发中,这种模式特别有用,因为它可以封装对象创建逻辑,提供更灵活的实例化方式。 ## 静态工厂模式的核心优势 1. **封装创建逻辑**:隐藏对象创建的复杂细节 2. **命名清晰**:静态方法可以有描述性名称 3. **控制实例**:可以返回已有实例或不同子类 4. **避免构造污染**:减少构造函数重载 5. **简化依赖**:集中管理对象创建 ## Android 中静态工厂模式的典型实现 ### 1. 基础静态工厂实现 ```java // 定义产品接口 public interface Shape { void draw(); } // 具体产品类 public class Circle implements Shape { @Override public void draw() { Log.d("Shape", "Drawing Circle"); } } public class Rectangle implements Shape { @Override public void draw() { Log.d("Shape", "Drawing Rectangle"); } } // 静态工厂类 public class ShapeFactory { // 私有构造防止实例化 private ShapeFactory() {} public static Shape createShape(String type) { switch (type) { case "CIRCLE": return new Circle(); case "RECTANGLE": return new Rectangle(); default: throw new IllegalArgumentException("Unknown shape type"); } } } // 在Activity中使用 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Shape circle = ShapeFactory.createShape("CIRCLE"); circle.draw(); // 输出: Drawing Circle } } ``` ### 2. Fragment静态工厂模式(Android最佳实践) ```java public class DetailFragment extends Fragment { private static final String ARG_ITEM_ID = "item_id"; // 私有构造防止外部实例化 private DetailFragment() {} // 静态工厂方法 public static DetailFragment newInstance(String itemId) { DetailFragment fragment = new DetailFragment(); Bundle args = new Bundle(); args.putString(ARG_ITEM_ID, itemId); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { String itemId = getArguments().getString(ARG_ITEM_ID); // 使用itemId } } } // 在Activity中使用 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 使用工厂方法创建Fragment Fragment detailFragment = DetailFragment.newInstance("12345"); getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_container, detailFragment) .commit(); } } ``` ## 静态工厂模式的高级用法 ### 1. 带缓存的静态工厂 ```java public class ImageLoader { private static final Map<String, Bitmap> cache = new HashMap<>(); private ImageLoader() {} public static Bitmap loadImage(Context context, String imageUrl) { // 检查缓存 if (cache.containsKey(imageUrl)) { return cache.get(imageUrl); } // 创建新实例 Bitmap bitmap = loadBitmapFromNetwork(imageUrl); // 伪代码 cache.put(imageUrl, bitmap); return bitmap; } } ``` ### 2. 返回不同子类的静态工厂 ```java public abstract class Dialog { public abstract void show(); } public class InfoDialog extends Dialog { @Override public void show() { // 显示信息对话框 } } public class ErrorDialog extends Dialog { @Override public void show() { // 显示错误对话框 } } public class DialogFactory { public static Dialog createDialog(Context context, DialogType type) { switch (type) { case INFO: return new InfoDialog(context); case ERROR: return new ErrorDialog(context); default: throw new IllegalArgumentException("Unknown dialog type"); } } public enum DialogType { INFO, ERROR } } ``` ## 静态工厂模式 vs 构造函数 | 特性 | 静态工厂方法 | 构造函数 | |------------------|------------------------------|-----------------------| | 命名 | 可以有描述性名称 | 固定与类名相同 | | 实例控制 | 可以返回已有实例或子类 | 总是返回新实例 | | 参数处理 | 可以处理复杂参数逻辑 | 参数直接传递给字段 | | 异常处理 | 可以抛出更具体的异常 | 只能抛出构造异常 | | 可读性 | 更高(方法名表达意图) | 较低 | | Android Fragment | 推荐使用(支持参数传递) | 不推荐(参数丢失风险)| ## Android 中的最佳实践 1. **Fragment创建**:总是使用静态工厂方法传递参数 2. **自定义View**:使用静态工厂处理自定义属性 3. **数据模型**:复杂对象创建使用工厂方法 4. **网络请求**:API客户端创建使用工厂 5. **数据库访问**:DAO对象创建使用工厂 ## 静态工厂模式的局限性 1. 如果类没有公共或受保护构造函数,则不能被继承 2. 在文档中不如构造函数明显 3. 可能增加类的数量(需要额外工厂类)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值