Try to asynchronize some time-costly tasks

This commit is contained in:
huangyuhui 2017-08-26 10:53:05 +08:00
parent 008f07cacc
commit c775e8368e
12 changed files with 82 additions and 70 deletions

View File

@ -42,15 +42,19 @@ fun i18n(key: String): String {
class Main : Application() {
override fun start(stage: Stage) {
println(System.currentTimeMillis())
// When launcher visibility is set to "hide and reopen" without [Platform.implicitExit] = false,
// Stage.show() cannot work again because JavaFX Toolkit have already shut down.
Platform.setImplicitExit(false)
Controllers.initialize(stage)
println("Showing stage: " + System.currentTimeMillis())
stage.isResizable = false
stage.scene = Controllers.scene
stage.show()
println("Showed stage: " + System.currentTimeMillis())
}
companion object {

View File

@ -23,6 +23,7 @@ import org.jackhuang.hmcl.setting.EnumGameDirectory
import org.jackhuang.hmcl.setting.Profile
import org.jackhuang.hmcl.setting.Settings
import org.jackhuang.hmcl.setting.VersionSetting
import org.jackhuang.hmcl.task.Scheduler
import org.jackhuang.hmcl.util.LOG
import org.jackhuang.hmcl.util.fromJson
import java.io.File
@ -68,7 +69,9 @@ class HMCLGameRepository(val profile: Profile, baseDirectory: File)
return File(Settings.commonPath).resolve("libraries/${lib.path}")
}
@Synchronized
override fun refreshVersionsImpl() {
Scheduler.NEW_THREAD.schedule {
versionSettings.clear()
super.refreshVersionsImpl()
@ -84,14 +87,11 @@ class HMCLGameRepository(val profile: Profile, baseDirectory: File)
} catch (ex: IOException) {
LOG.log(Level.WARNING, "Unable to create launcher_profiles.json, Forge/LiteLoader installer will not work.", ex)
}
}
}
fun changeDirectory(newDir: File) {
baseDirectory = newDir
refreshVersions()
}

View File

@ -47,11 +47,7 @@ class Profile(name: String = "Default", initialGameDir: File = File(".minecraft"
var modManager = ModManager(repository)
init {
gameDirProperty.onChange { newGameDir ->
repository.baseDirectory = newGameDir!!
repository.refreshVersions()
}
gameDirProperty.onChange { repository.changeDirectory(it!!) }
selectedVersionProperty.addListener { _ -> verifySelectedVersion() }
EVENT_BUS.channel<RefreshedVersionsEvent>() += { event -> if (event.source == repository) verifySelectedVersion() }
}

View File

@ -191,7 +191,7 @@ class VersionSetting() {
return null // Custom Java Directory not found,
}
} else if (java.isNotBlank()) {
val c = JavaVersion.JAVAS[java]
val c = JavaVersion.getJREs()[java]
if (c == null) {
java = "Default"
return JavaVersion.fromCurrentEnvironment()

View File

@ -25,14 +25,16 @@ import javafx.scene.layout.Region
import javafx.stage.Stage
import org.jackhuang.hmcl.Main
import org.jackhuang.hmcl.setting.Settings
import org.jackhuang.hmcl.task.task
import org.jackhuang.hmcl.util.JavaVersion
object Controllers {
lateinit var scene: Scene private set
lateinit var stage: Stage private set
val mainPane = MainPage()
val settingsPane = SettingsPage()
val versionPane = VersionPage()
val settingsPane by lazy { SettingsPage() }
val versionPane by lazy { VersionPage() }
lateinit var leftPaneController: LeftPaneController
@ -46,6 +48,7 @@ object Controllers {
leftPaneController = LeftPaneController(decorator.leftPane)
Settings.onProfileLoading()
task { JavaVersion.initialize() }.start()
decorator.isCustomMaximize = false

View File

@ -17,21 +17,38 @@
*/
package org.jackhuang.hmcl.ui
import com.jfoenix.controls.JFXButton
import com.jfoenix.controls.JFXCheckBox
import com.jfoenix.effects.JFXDepthManager
import javafx.fxml.FXML
import javafx.geometry.Pos
import javafx.scene.control.Label
import javafx.scene.layout.BorderPane
import javafx.scene.layout.VBox
import org.jackhuang.hmcl.mod.ModInfo
import org.jackhuang.hmcl.util.onChange
class ModItem(info: ModInfo, private val deleteCallback: (ModItem) -> Unit) : BorderPane() {
@FXML lateinit var lblModFileName: Label
@FXML lateinit var lblModAuthor: Label
@FXML lateinit var chkEnabled: JFXCheckBox
val lblModFileName = Label().apply { style = "-fx-font-size: 15;" }
val lblModAuthor = Label().apply { style = "-fx-font-size: 10;" }
val chkEnabled = JFXCheckBox().apply { BorderPane.setAlignment(this, Pos.CENTER) }
init {
loadFXML("/assets/fxml/version/mod-item.fxml")
left = chkEnabled
center = VBox().apply {
BorderPane.setAlignment(this, Pos.CENTER)
children += lblModFileName
children += lblModAuthor
}
right = JFXButton().apply {
setOnMouseClicked { onDelete() }
styleClass += "toggle-icon4"
BorderPane.setAlignment(this, Pos.CENTER)
graphic = SVG.close("black", 15.0, 15.0)
}
style = "-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"
JFXDepthManager.setDepth(this, 1)

View File

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui
import com.jfoenix.controls.*
import javafx.beans.value.ChangeListener
import javafx.fxml.FXML
import javafx.scene.Node
import javafx.scene.control.Label
import javafx.scene.control.ScrollPane
import javafx.scene.control.Toggle
@ -106,16 +107,22 @@ class VersionSettingsController {
txtMetaspace.setValidators(validator(true))
txtMetaspace.setValidateWhileTextChanged()
javaPane.children.clear()
javaPane.children += createJavaPane(JavaVersion.fromCurrentEnvironment(), javaGroup)
JavaVersion.JAVAS.values.forEach { javaVersion ->
javaPane.children += createJavaPane(javaVersion, javaGroup)
}
javaPane.children += javaPaneCustom
javaPaneCustom.limitHeight(20.0)
radioCustom.toggleGroup = javaGroup
txtJavaDir.disableProperty().bind(radioCustom.selectedProperty().not())
btnJavaSelect.disableProperty().bind(radioCustom.selectedProperty().not())
task {
val list = mutableListOf<Node>()
list += createJavaPane(JavaVersion.fromCurrentEnvironment(), javaGroup)
JavaVersion.getJREs().values.forEach { javaVersion ->
list += createJavaPane(javaVersion, javaGroup)
}
list += javaPaneCustom
it["list"] = list
}.subscribe(Scheduler.JAVAFX) {
javaPane.children.setAll(it.get<List<Node>>("list"))
}
}
private fun createJavaPane(java: JavaVersion, group: ToggleGroup): Pane {

View File

@ -35,7 +35,7 @@ class InstallWizardProvider(val profile: Profile, val gameVersion: String, val v
if (settings.containsKey("optifine"))
ret = ret with profile.dependency.installLibraryAsync(gameVersion, version, "optifine", settings["optifine"] as String)
return ret with task(Scheduler.JAVAFX) { profile.repository.refreshVersions() }
return ret with task { profile.repository.refreshVersions() }
}
override fun createPage(controller: WizardController, step: Int, settings: MutableMap<String, Any>): Node {

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXCheckBox?>
<?import com.jfoenix.controls.JFXButton?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
type="BorderPane">
<left>
<JFXCheckBox fx:id="chkEnabled" BorderPane.alignment="CENTER" />
</left>
<center>
<VBox BorderPane.alignment="CENTER">
<Label fx:id="lblModFileName" style="-fx-font-size: 15;" />
<Label fx:id="lblModAuthor" style="-fx-font-size: 10;" />
</VBox>
</center>
<right>
<JFXButton onMouseClicked="#onDelete" styleClass="toggle-icon4" BorderPane.alignment="CENTER">
<graphic>
<fx:include source="/assets/svg/close-black.fxml"/>
</graphic>
</JFXButton>
</right>
</fx:root>

View File

@ -12,7 +12,7 @@
<JFXSpinner style="-fx-radius:16" styleClass="materialDesign-purple, first-spinner" />
<StackPane fx:id="contentPane">
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true">
<VBox fx:id="modPane" spacing="10" style="-fx-padding: 20;">
<VBox fx:id="modPane" spacing="10" style="-fx-padding: 20 20 70 20;">
</VBox>
</ScrollPane>

View File

@ -140,7 +140,6 @@ open class DefaultGameRepository(var baseDirectory: File): GameRepository {
isLoaded = true
}
@Synchronized
final override fun refreshVersions() {
EVENT_BUS.fireEvent(RefreshingVersionsEvent(this))
refreshVersionsImpl()

View File

@ -18,10 +18,12 @@
package org.jackhuang.hmcl.util
import com.google.gson.annotations.SerializedName
import org.jackhuang.hmcl.game.Version
import java.io.File
import java.io.IOException
import java.io.Serializable
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.regex.Pattern
/**
@ -49,8 +51,6 @@ data class JavaVersion internal constructor(
companion object {
private val regex = Pattern.compile("java version \"(?<version>[1-9]*\\.[1-9]*\\.[0-9]*(.*?))\"")
val JAVAS: Map<String, JavaVersion>
val UNKNOWN: Int = -1
val JAVA_5: Int = 50
val JAVA_6: Int = 60
@ -132,7 +132,22 @@ data class JavaVersion internal constructor(
}
fun fromCurrentEnvironment() = currentJava
init {
private var javas: Map<String, JavaVersion>? = null
private val await = CountDownLatch(1)
/**
* This method will block until [initialize] succeeds.
*/
fun getJREs(): Map<String, JavaVersion> {
if (javas != null) return javas!!
await.await()
return javas!!
}
@Synchronized
fun initialize() {
if (javas != null)
throw IllegalStateException("JavaVersions have already been initialized.")
val temp = mutableMapOf<String, JavaVersion>()
(when (OS.CURRENT_OS) {
OS.WINDOWS -> queryWindows()
@ -141,7 +156,8 @@ data class JavaVersion internal constructor(
}).forEach { javaVersion ->
temp.put(javaVersion.longVersion, javaVersion)
}
JAVAS = temp
javas = temp
await.countDown()
}
private fun queryMacintosh() = LinkedList<JavaVersion>().apply {