关于Android SharedPreferences中apply方法源码(awaitCommit )的一点分析

本文深入分析了SharedPreferencesImpl中的apply方法,特别聚焦于awaitCommit Runnable的作用。通过解释CountDownLatch的使用方式,阐述了如何确保在Activity销毁前将SharedPreferences的所有更改写入磁盘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SharedPreferencesImpl.java (建议大家先找一篇系统介绍这个SharedPreferencesImpl源码的博客看一下)

apply方法源码:

     

        public void apply() {
            final MemoryCommitResult mcr = commitToMemory();
            final Runnable awaitCommit = new Runnable() {
                    public void run() {
                        try {
                            mcr.writtenToDiskLatch.await();
                        } catch (InterruptedException ignored) {
                        }
                    }
                };

            QueuedWork.add(awaitCommit);

            Runnable postWriteRunnable = new Runnable() {
                    public void run() {
                        awaitCommit.run();
                        QueuedWork.remove(awaitCommit);
                    }
                };

            SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);

            // Okay to notify the listeners before it's hit disk
            // because the listeners should always get the same
            // SharedPreferences instance back, which has the
            // changes reflected in memory.
            notifyListeners(mcr);
        }

     这里只分析一点:awaitCommit 这个Runnable是干啥用的

     run方法只有一句:mcr.writtenToDiskLatch,mcr是MemoryCommitResult类型的变量,源码如下:

     

  // Return value from EditorImpl#commitToMemory()
    private static class MemoryCommitResult {
        public boolean changesMade;  // any keys different?
        public List<String> keysModified;  // may be null
        public Set<OnSharedPreferenceChangeListener> listeners;  // may be null
        public Map<?, ?> mapToWriteToDisk;
        public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
        public volatile boolean writeToDiskResult = false;

        public void setDiskWriteResult(boolean result) {
            writeToDiskResult = result;
            writtenToDiskLatch.countDown();
        }
    }

     首先明确的是writtenToDiskLatch是一个CountDownLatch,java里的一种锁,此处初始化参数为1,即writtenToDiskLatch = new CountDownLatch(1),当调用它的countDown()方法减至0时,则释放这个锁,从await方法处继续调用,注意MemroyCommitResult这个类的setDiskWriteResult方法是唯一调用countDown()的方法。注意,setDiskWriteResult方法会在执行写入磁盘逻辑后执行(无论写入成功还是失败,都会执行)。

         先说结论:awaitCommit是用来防止多次apply,然后该activity调用onStop方法时(activity将要销毁时),用来保证每一次apply都能够最终执行将sharedpreferences写入磁盘的逻辑(无论写入成功还是失败,一定保证它执行一次)。

         代码倒着看,ActivityThread.java类中handleStopActivity方法中有一句代码:QueuedWork.waitToFinish();

    public static void waitToFinish() {
        Runnable toFinish;
        while ((toFinish = sPendingWorkFinishers.poll()) != null) {
            toFinish.run();
        }
    }
      如果,队列中还处理的toFinish(说明调用了apply方法,我们暂不去关注commit方法,并且sharedpreferences还未写完磁盘),则调用toFinish.run,toFinish是哪里来的呢?答案在apply方法中的QueuedWork.add(awaitCommit);

      此时,mcr.writtenToDiskLatch.await();线程阻塞,阻止了handleStopActivity方法继续执行,等到所有写磁盘过程结束,调用setDiskWriteResult,handleStopActivity方法继续执行,最终Activity销毁。

      一句话概括:awaitCommit这个Runnable就是为了保证在Activity销毁之前,把所有的SharedPreferences的改动写入磁盘。


          



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值