Cache mapped values and objects

This commit is contained in:
Sergey Solovyev 2017-05-26 22:54:08 +02:00
parent adf764cf13
commit 1ec5714174
4 changed files with 72 additions and 6 deletions

View File

@ -0,0 +1,63 @@
package org.solovyev.android.prefs;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.solovyev.common.text.Mapper;
import java.util.Objects;
import javax.annotation.Nullable;
public final class CachingMapper<T> implements Mapper<T> {
private static class CachedEntry<T> {
@Nullable
private String value;
@Nullable
private T object;
}
@NonNull
private final Mapper<T> mapper;
@Nullable
private CachedEntry<T> cachedEntry = null;
private CachingMapper(@NonNull Mapper<T> mapper) {
this.mapper = mapper;
}
@NonNull
public static <T> Mapper<T> of(@NonNull Mapper<T> mapper) {
if (mapper.getClass().equals(CachingMapper.class)) {
return mapper;
}
return new CachingMapper<>(mapper);
}
@Nullable
@Override
public synchronized T parseValue(@Nullable String value) throws IllegalArgumentException {
if (cachedEntry == null) {
cachedEntry = new CachedEntry<>();
} else if (TextUtils.equals(cachedEntry.value, value)) {
return cachedEntry.object;
}
cachedEntry.value = value;
cachedEntry.object = mapper.parseValue(value);
return cachedEntry.object;
}
@Nullable
@Override
public synchronized String formatValue(@Nullable T object) throws IllegalArgumentException {
if (cachedEntry == null) {
cachedEntry = new CachedEntry<>();
} else if (Objects.equals(cachedEntry.object, object)) {
return cachedEntry.value;
}
cachedEntry.object = object;
cachedEntry.value = mapper.formatValue(object);
return cachedEntry.value;
}
}

View File

@ -43,7 +43,7 @@ public final class StringPreference<T> extends AbstractPreference<T> {
public StringPreference(@Nonnull String key, @Nullable T defaultValue, @Nonnull Mapper<T> mapper) { public StringPreference(@Nonnull String key, @Nullable T defaultValue, @Nonnull Mapper<T> mapper) {
super(key, defaultValue); super(key, defaultValue);
this.mapper = mapper; this.mapper = CachingMapper.of(mapper);
} }
@Nonnull @Nonnull

View File

@ -22,11 +22,12 @@
package org.solovyev.common.text; package org.solovyev.common.text;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class EnumMapper<T extends Enum> implements Mapper<T> { public class EnumMapper<T extends Enum> implements Mapper<T> {
@Nonnull @Nonnull

View File

@ -23,13 +23,15 @@
package org.solovyev.common.text; package org.solovyev.common.text;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.prefs.CachingMapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class NumberMapper<N extends Number> implements Mapper<N> { public class NumberMapper<N extends Number> implements Mapper<N> {
private static final List<Class<? extends Number>> supportedClasses = NumberParser.supportedClasses; private static final List<Class<? extends Number>> supportedClasses = NumberParser.supportedClasses;
@ -38,7 +40,7 @@ public class NumberMapper<N extends Number> implements Mapper<N> {
static { static {
for (Class<? extends Number> supportedClass : supportedClasses) { for (Class<? extends Number> supportedClass : supportedClasses) {
mappers.put(supportedClass, newInstance(supportedClass)); mappers.put(supportedClass, CachingMapper.of(newInstance(supportedClass)));
} }
} }