SharePreferences两个提交方法:commit与apply的区别

本文探讨了Android中SharedPreferences的commit和apply两种提交方法的区别。commit()在成功提交时返回true,无返回值时表明失败,且同步将数据写入磁盘;apply()则异步保存,不提供返回值,可能在极端情况下导致数据丢失。考虑到效率,apply()优于commit(),但若需确保数据完整性,推荐使用commit()。

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

1.先说区别:
  • commit()提交成功返回true,apply()提交没有返回值
  • apply()提交失败的时候,不会有任何提示
  • 都会把数据先原子提交(什么是原子提交:就是事务的所有修改动作,要么全部发生,要么一个都不发生)到内存,然后apply()异步提交到磁盘上。而commit()是同步提交到磁盘上。内存存储都是更新Map的值(具体请看下面?源码)。
2.再分析优劣

a.针对效率上来说:apply()要比commit()高效,因为当有多次提交的时候,因为写入磁盘耗时并且commit()是同步写入,如果前一个commit()没有执行完后面的都要等待(因为数据写入的过程中,为了保证数据写入的准确性,会用同步锁保证数据的安全性)
b.但是commit()能保证写入数据的成功性,而apply()只是调用了写入就返回了。如果在一些极端情况下(比如应用重启),apply()就可能造成数据写入失败了,但是我们并不知道失败了的情况。
总 结 \color{red}{总结} :如果对结果要求严格,就使用commit()。如果对结果不做强烈要求,但是更看重性能,那就使用apply()。

下面是相关的源码:

public boolean commit() {
    MemoryCommitResult mcr = commitToMemory();
    SharedPreferencesImpl.this.enqueueDiskWrite(mcr, null /* sync write on this thread okay */);
    try {
        mcr.writtenToDiskLatch.await();
    } catch (InterruptedException e) {
        return false;
    }
    notifyListeners(mcr);
    return mcr.writeToDiskResult;
}

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);
}
private MemoryCommitResult commitToMemory() {
    MemoryCommitResult mcr = new MemoryCommitResult();
    synchronized (SharedPreferencesImpl.this) {
        ...
        synchronized (this) {
            ...
            for (Map.Entry<String, Object> e : mModified.entrySet()) {
                String k = e.getKey();
                Object v = e.getValue();
                if (v == this || v == null) {
                    if (!mMap.containsKey(k)) {
                        continue;
                    }
                    mMap.remove(k);
                } else {
                    if (mMap.containsKey(k)) {
                        Object existingValue = mMap.get(k);
                        if (existingValue != null && existingValue.equals(v)) {
                            continue;
                        }
                    }
                    mMap.put(k, v);
                }
                ...
            }
            mModified.clear();
        }
    }
    return mcr;
}
private void enqueueDiskWrite(final MemoryCommitResult mcr,final Runnable postWriteRunnable) {
    final Runnable writeToDiskRunnable = new Runnable() {
        public void run() {
            synchronized (mWritingToDiskLock) {
                writeToFile(mcr);
            }
            synchronized (SharedPreferencesImpl.this) {
                mDiskWritesInFlight--;
            }
            if (postWriteRunnable != null) {
                postWriteRunnable.run();
            }
        }
    };
    final boolean isFromSyncCommit = (postWriteRunnable == null);
    // Typical #commit() path with fewer allocations, doing a write on
    // the current thread.
    if (isFromSyncCommit) {
        boolean wasEmpty = false;
        synchronized (SharedPreferencesImpl.this) {
            wasEmpty = mDiskWritesInFlight == 1;
        }
        if (wasEmpty) {
            writeToDiskRunnable.run();
            return;
        }
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值