2012-07-02 61 views
0

所以我開始爲一個簡單的Android遊戲製作一個簡單的「啓動畫面」(它更像是一個介紹畫面),我正在爲一個移動編程課程做一個簡單的安卓遊戲。我遇到了問題。我知道我應該使用一個線程,但我的實現似乎不工作。你應該能夠感受到我要去的效果。Splash Screen&Premise Screen - Android

public class SplashScreen extends Activity { 

//how long until we go to the next activity 
protected int splashTime = 2000; 
private Thread splashThread; 

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

    final TextView first = (TextView) findViewById(R.id.textView1); 
    final TextView second = (TextView) findViewById(R.id.textView2); 
    final TextView third = (TextView) findViewById(R.id.textView3); 
    final TextView fourth = (TextView) findViewById(R.id.textView4); 
    final TextView fifth = (TextView) findViewById(R.id.textView5); 
    final TextView sixth = (TextView) findViewById(R.id.textView6); 
    final ImageView main_character = (ImageView) findViewById(R.id.imageView1); 

    // thread for displaying the SplashScreen 
    splashThread = new Thread() { 
     @Override 
     public void run() { 
      try { 
       synchronized(this){ 

        first.setText("The year is 2048..."); 

        wait(splashTime); 

        first.setText(""); 
        second.setText("...the Earth's resources have long been depleted"); 

        wait(splashTime); 

        second.setText(""); 
        third.setText("Attempts have been made to save our home..."); 

        wait(splashTime); 

        third.setText(""); 
        fourth.setText("...but all has gone awry, trash now rains from the skies"); 

        wait(splashTime); 

        fourth.setText(""); 
        fifth.setText("Now, only one man can save us, and his name is..."); 

        wait(splashTime); 

        fifth.setText(""); 
        sixth.setText("The Garbage Man!"); 
        main_character.setImageResource(drawable.bobrgb888); 

       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      finally { 
       finish(); 

       //start a new activity 
       Intent i = new Intent(getApplicationContext(), MainMenu.class); 
       startActivity(i); 
      } 
     } 
    }; 
    splashThread.start(); 

} 

問題是,第一個textview與第一個wait()調用一起被調用,但隨後我得到一個強制關閉。

這裏是我的logcat:

07-02 19:35:16.241: W/dalvikvm(709): threadid=9: thread exiting with uncaught exception (group=0x40015560) 
07-02 19:35:16.250: E/AndroidRuntime(709): FATAL EXCEPTION: Thread-10 
07-02 19:35:16.250: E/AndroidRuntime(709):  android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.ViewRoot.checkThread(ViewRoot.java:2932) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.ViewRoot.requestLayout(ViewRoot.java:629) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.View.requestLayout(View.java:8267) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.View.requestLayout(View.java:8267) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.View.requestLayout(View.java:8267) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.View.requestLayout(View.java:8267) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:257) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.view.View.requestLayout(View.java:8267) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.widget.TextView.checkForRelayout(TextView.java:5521) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.widget.TextView.setText(TextView.java:2724) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.widget.TextView.setText(TextView.java:2592) 
07-02 19:35:16.250: E/AndroidRuntime(709): at android.widget.TextView.setText(TextView.java:2567) 
07-02 19:35:16.250: E/AndroidRuntime(709): at com.connor.black.SplashScreen$1.run(SplashScreen.java:41) 
07-02 19:35:16.420: D/szipinf(709): Initializing inflate state 
+0

如果你在後臺線程而不是UI線程上這樣做,它不會有你正在尋找的效果。如果您不介意在介紹發生時用戶無法做任何事情,則可能不希望在另一個線程上執行此操作。或者你也可以使用AsyncTask,雖然這通常更像是在後臺做一些東西時顯示進度條。 – matt5784

回答

1

這是我用我的閃屏代碼:

final SplashScreen splash = this; 

Thread splashThread = new Thread() { 
     @Override 
     public void run() { 
      go = true; 
      while (go) { 
      try { 
       int waited = 0; 
       while(_active && (waited < _splashTime)) { 
        sleep(100); 
        if(_active) { 
         waited += 100; 
        } 
       } 
      } catch(InterruptedException e) { 
       // do nothing 
      } finally { 
       finish(); 
       Intent i = new Intent(); 
       i.setClass(splash, MyActivity.class); 
       startActivity(i); 
       //stop(); 
       go = false; 
      } 
      } 
     } 
    }; 
    splashThread.start(); 

與閃屏的問題是,你使用的wait()不正確。你在找什麼是睡眠()。

要觸摸工作線程的UI線程,您需要使用runOnUiThread(Runnable action)或處理程序。

+0

謝謝,這有幫助,但我主要試圖找出爲什麼我調用wait()函數後無法調用任何代碼 –

+1

http://www.javamex.com/tutorials/synchronization_wait_notify.shtml 您不應該使用wait()來達到此目的。你想要的是睡眠()。 – CSAntol

+0

好的,謝謝!我會檢查出來的。 –

2

如果你想使用一個線程在這裏,您必須調用start啓動線程。這又將調用run()方法:

splashTread = new Thread() { 
    @Override 
    public void run() { 
     ... 
    } 
}; 

splashThread.start(); 

請記住,這將在後臺運行,即不是UI線程。

+0

好吧,我已經添加了這個,並且第一個textview被填充,並且它看起來像第一個wait()調用運行,但是然後我得到一個forceclose。我將發佈我的logcat –

+0

在這裏使用線程可能不是正確的選擇,正如您從「創建視圖層次結構的原始線程可以觸及其視圖」中看到的。信息。快速(也許很髒)的解決方案是不使用線程,直接在onCreate()內調用TextView更新代碼。 –

0

您需要使用Handler觸摸UI(即設置你的textviews'文本。)

只是你的線程聲明的上面,把這個:

Handler handler = new Handler(); 

然後而不是做first.setText("bla bla bla");

handler.post(new Runnable(){ 
    public void run(){ 
    first.setText("bla bla bla"); 
    } 
}); 

你需要這樣做,因爲單獨的線程不能觸摸UI元素。使用處理器基本上告訴UI線程運行任何你在傳遞

+0

我需要爲每次要更改文本時創建一個新的處理程序? –

+0

不,處理程序保持不變,您在UI線程中創建處理程序對象一次。就像我說過的,你可以在線程聲明之上聲明它。或者你可以使Handler對象成爲全局對象。你每次創建的是一個新的Runnable。 – you786

0

通過類似更換內部splashThread線程代碼:

runOnUiThread(new Runnable() { 
    public void run() { 
     first.setText("The year is 2048..."); 
     //... The rest of code goes here too. 
    } 
}); 

這樣UI線程可以完美地觸摸自己的看法。