【问题标题】:Android: The splash screen does not get shown, why?Android:启动画面没有显示,为什么?
【发布时间】:2011-06-10 16:55:38
【问题描述】:

我正在学习 Android。从我到目前为止阅读的文档中,我无法弄清楚如何让启动视图显示(在睡眠期间屏幕保持空白)。看来我需要为主布局启动一个新活动,但这似乎很浪费(飞溅应该永远消失,我想重用它的线程)。

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class Ext3 extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);

        Log.v("Ext3", "starting to sleep");

        try {
            Thread.sleep (5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.v("Ext3", "done sleeping");

        setContentView (R.layout.main);
    }

}

【问题讨论】:

    标签: android splash-screen


    【解决方案1】:

    我相信你的启动画面永远不会显示,因为你从来没有给 UI 线程(你所在的)一个机会来绘制它,因为你只是睡在那里什么都不做。

    我建议您不要使用 Thread.sleep,而是查看 Timer 或类似的东西来安排刷新和更改视图的内容;另一种方法是启动一个AsyncTask,您可以在其中睡觉,然后像现在一样更改视图。

    不要休眠或以任何其他方式阻塞 UI 线程,这很糟糕......(导致 ANR)

    【讨论】:

    • 请参阅anddev.org/simple_splash_screen-t811.html,了解如何完成此操作的示例。
    • 显然,我认为在调用函数和返回其工作之间完成的信念是错误的。这严重地调用了我有问题的机器模型。显然该线程比我的代码做得更多。这些操作是什么以及何时?
    • @kasterma - 这在活动指南的Activity docsManaging the Activity Lifecycle 部分的活动生命周期下进行了描述。
    • 所以在 UI 线程中,工作由其他代码完成,我的代码只是“设置一些变量”为正确的值。我已阅读 Activity Lifecycle,但不了解导入。
    • 您是对的,UI 线程是执行所有绘图、布局等的线程......其中一部分是调用您的活动来设置所有这些组件。如果您阻止它(睡觉或等待某事),那么您将冻结您的用户界面并使您的应用程序无响应。
    【解决方案2】:

    当你像这样调用sleep 时,你正在阻塞 UI 线程。相反,将第二次调用setContentView 放在Runnable 中,创建一个Handler,并使用Handler 的postDelayed 方法运行Runnable。像这样的:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);
        Runnable endSplash = new Runnable() {
            @Override
            public void run() {
                setContentView (R.layout.main);
            }
        }
        new Handler().postDelayed(endSplash, 5000L);
    }
    

    【讨论】:

    • 在@Matthieu 的回答中查看我的评论,我希望 UI 线程中的睡眠会阻止任何进一步的交互。但是我已经设置了布局;以我的心智模型,我应该无法再阻止任何东西了。
    • 设置布局不会自动导致屏幕被渲染。那是在onCreate 返回后执行的框架内的代码。由于在 更改 内容视图之前您不会返回,因此启动屏幕从来没有机会。应用的整个 UI 在睡眠期间停止。
    【解决方案3】:

    我已经在我的应用程序中尝试过这段代码,它运行良好。也许它会对你有所帮助。

    public class SplashScreen extends Activity {
    
        /**
         * The thread to process splash screen events
         */
        private Thread mSplashThread;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Splash screen view
            setContentView(R.layout.splash);
    
    
    
            final SplashScreen sPlashScreen = this;
    
            // The thread to wait for splash screen events
            mSplashThread = new Thread() {
                @Override
                public void run() {
                    try {
                        synchronized (this) {
                            // Wait given period of time or exit on touch
                            wait(5000);
                        }
                    } catch (InterruptedException ex) {
                    }
    
                    finish();
    
                    // Run next activity
                    Intent intent = new Intent();
                    intent.setClass(sPlashScreen, MainActivity.class);
                    startActivity(intent);
                    stop();
                }
            };
    
            mSplashThread.start();
    
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            return false;
        }
    
        /**
         * Processes splash screen touch events
         */
        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            if (evt.getAction() == MotionEvent.ACTION_DOWN) {
                synchronized (mSplashThread) {
                    mSplashThread.notifyAll();
                }
            }
            return true;
        }
    
    }
    

    【讨论】:

    • 开始一个新的活动肯定比开始一个新线程要多。
    • @kasterma - 不一定。这种方法有很多话要说。一方面,它将启动屏幕与主要活动分开。它的主要问题是闪屏的主要目的(在我看来)是进行耗时的初始化,这会阻止主视图立即显示。在单独的启动活动中进行初始化意味着必须将初始化的数据传输到主活动。 (顺便说一句,在线程的 run() 方法中调用已弃用的 stop() 方法是错误的;我不知道人们为什么这样做。)
    【解决方案4】:

    这是基本启动画面的 sn-p

    public class Splash extends Activity {
    
    //private ProgressDialog pd = null;
    private final int SPLASH_DISPLAY_LENGTH = 3000; 
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.splashscreen);
        //this.pd = ProgressDialog.show(this, "Initializing..", "Initializing Infraline...", true, false);
    
        /* New Handler to start the InfralineTabWidget-Activity
         * and close this Splash-Screen after some seconds.*/
    
        new Handler().postDelayed(new Runnable(){
            @Override
            public void run() {
            /* Create an Intent that will start the InfralineTabWidget-Activity. */
                Intent mainIntent = new Intent(Splash.this,InfralineTabWidget.class);
                Splash.this.startActivity(mainIntent);
                Splash.this.finish();
            }
        }, SPLASH_DISPLAY_LENGTH);
    
    }
    
    }
    

    然后在你的 AndroidManifest.xml 中放

        <activity android:name=".Splash" android:theme="@android:style/Theme.NoTitleBar" android:configChanges="orientation|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    

    希望这对你有用:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多