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

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);
}

你可能感兴趣的:(android,Android高阶)