Optimize app startup speed
This commit is contained in:
parent
bc901558ef
commit
757444c6b4
|
@ -95,5 +95,11 @@ class AnimUtil {
|
|||
this.interpolator = interpolator
|
||||
return this
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun ObjectAnimator.startAfter(delayTime: Long) {
|
||||
this.startDelay = delayTime
|
||||
this.start()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.mio.util
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.util.Printer
|
||||
|
||||
class PerfUtil : Printer {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun install() {
|
||||
Looper.getMainLooper().setMessageLogging(PerfUtil())
|
||||
}
|
||||
}
|
||||
|
||||
private val sampler = StackSampler(300)
|
||||
private var isStarted = false
|
||||
private var startTime = 0L
|
||||
|
||||
override fun println(x: String?) {
|
||||
if (!isStarted) {
|
||||
isStarted = true
|
||||
startTime = System.currentTimeMillis()
|
||||
sampler.startDump()
|
||||
} else {
|
||||
isStarted = false
|
||||
val endTime = System.currentTimeMillis()
|
||||
if (endTime - startTime > 300) {
|
||||
Log.e("FCL PerfUtil", "block time = ${endTime - startTime}")
|
||||
}
|
||||
sampler.stopDump()
|
||||
}
|
||||
}
|
||||
|
||||
inner class StackSampler(val interval: Long) {
|
||||
private val handler: Handler
|
||||
private val runnable = Runnable {
|
||||
val sb = StringBuilder()
|
||||
Looper.getMainLooper().thread.stackTrace.forEach {
|
||||
sb.append(it.toString())
|
||||
sb.append("\n")
|
||||
}
|
||||
Log.e("FCL PerfUtil", sb.toString())
|
||||
}
|
||||
|
||||
init {
|
||||
val handlerThread = HandlerThread("")
|
||||
handlerThread.start()
|
||||
handler = Handler(handlerThread.looper)
|
||||
}
|
||||
|
||||
fun startDump() {
|
||||
handler.postDelayed(runnable, interval)
|
||||
}
|
||||
|
||||
fun stopDump() {
|
||||
handler.removeCallbacks(runnable)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ import android.os.StrictMode;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mio.util.PerfUtil;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class FCLApplication extends Application implements Application.ActivityLifecycleCallbacks {
|
||||
|
@ -18,6 +20,7 @@ public class FCLApplication extends Application implements Application.ActivityL
|
|||
// enabledStrictMode();
|
||||
super.onCreate();
|
||||
this.registerActivityLifecycleCallbacks(this);
|
||||
PerfUtil.install();
|
||||
}
|
||||
|
||||
public static Activity getCurrentActivity() {
|
||||
|
|
|
@ -9,10 +9,14 @@ import android.os.Bundle
|
|||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.BounceInterpolator
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.forEach
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.mio.util.AnimUtil
|
||||
import com.mio.util.AnimUtil.Companion.interpolator
|
||||
import com.mio.util.AnimUtil.Companion.startAfter
|
||||
import com.tungsten.fcl.R
|
||||
import com.tungsten.fcl.databinding.ActivityMainBinding
|
||||
import com.tungsten.fcl.game.JarExecutorHelper
|
||||
|
@ -246,6 +250,11 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener {
|
|||
_uiManager?.onResume()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
playAnim()
|
||||
}
|
||||
|
||||
override fun onSelect(view: FCLMenuView) {
|
||||
refreshMenuView(view)
|
||||
bind.apply {
|
||||
|
@ -394,6 +403,7 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener {
|
|||
version
|
||||
)
|
||||
) {
|
||||
Schedulers.defaultScheduler().execute {
|
||||
val game = Profiles.getSelectedProfile().repository.getGameVersion(version)
|
||||
.orElse(getString(R.string.message_unknown))
|
||||
val libraries = StringBuilder(game)
|
||||
|
@ -422,6 +432,7 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener {
|
|||
)
|
||||
}
|
||||
}
|
||||
Schedulers.androidUIThread().execute {
|
||||
bind.versionName.text = version
|
||||
bind.versionHint.text = libraries.toString()
|
||||
bind.icon.setBackgroundDrawable(
|
||||
|
@ -429,6 +440,8 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener {
|
|||
version
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bind.versionName.text = getString(R.string.version_no_version)
|
||||
bind.versionHint.text = getString(R.string.version_manage)
|
||||
|
@ -454,4 +467,21 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun playAnim() {
|
||||
bind.apply {
|
||||
AnimUtil.playTranslationX(
|
||||
leftMenu,
|
||||
ThemeEngine.getInstance().getTheme().animationSpeed * 30L,
|
||||
-100f,
|
||||
0f
|
||||
).interpolator(BounceInterpolator()).start()
|
||||
AnimUtil.playTranslationX(
|
||||
rightMenu,
|
||||
ThemeEngine.getInstance().getTheme().animationSpeed * 30L,
|
||||
100f,
|
||||
0f
|
||||
).interpolator(BounceInterpolator()).start()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,9 +41,6 @@ public class SplashActivity extends FCLActivity {
|
|||
|
||||
public ConstraintLayout background;
|
||||
|
||||
private EulaFragment eulaFragment;
|
||||
private RuntimeFragment runtimeFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -103,21 +100,15 @@ public class SplashActivity extends FCLActivity {
|
|||
FCLPath.loadPaths(this);
|
||||
transFile();
|
||||
Logging.start(Paths.get(FCLPath.LOG_DIR));
|
||||
initFragments();
|
||||
start();
|
||||
}
|
||||
|
||||
private void initFragments() {
|
||||
eulaFragment = new EulaFragment();
|
||||
runtimeFragment = new RuntimeFragment();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
SharedPreferences sharedPreferences = getSharedPreferences("launcher", MODE_PRIVATE);
|
||||
if (sharedPreferences.getBoolean("isFirstLaunch", true)) {
|
||||
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, eulaFragment).commit();
|
||||
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, EulaFragment.class, null).commit();
|
||||
} else {
|
||||
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, runtimeFragment).commit();
|
||||
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, RuntimeFragment.class, null).commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.tungsten.fcl.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
@ -12,11 +11,9 @@ import com.tungsten.fcl.activity.SplashActivity
|
|||
import com.tungsten.fcl.databinding.FragmentRuntimeBinding
|
||||
import com.tungsten.fcl.util.RuntimeUtils
|
||||
import com.tungsten.fclauncher.utils.FCLPath
|
||||
import com.tungsten.fclcore.task.Schedulers
|
||||
import com.tungsten.fclcore.util.io.FileUtils
|
||||
import com.tungsten.fcllibrary.component.FCLFragment
|
||||
import com.tungsten.fcllibrary.component.view.FCLButton
|
||||
import com.tungsten.fcllibrary.component.view.FCLImageView
|
||||
import com.tungsten.fcllibrary.component.view.FCLProgressBar
|
||||
import com.tungsten.fcllibrary.util.LocaleUtils
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
@ -41,10 +38,12 @@ class RuntimeFragment : FCLFragment(), View.OnClickListener {
|
|||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_runtime, container, false)
|
||||
bind = FragmentRuntimeBinding.bind(view)
|
||||
bind.install.setOnClickListener(this)
|
||||
Schedulers.defaultScheduler().execute {
|
||||
initState()
|
||||
refreshDrawables()
|
||||
check()
|
||||
bind.install.setOnClickListener(this)
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.tungsten.fcl.setting;
|
|||
|
||||
import com.tungsten.fcl.game.FCLCacheRepository;
|
||||
import com.tungsten.fclauncher.utils.FCLPath;
|
||||
import com.tungsten.fclcore.task.Schedulers;
|
||||
import com.tungsten.fclcore.util.CacheRepository;
|
||||
|
||||
public final class Settings {
|
||||
|
@ -43,7 +44,7 @@ public final class Settings {
|
|||
DownloadProviders.init();
|
||||
Accounts.init();
|
||||
Profiles.init();
|
||||
Controllers.init();
|
||||
Schedulers.defaultScheduler().execute(Controllers::init);
|
||||
AuthlibInjectorServers.init();
|
||||
|
||||
CacheRepository.setInstance(FCLCacheRepository.REPOSITORY);
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
package com.tungsten.fcl.ui;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.tungsten.fcl.R;
|
||||
import com.tungsten.fcl.ui.account.AccountUI;
|
||||
import com.tungsten.fcl.ui.controller.ControllerUI;
|
||||
import com.tungsten.fcl.ui.download.DownloadUI;
|
||||
import com.tungsten.fcl.ui.manage.ManageUI;
|
||||
import com.tungsten.fcl.ui.main.MainUI;
|
||||
import com.tungsten.fcl.ui.multiplayer.MultiplayerUI;
|
||||
import com.tungsten.fcl.ui.setting.SettingUI;
|
||||
import com.tungsten.fcl.ui.version.VersionUI;
|
||||
import com.tungsten.fclcore.util.Logging;
|
||||
import com.tungsten.fcllibrary.component.ui.FCLBaseUI;
|
||||
import com.tungsten.fcllibrary.component.ui.FCLCommonUI;
|
||||
import com.tungsten.fcllibrary.component.view.FCLUILayout;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class UIManager {
|
||||
|
||||
private static UIManager instance;
|
||||
|
||||
public static UIManager getInstance() {
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException("UIManager not initialized!");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
private final FCLUILayout parent;
|
||||
|
||||
private MainUI mainUI;
|
||||
private AccountUI accountUI;
|
||||
private VersionUI versionUI;
|
||||
private ManageUI manageUI;
|
||||
private DownloadUI downloadUI;
|
||||
private ControllerUI controllerUI;
|
||||
private MultiplayerUI multiplayerUI;
|
||||
private SettingUI settingUI;
|
||||
|
||||
private FCLBaseUI[] allUIs;
|
||||
private FCLBaseUI currentUI;
|
||||
|
||||
private int loadedUI = 0;
|
||||
|
||||
public UIManager(Context context, FCLUILayout parent) {
|
||||
this.context = context;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void init(UIListener listener) {
|
||||
if (instance != null) {
|
||||
Logging.LOG.log(Level.WARNING, "UIManager already initialized!");
|
||||
return;
|
||||
}
|
||||
instance = this;
|
||||
|
||||
mainUI = new MainUI(context, parent, R.layout.ui_main);
|
||||
accountUI = new AccountUI(context, parent, R.layout.ui_account);
|
||||
versionUI = new VersionUI(context, parent, R.layout.ui_version);
|
||||
manageUI = new ManageUI(context, parent, R.layout.ui_manage);
|
||||
downloadUI = new DownloadUI(context, parent, R.layout.ui_download);
|
||||
controllerUI = new ControllerUI(context, parent, R.layout.ui_controller);
|
||||
multiplayerUI = new MultiplayerUI(context, parent, R.layout.ui_multiplayer);
|
||||
settingUI = new SettingUI(context, parent, R.layout.ui_setting);
|
||||
|
||||
allUIs = new FCLBaseUI[] {
|
||||
mainUI,
|
||||
accountUI,
|
||||
versionUI,
|
||||
manageUI,
|
||||
downloadUI,
|
||||
controllerUI,
|
||||
multiplayerUI,
|
||||
settingUI
|
||||
};
|
||||
|
||||
for (FCLBaseUI ui : allUIs) {
|
||||
((FCLCommonUI) ui).addLoadingCallback(() -> {
|
||||
loadedUI++;
|
||||
if (loadedUI == allUIs.length) {
|
||||
listener.onLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public FCLUILayout getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public MainUI getMainUI() {
|
||||
return mainUI;
|
||||
}
|
||||
|
||||
public AccountUI getAccountUI() {
|
||||
return accountUI;
|
||||
}
|
||||
|
||||
public VersionUI getVersionUI() {
|
||||
return versionUI;
|
||||
}
|
||||
|
||||
public ManageUI getManageUI() {
|
||||
return manageUI;
|
||||
}
|
||||
|
||||
public DownloadUI getDownloadUI() {
|
||||
return downloadUI;
|
||||
}
|
||||
|
||||
public ControllerUI getControllerUI() {
|
||||
return controllerUI;
|
||||
}
|
||||
|
||||
public MultiplayerUI getMultiplayerUI() {
|
||||
return multiplayerUI;
|
||||
}
|
||||
|
||||
public SettingUI getSettingUI() {
|
||||
return settingUI;
|
||||
}
|
||||
|
||||
public FCLBaseUI getCurrentUI() {
|
||||
return currentUI;
|
||||
}
|
||||
|
||||
public void switchUI(FCLBaseUI ui) {
|
||||
for (FCLBaseUI baseUI : allUIs) {
|
||||
if (ui == baseUI) {
|
||||
if (currentUI != null) {
|
||||
currentUI.onStop();
|
||||
}
|
||||
ui.onStart();
|
||||
currentUI = ui;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerDefaultBackEvent(Runnable runnable) {
|
||||
FCLBaseUI.setDefaultBackEvent(runnable);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
if (currentUI != null) {
|
||||
currentUI.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
for (FCLBaseUI baseUI : allUIs) {
|
||||
baseUI.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
for (FCLBaseUI baseUI : allUIs) {
|
||||
baseUI.onResume();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.tungsten.fcl.ui
|
||||
|
||||
import android.content.Context
|
||||
import com.tungsten.fcl.R
|
||||
import com.tungsten.fcl.ui.account.AccountUI
|
||||
import com.tungsten.fcl.ui.controller.ControllerUI
|
||||
import com.tungsten.fcl.ui.download.DownloadUI
|
||||
import com.tungsten.fcl.ui.main.MainUI
|
||||
import com.tungsten.fcl.ui.manage.ManageUI
|
||||
import com.tungsten.fcl.ui.multiplayer.MultiplayerUI
|
||||
import com.tungsten.fcl.ui.setting.SettingUI
|
||||
import com.tungsten.fcl.ui.version.VersionUI
|
||||
import com.tungsten.fclcore.util.Logging
|
||||
import com.tungsten.fcllibrary.component.ui.FCLBaseUI
|
||||
import com.tungsten.fcllibrary.component.ui.FCLCommonUI
|
||||
import com.tungsten.fcllibrary.component.view.FCLUILayout
|
||||
import java.util.logging.Level
|
||||
|
||||
class UIManager(val context: Context, val parent: FCLUILayout) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
lateinit var instance: UIManager
|
||||
}
|
||||
|
||||
private var initialized = false
|
||||
lateinit var mainUI: MainUI
|
||||
val accountUI: AccountUI by lazy { AccountUI(context, parent, R.layout.ui_account) }
|
||||
val versionUI: VersionUI by lazy { VersionUI(context, parent, R.layout.ui_version) }
|
||||
val manageUI: ManageUI by lazy { ManageUI(context, parent, R.layout.ui_manage) }
|
||||
val downloadUI: DownloadUI by lazy { DownloadUI(context, parent, R.layout.ui_download) }
|
||||
val controllerUI: ControllerUI by lazy { ControllerUI(context, parent, R.layout.ui_controller) }
|
||||
val multiplayerUI: MultiplayerUI by lazy {
|
||||
MultiplayerUI(
|
||||
context,
|
||||
parent,
|
||||
R.layout.ui_multiplayer
|
||||
)
|
||||
}
|
||||
val settingUI: SettingUI by lazy { SettingUI(context, parent, R.layout.ui_setting) }
|
||||
|
||||
private val allUIList = mutableListOf<FCLBaseUI>()
|
||||
var currentUI: FCLBaseUI? = null
|
||||
|
||||
fun init(listener: UIListener) {
|
||||
if (initialized) {
|
||||
Logging.LOG.log(Level.WARNING, "UIManager already initialized!")
|
||||
return
|
||||
}
|
||||
instance = this
|
||||
mainUI = MainUI(context, parent, R.layout.ui_main)
|
||||
allUIList.add(mainUI)
|
||||
mainUI.addLoadingCallback {
|
||||
listener.onLoad()
|
||||
}
|
||||
}
|
||||
|
||||
fun switchUI(ui: FCLCommonUI) {
|
||||
var isFirstAdd = false
|
||||
if (!allUIList.contains(ui)) {
|
||||
isFirstAdd = true
|
||||
allUIList.add(ui)
|
||||
}
|
||||
for (baseUI in allUIList) {
|
||||
if (ui === baseUI) {
|
||||
currentUI?.onStop()
|
||||
if (isFirstAdd) {
|
||||
ui.addLoadingCallback {
|
||||
ui.onStart()
|
||||
}
|
||||
} else {
|
||||
ui.onStart()
|
||||
}
|
||||
currentUI = ui
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun registerDefaultBackEvent(runnable: Runnable?) {
|
||||
FCLBaseUI.setDefaultBackEvent(runnable)
|
||||
}
|
||||
|
||||
fun onBackPressed() {
|
||||
currentUI?.onBackPressed()
|
||||
}
|
||||
|
||||
fun onPause() {
|
||||
for (baseUI in allUIList) {
|
||||
baseUI.onPause()
|
||||
}
|
||||
}
|
||||
|
||||
fun onResume() {
|
||||
for (baseUI in allUIList) {
|
||||
baseUI.onResume()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -68,6 +68,9 @@ public class ManageUI extends FCLMultiPageUI implements TabLayout.OnTabSelectedL
|
|||
return;
|
||||
}
|
||||
|
||||
if (pageManager == null) {
|
||||
pageManager = new ManagePageManager(getContext(), container, ManagePageManager.PAGE_ID_MANAGE_MANAGE, null);
|
||||
}
|
||||
loadVersion(getVersion(), getProfile());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue