diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java index ea3d066bc..f9cceabf7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java @@ -34,6 +34,8 @@ import org.jackhuang.hmcl.auth.NoCharacterException; import org.jackhuang.hmcl.auth.ServerResponseMalformedException; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; +import javafx.beans.binding.ObjectBinding; + public class YggdrasilAccount extends Account { private final YggdrasilService service; @@ -48,6 +50,8 @@ public class YggdrasilAccount extends Account { this.username = requireNonNull(username); this.characterUUID = requireNonNull(session.getSelectedProfile().getId()); this.session = requireNonNull(session); + + addProfilePropertiesListener(); } protected YggdrasilAccount(YggdrasilService service, String username, String password, CharacterSelector selector) throws AuthenticationException { @@ -73,6 +77,17 @@ public class YggdrasilAccount extends Account { characterUUID = session.getSelectedProfile().getId(); authenticated = true; + + addProfilePropertiesListener(); + } + + private ObjectBinding> profilePropertiesBinding; + private void addProfilePropertiesListener() { + // binding() is thread-safe + // hold the binding so that it won't be garbage-collected + profilePropertiesBinding = service.getProfileRepository().binding(characterUUID, true); + // and it's safe to add a listener to an ObjectBinding which does not have any listener attached before (maybe tricky) + profilePropertiesBinding.addListener((a, b, c) -> this.invalidate()); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableCache.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableCache.java index 937d6ca87..e3602b5ad 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableCache.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableCache.java @@ -132,6 +132,14 @@ public class ObservableCache { } public ObjectBinding binding(K key) { + return binding(key, false); + } + + /** + * @param quiet if true, calling get() on the returned binding won't toggle a query + */ + public ObjectBinding binding(K key, boolean quiet) { + // This method is thread-safe because ObservableHelper supports concurrent modification return Bindings.createObjectBinding(() -> { V result; boolean refresh; @@ -144,7 +152,7 @@ public class ObservableCache { refresh = invalidated.containsKey(key); } } - if (refresh) { + if (!quiet && refresh) { query(key, executor); } return result; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableOptionalCache.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableOptionalCache.java index 70ccc2a79..e3bb8da66 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableOptionalCache.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ObservableOptionalCache.java @@ -56,6 +56,10 @@ public class ObservableOptionalCache { return backed.binding(key); } + public ObjectBinding> binding(K key, boolean quiet) { + return backed.binding(key, quiet); + } + public void invalidate(K key) { backed.invalidate(key); }