Replace Properties with InvocationDispatcher & Make config saving async

This commit is contained in:
yushijinhun
2018-09-22 14:04:05 +08:00
parent fa38c53915
commit 4a0831a155
6 changed files with 77 additions and 86 deletions

View File

@@ -17,6 +17,7 @@
*/
package org.jackhuang.hmcl.task;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.beans.property.ReadOnlyStringProperty;
@@ -26,12 +27,10 @@ import org.jackhuang.hmcl.util.*;
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
import org.jackhuang.hmcl.util.javafx.Properties;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.logging.Level;
@@ -176,8 +175,8 @@ public abstract class Task {
}
private long lastTime = Long.MIN_VALUE;
private final AtomicReference<Double> progressUpdate = new AtomicReference<>();
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper(this, "progress", -1);
private final InvocationDispatcher<Double> progressUpdate = InvocationDispatcher.runOn(Platform::runLater, progress::set);
public ReadOnlyDoubleProperty progressProperty() {
return progress.getReadOnlyProperty();
@@ -198,18 +197,18 @@ public abstract class Task {
}
protected void updateProgressImmediately(double progress) {
Properties.updateAsync(this.progress, progress, progressUpdate);
progressUpdate.accept(progress);
}
private final AtomicReference<String> messageUpdate = new AtomicReference<>();
private final ReadOnlyStringWrapper message = new ReadOnlyStringWrapper(this, "message", null);
private final InvocationDispatcher<String> messageUpdate = InvocationDispatcher.runOn(Platform::runLater, message::set);
public final ReadOnlyStringProperty messageProperty() {
return message.getReadOnlyProperty();
}
protected final void updateMessage(String newMessage) {
Properties.updateAsync(message, newMessage, messageUpdate);
messageUpdate.accept(newMessage);
}
public final void run() throws Exception {

View File

@@ -17,10 +17,6 @@
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.task.Schedulers;
import java.awt.*;
import java.util.function.Consumer;
/**
* Constants.
*
@@ -34,20 +30,4 @@ public final class Constants {
public static final String DEFAULT_LIBRARY_URL = "https://libraries.minecraft.net/";
public static final String DEFAULT_VERSION_DOWNLOAD_URL = "https://s3.amazonaws.com/Minecraft.Download/versions/";
public static final String DEFAULT_INDEX_URL = "https://s3.amazonaws.com/Minecraft.Download/indexes/";
public static Consumer<Runnable> UI_THREAD_SCHEDULER = s -> Schedulers.computation().schedule(s::run);
public static final Consumer<Runnable> SWING_UI_THREAD_SCHEDULER = s -> {
if (EventQueue.isDispatchThread())
s.run();
else
EventQueue.invokeLater(s);
};
public static final Consumer<Runnable> JAVAFX_UI_THREAD_SCHEDULER = s -> {
if (javafx.application.Platform.isFxApplicationThread())
s.run();
else
javafx.application.Platform.runLater(s);
};
}

View File

@@ -0,0 +1,55 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* When {@link #accept(ARG)} is called, this class invokes the handler on another thread.
* If {@link #accept(ARG)} is called more than one time before the handler starts processing,
* the handler will only be invoked once, taking the latest argument as its input.
*
* @author yushijinhun
*/
public class InvocationDispatcher<ARG> implements Consumer<ARG> {
public static <ARG> InvocationDispatcher<ARG> runOn(Consumer<Runnable> executor, Consumer<ARG> action) {
return new InvocationDispatcher<>(arg -> executor.accept(() -> {
action.accept(arg.get());
}));
}
private Consumer<Supplier<ARG>> handler;
private AtomicReference<Optional<ARG>> pendingArg = new AtomicReference<>();
public InvocationDispatcher(Consumer<Supplier<ARG>> handler) {
this.handler = handler;
}
@Override
public void accept(ARG arg) {
if (pendingArg.getAndSet(Optional.ofNullable(arg)) == null) {
handler.accept(() -> pendingArg.getAndSet(null).orElse(null));
}
}
}

View File

@@ -1,40 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.javafx;
import javafx.beans.property.Property;
import java.util.concurrent.atomic.AtomicReference;
import org.jackhuang.hmcl.util.Constants;
/**
*
* @author huangyuhui
*/
public final class Properties {
private Properties() {
}
public static <T> void updateAsync(Property<? super T> property, T newValue, AtomicReference<T> update) {
if (update.getAndSet(newValue) == null)
Constants.UI_THREAD_SCHEDULER.accept(() ->
property.setValue(update.getAndSet(null)));
}
}