본문 바로가기
Android

[Android] SharedPreference commit()과 apply() 중 어떤 걸 써야할까?

by 너츠너츠 2023. 5. 23.

commit()

  • 이 편집기에서 편집 중인 SharedPreferences Object로 preferences 변경사항을 다시 commit합니다.
  • 요청된 수정 작업이 원자적으로 수행되어 모든 수정 작업을 대체할 수 있습니다.
  • 두 편집자가 동시에 수정할 때 commit을 호출하는 마지막 편집자가 승리합니다.
  • 반환 값이 중요하지 않고 application의 메인 스레드로부터 사용한다면 apply를 대신 사용하는 것이 좋습니다.
  • @return 새 값이 영구 스토리지에 성공적으로 기록된 경우 true를 반환합니다.

소스 코드

@Override
public boolean commit() {
	long startTime = 0;
	if (DEBUG) {
 		startTime = System.currentTimeMillis();
	}
	MemoryCommitResult mcr = commitToMemory();
	SharedPreferencesImpl.this.enqueueDiskWrite(
		mcr, null /* sync write on this thread okay */);
	try {
		mcr.writtenToDiskLatch.await();
	} catch (InterruptedException e) {
 		return false;
	} finally {
		if (DEBUG) {
			Log.d(TAG, mFile.getName() + ":" + mcr.memoryStateGeneration
				+ " committed after " + (System.currentTimeMillis() - startTime)
 				+ " ms");
		}
	}
	notifyListeners(mcr);
 	return mcr.writeToDiskResult;
 }

commit  코드를 보면 호출된 스레드에서 실행되는 것을 확인할 수 있습니다. 

 

apply()

  • apply를 사용하면 편집 중인 SharedPreferences Object로 변경사항을 다시 커밋하며 이 동작이 원자적으로 수행되어 모든 수정 작업을 대체할 수 있습니다.  -> 마지막으로 적용을 호출한 편집이 적용
  • commit은 동기적으로 기록하지만, apply는 메모리 내 변경사항을 즉시 비동기적으로 기록하며, 실패해도 공지X
  • apply가 아직 완료되지 않은 상태에서 다른 Editor에서 commit을 한다면, commit 뿐만 아니라 모든 commit들이 완료될 때까지 commit이 Block됩니다.
  • SharedPreferences 싱글톤이기 때문에 이미 반환값을 무시하고 있었다면 commit 인스턴스를 apply로 바꾸는 것이 안전합니다.
  • Android 컴포넌트 생명주기에 대해 걱정할 필요 없이 상태를 전환하기 전에 완료됩니다.
  • SharedPreferences.Editor 인터페이스는 즉시 시행되지 않습니다.
  • apply() 누락에 대한 에러가 발생하면,  commit()을 호출하면 됩니다.

소스코드

@Override
public void apply() {
    final long startTime = System.currentTimeMillis();
    final MemoryCommitResult mcr = commitToMemory();
    final Runnable awaitCommit = new Runnable() {
        @Override
        public void run() {
            try {
                mcr.writtenToDiskLatch.await();
            } catch (InterruptedException ignored) {
            }
            if (DEBUG && mcr.wasWritten) {
                Log.d(TAG, mFile.getName() + ":" + mcr.memoryStateGeneration
                        + " applied after " + (System.currentTimeMillis() - startTime)
                        + " ms");
            }
        }
    };
    QueuedWork.addFinisher(awaitCommit);
    Runnable postWriteRunnable = new Runnable() {
        @Override
        public void run() {
            awaitCommit.run();
            QueuedWork.removeFinisher(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);
}
반응형

댓글