diff --git a/blogs/Android/Handler 消息机制.md b/blogs/Android/Handler 消息机制.md index a351c99..2b79d27 100644 --- a/blogs/Android/Handler 消息机制.md +++ b/blogs/Android/Handler 消息机制.md @@ -477,6 +477,53 @@ MessageQueue 有两个重要方法,一个是 enqueueMessage 用于存消息, 这里,推荐一个说法:[https://www.zhihu.com/question/34652589/answer/90344494](https://www.zhihu.com/question/34652589/answer/90344494) +4. Handler 如何避免内存泄漏 + + Handler 允许我们发送延时消息,如果在延时期间用户关闭了 Activity,那么该 Activity 泄漏。这是因为内部类默认持有外部类的引用。 + + 解决办法就是:将 Handler 定义为静态内部类的形式,在内部持有 Activity 的弱引用,并及时移除所有消息。 + + ```java + public class MainActivity extends AppCompatActivity { + + private MyHandler mMyHandler = new MyHandler(this); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + private void handleMessage(Message msg) { + + } + + static class MyHandler extends Handler { + private WeakReference mReference; + + MyHandler(Activity reference) { + mReference = new WeakReference<>(reference); + } + + @Override + public void handleMessage(Message msg) { + MainActivity activity = (MainActivity) mReference.get(); + if (activity != null) { + activity.handleMessage(msg); + } + } + } + + @Override + protected void onDestroy() { + mMyHandler.removeCallbacksAndMessages(null); + super.onDestroy(); + } + } + ``` + + + #### 总结 一张图说明一切: @@ -491,3 +538,5 @@ MessageQueue 有两个重要方法,一个是 enqueueMessage 用于存消息, Android SDK 26 源码。 +[Handler 都没搞懂,拿什么去跳槽啊?]() + diff --git a/blogs/Android/SharedPreferences.md b/blogs/Android/SharedPreferences.md index 864e0bb..8fbdb2c 100644 --- a/blogs/Android/SharedPreferences.md +++ b/blogs/Android/SharedPreferences.md @@ -84,6 +84,8 @@ private static ArrayMap> sSharedPr sSharedPrefsCache 是一个 ArrayMap,它存储的是包名和 packagePrefs 的映射关系,而 packagePrefs 存储的是 SharedPreferences 文件与 SharedPreferences 实例对象之间的映射关系。 +这里为什么要把 packageName 作为 key 呢?那是因为一个进程可以有多个应用程序,所以需要用包名来区分它们,在这里感谢 @水晶虾饺 的指正和淳淳教诲。 + 这里,可以稍微总结一下,sSharedPrefsCache 会保存加载到内存中的 SharedPreferences 对象,当用户需要获取 SP 对象的时候,首先会在 sSharedPrefsCache 中查找,如果没找到,就创建一个新的 SP 对象添加到 sSharedPrefsCache 中,并且以当前应用的包名为 key。 除此之外,需要注意的是,ContextImpl 类中并没有定义将 SharedPreferences 对象移除 sSharedPrefsCache 的方法,所以一旦加载到内存中,就会存在直至进程销毁。相对的,也就是说,SP 对象一旦加载到内存,后面任何时间使用,都是从内存中获取,不会再出现读取磁盘的情况。