Season5 ep3 主要介绍了Android中使用多线程可能导致的风险——内存泄漏
link


Memory Contention Problems

内存问题的产生,是由于两个线程操作了同一块内存,由于两者执行的先后顺序未知,导致运行结果不可预测。

用光头哥的话说(给光头哥的幽默感点赞)

Memory contention problems with read-write access order, ABA problems, rips in the fabric of space-time…

怎样解决上述问题呢?加锁是一个通用的方法——不过这一点要是扩展起来讲,可说来话长了。


Memory Problems in Android

记住一点:Android中的UI对象不!是!线!程!安!全!的!(not thread-safe)!所有UI对象的生命周期都在UI线程里进行,在其它线程中维护的UI对象引用,很可能正处于一个invalid的状态。

譬如,在Worker Thread中持有一个View的引用,而这个引用实际上已经在UI Thread中结束了它的生命周期,从view hierarchy里面被移除掉了。然而,Worker Thread却傻傻地对此一无所知,接下来对这个View的一切操作都将是徒劳。


Don’t Keep Activity References

Worker Thread中是不应该持有Activity引用的,这会导致Activity无法正常回收,进而产生内存泄漏。在Android中,当我们不可避免地用到多线程时,这个问题的风险被放大了。当在Worker Thread中持有Activity引用时,除非Worker Thread完成运算(通常这是一项非常耗时的操作),否则Activity的实例不会真正被释放。


Implicit Reference of Activity

除了上文提到的显式引用(explicit reference),还应该当心内部类导致的隐式引用(implicit reference)。Android为我们提供了解决方案——WeakReference & static 关键字。

上述场景是可能导致应用程序crash的一个原因——AsyncTask持有一个Activity的引用,而这个Activity实际上已经处于invalid状态时(例如,执行过onDestroy()),AsyncTask却对此一无所知,当AsyncTask执行完它所运行的任务,试图操作Activity的界面时,这个Activity实际上并不可用。这就导致了下面的糟糕场景——


Don’t Hold References

不要试图在UI线程外保存任何UI元素的引用!!!


How We Do?

我们要遵守的唯一准则是:所有UI操作,都在UI线程里进行。

Worker Thread可以通过callback、intent等任意进程间通信方法来告诉UI线程——我需要你帮我变更一下界面。


Tool in Android Studio 2.0

如果你想更深入地了解运行时Thread&Memory的情况,请使用Android Studio 2.0中提供的有力工具。


===Ending===