You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免切换应用时我的CN1应用重启并保留运行状态?

问题:Codename One应用切出后台后返回,重新启动闪屏无法恢复原界面

我需要让应用在失去焦点后再次返回时,从之前中断的位置继续运行。但目前每次切出再切回应用,都会重新执行闪屏动画,回到初始界面。这个问题在真机和模拟器上都会出现。

主类代码

public class TarifaTaxiPredictivo extends Lifecycle {

    private Usuario iU;

    @Override
    public void runApp() {
        String sIdioma = L10NManager.getInstance().getLanguage().toLowerCase();// Salva el tipo de idioma
        if (!sIdioma.equals(IDIOMA_INGLES) && !sIdioma.equals(IDIOMA_ESPANOL)) {
            sIdioma = IDIOMA_ESPANOL;
        }
        iU = Usuario.getInstancia();
        iU.setIdioma(sIdioma);
        iU.setAumento(calculatePorcentajeAumento());
        showSplashAnimation();
    }

    public void showSplashAnimation() {
        Form splash = new Form(new LayeredLayout());
        splash.setUIID("Splash");

        ScaleImageLabel iconBackground = new ScaleImageLabel(getGlobalResources().getImage("attt.png"));
        iconBackground.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
        Container centerBackground = BorderLayout.center(iconBackground);
        splash.add(centerBackground);

        Label iconForeground = new Label(getGlobalResources().getImage("attt.png"));
        Container centerIcon = BorderLayout.centerAbsolute(iconForeground);
        splash.add(centerIcon);
        splash.show();

        Display.getInstance().callSerially(() -> {
            ((BorderLayout) centerBackground.getLayout()).setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
            centerBackground.setShouldCalcPreferredSize(true);
            centerBackground.animateLayoutAndWait(2000);

            iconForeground.remove();
            iconBackground.remove();
            centerIcon.remove();

            Container cnFondo = LayeredLayout.encloseIn(
                    new Label(iconBackground.getIcon(), "CenterIcon"));
            Container boxy = BoxLayout.encloseY(cnFondo);
            Label placeholder = new Label();
            placeholder.setShowEvenIfBlank(true);
            Label lbTit = new Label("Tarifa de Taxi", "SplashSubTitulo");
            Component.setSameHeight(placeholder, lbTit);
            Component.setSameWidth(placeholder, lbTit, boxy);
            centerBackground.add(BorderLayout.CENTER, boxy);
            splash.revalidate();

            Display.getInstance().callSerially(() -> {
                placeholder.setText(" ");
                boxy.add(placeholder);
                boxy.setShouldCalcPreferredSize(true);
                boxy.getParent().animateLayoutAndWait(1500);
                boxy.replaceAndWait(placeholder, lbTit, CommonTransitions.createFade(1500));

                Label lbNuevoTitulo = new Label(" ");
                Label lbTitulo = new Label("ATTT", "SplashTitulo");
                Component.setSameHeight(lbNuevoTitulo, lbTitulo);
                Component.setSameWidth(lbNuevoTitulo, lbTitulo);
                boxy.add(lbNuevoTitulo);
                boxy.getParent().animateLayoutAndWait(250);
                boxy.replaceAndWait(lbNuevoTitulo, lbTitulo, CommonTransitions.createFade(3000));

                new Tarifa().show();
            });
        });
    }
}

相关截图

相关截图


解决方案

问题根源:Codename One的Lifecycle.runApp()方法会在应用首次启动和从后台恢复时被调用,当前代码每次执行runApp()都会直接启动闪屏,导致恢复时重新初始化。

修改方案

  1. 添加初始化状态标记,避免重复执行初始化逻辑
  2. 保存当前显示的Form,恢复时直接显示该Form
  3. 重写pause()方法保存应用状态,resume()方法可添加额外恢复逻辑

修改后的代码

public class TarifaTaxiPredictivo extends Lifecycle {

    private Usuario iU;
    private boolean isAppInitialized = false;
    private Form currentForm; // 保存当前活跃的Form

    @Override
    public void runApp() {
        if (!isAppInitialized) {
            // 首次启动时执行初始化逻辑
            String sIdioma = L10NManager.getInstance().getLanguage().toLowerCase();
            if (!sIdioma.equals(IDIOMA_INGLES) && !sIdioma.equals(IDIOMA_ESPANOL)) {
                sIdioma = IDIOMA_ESPANOL;
            }
            iU = Usuario.getInstancia();
            iU.setIdioma(sIdioma);
            iU.setAumento(calculatePorcentajeAumento());
            showSplashAnimation();
            isAppInitialized = true;
        } else {
            // 应用从后台恢复,显示之前的界面
            if (currentForm != null) {
                currentForm.show();
            } else {
                // 兜底逻辑:如果没有保存的Form,直接显示主界面
                currentForm = new Tarifa();
                currentForm.show();
            }
        }
    }

    @Override
    public void pause() {
        // 应用进入后台时,保存当前显示的Form
        currentForm = Display.getInstance().getCurrent();
        super.pause();
    }

    @Override
    public void resume() {
        super.resume();
        // 可选:添加界面数据刷新等恢复逻辑
    }

    public void showSplashAnimation() {
        Form splash = new Form(new LayeredLayout());
        splash.setUIID("Splash");

        ScaleImageLabel iconBackground = new ScaleImageLabel(getGlobalResources().getImage("attt.png"));
        iconBackground.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
        Container centerBackground = BorderLayout.center(iconBackground);
        splash.add(centerBackground);

        Label iconForeground = new Label(getGlobalResources().getImage("attt.png"));
        Container centerIcon = BorderLayout.centerAbsolute(iconForeground);
        splash.add(centerIcon);
        splash.show();

        Display.getInstance().callSerially(() -> {
            ((BorderLayout) centerBackground.getLayout()).setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
            centerBackground.setShouldCalcPreferredSize(true);
            centerBackground.animateLayoutAndWait(2000);

            iconForeground.remove();
            iconBackground.remove();
            centerIcon.remove();

            Container cnFondo = LayeredLayout.encloseIn(
                    new Label(iconBackground.getIcon(), "CenterIcon"));
            Container boxy = BoxLayout.encloseY(cnFondo);
            Label placeholder = new Label();
            placeholder.setShowEvenIfBlank(true);
            Label lbTit = new Label("Tarifa de Taxi", "SplashSubTitulo");
            Component.setSameHeight(placeholder, lbTit);
            Component.setSameWidth(placeholder, lbTit, boxy);
            centerBackground.add(BorderLayout.CENTER, boxy);
            splash.revalidate();

            Display.getInstance().callSerially(() -> {
                placeholder.setText(" ");
                boxy.add(placeholder);
                boxy.setShouldCalcPreferredSize(true);
                boxy.getParent().animateLayoutAndWait(1500);
                boxy.replaceAndWait(placeholder, lbTit, CommonTransitions.createFade(1500));

                Label lbNuevoTitulo = new Label(" ");
                Label lbTitulo = new Label("ATTT", "SplashTitulo");
                Component.setSameHeight(lbNuevoTitulo, lbTitulo);
                Component.setSameWidth(lbNuevoTitulo, lbTitulo);
                boxy.add(lbNuevoTitulo);
                boxy.getParent().animateLayoutAndWait(250);
                boxy.replaceAndWait(lbNuevoTitulo, lbTitulo, CommonTransitions.createFade(3000));

                // 闪屏结束后,保存主界面Form
                currentForm = new Tarifa();
                currentForm.show();
            });
        });
    }
}

修改说明

  • isAppInitialized标记确保初始化逻辑只执行一次
  • currentForm变量在pause()时保存当前界面,恢复时直接显示
  • 闪屏结束后主动保存主界面Form,避免空指针
  • 添加兜底逻辑,防止异常情况导致无法恢复界面

内容的提问来源于stack exchange,提问作者Rubén Villarreal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:40:34