我在活动中有一段简单的代码……
public class MainActivity extends AppCompatActivity { @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); ValueAnimator valueAnimator = ValueAnimator.offloat(0.0f,1.0f); valueAnimator.setRepeatCount(ValueAnimator.INFINITE); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @OverrIDe public voID onAnimationUpdate(ValueAnimator animation) { } }); valueAnimator.start(); }}
如果活动终止,将会有内存泄漏(Leak Canary证明).
但是,当我将此代码转换为相同的Kotlin代码(使用shift-alt-command-k)时,如下所示
class MainActivity : AppCompatActivity() { overrIDe fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentVIEw(R.layout.activity_main) val valueAnimator = ValueAnimator.offloat(0.0f,1.0f) valueAnimator.repeatCount = ValueAnimator.INFINITE valueAnimator.addUpdateListener { } valueAnimator.start() }}
内存泄漏不再发生.为什么?是因为匿名类对象被转换为Lambda?
解决方法 这两个版本之间的区别非常简单.AnimatorUpdateListener
的Java版本包含对外部类的隐式引用(在您的情况下为MainActivity).因此,如果动画在不再需要活动时继续运行,则侦听器会持续保持对活动的引用,从而防止对其进行垃圾回收.
科特林试图在这里变得更聪明.它看到传递给ValueAnimator
的lambda不引用外部作用域中的任何对象(即MainActivity),因此它创建了一个单独的AnimatorUpdateListener
实例,只要你[重新]启动动画,它就会被重用.并且此实例没有对外部作用域的任何隐式引用.
旁注:如果将对外部作用域中某个对象的引用添加到lambda,Kotlin将生成每次动画重新启动时创建更新侦听器的新实例的代码,这些实例将保持隐式对MainActivity的引用(为了访问您决定在lambda中使用的对象所必需的).
另一方面注意:我强烈建议阅读名为“Kotlin in Action”的书,因为它包含了很多有关Kotlin的有用信息,以及我对Kotlin编译器如何选择是否将隐式引用放入外部范围的解释SAM转换后创建的对象是否来自本书.
总结以上是内存溢出为你收集整理的android – Java中的内存泄漏,但不是Kotlin(相同的代码库)…为什么?全部内容,希望文章能够帮你解决android – Java中的内存泄漏,但不是Kotlin(相同的代码库)…为什么?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)