6

我正在开发一个 Android 应用程序,而我正在编写的方法可能会被调用很多次。在这种方法中,我正在对用户界面进行更新。内存使用和性能对我来说很重要。在我看来,我有 2 个选项可用于更改 UI。

首先是每次都制作新的对象。也就是说:

public void myMethod(){
new View().makeVisible();
}

第二种是将对象声明为全局变量,并在方法中引用。这可能看起来像:

View myView = new View();

public void myMethod(){
myView.makeVisible();
}

显然,如果这个方法只调用了几次,那么任何差异都会很小。但是,如果我可能多次调用这个,并且有很多变量被调用/创建,那么第二种方法会提高性能吗?

4

4 回答 4

4

正如其他答案所表明的那样,重用同一个对象而不是为每个方法调用重复实例化一个新对象将减少您的内存占用并提高垃圾收集的性能。

但我实际上会首先考虑可维护性。重用同一个对象是否会使您的代码更加复杂(并可能引入错误)?在编程时牢记效率是很好的,但要避免过早的优化,这会使您的项目复杂化并减慢开发速度。

如果性能和内存使用一个问题,那么是的,重用相同的内容将使您受益View

final View myView = new View(); //made final because it shouldn't be reassigned

如果您真的想考虑资源,您甚至可以延迟加载对象 - 也就是说,仅在需要时才创建它。但是,我建议使用 GuavaSuppliers.memoize(Supplier)来解决这个问题,而不是手动编码该行为:

final Supplier<View> myViewSupplier = Suppliers.memoize(new Supplier<View>() {
    @Override
    public View get() {
        return new View();
    }
});

...

public void myMethod() {
    View myView = myViewSupplier.get(); //lazy-loads when first called
    myView.makeVisible();
}

不过,对于这种特殊情况,这可能是极端的。

于 2012-06-03T23:33:57.173 回答
1

我不认为应该纯粹根据效率做出决定 - 而是哪个组合更能代表您尝试建模的领域。要问的问题是“哪个是使用 View 的班级的正确结构?”。

使用实例变量不是全局变量——它包含在声明它的对象的上下文中。尽管公共静态变量非常接近,但全局变量不应该存在于 OO 中。

首先要决定的是您的“视图”实例在逻辑上属于相对于使用它的类/方法的意图。如果使用它的类是某种工厂,并且“myMethod”是工厂方法,那么是返回一个新实例。

如果“视图”是您类的一个逻辑字段,并且以某种方式有助于捕获和增强其状态和行为,那么没有理由每次都创建一个新字段。只需保持其状态,并使用现有对象。

根据您的描述,您似乎正在尝试维护和更新某种视图的状态。将其更改为所需状态并重新显示它是有意义的,而不是每次都创建一个新对象。由于在功能上这两种方法似乎都适用于您的场景,我会采用第二种选择并避免创建不必要的对象。

于 2012-06-03T23:54:50.517 回答
0

全局变量更有效。

创建新对象会占用更多内存,因为每次创建视图并替换旧视图时,旧视图都必须进行垃圾收集。使用全局变量重用相同的视图可以节省系统创建新对象和收集旧对象的任务。

编辑:全局变量只是对对象的引用,而不是对象本身。

于 2012-06-03T22:59:45.607 回答
0

好吧,当您让每个构造函数都创建一个新实例时,本质上您正在再次执行并非绝对必要的工作。如果我站在你的立场上,我会选择全局变量,然后清除视图,并尽可能在同一个对象上重绘。这可以防止使用其他方法重复内存释放和分配的可能性,因此除非您认为清除特别昂贵 - 足以使其值得不断分配新视图,然后擦除它。

重用同一对象的另一个动机是 java 虚拟机实现在垃圾回收的使用上有所不同,因为一旦变量超出范围,它就不能被访问——当对应于 JVM 的内存被释放时并不总是相同. 您可能会发现,在另一种情况下,您可以在实例中按顺序分配许多视图,但直到进程空闲一段时间后才会全部释放,从而有效地使应用程序完全像您不想要的那样占用内存。

于 2012-06-03T23:00:40.643 回答