2010-11-13 40 views
0

我有一個Android應用程序,我只是試驗的東西,我似乎無法弄清楚爲什麼我的應用程序的力量關閉時,我通過一個while循環更新TextView。當我註釋掉updateText方法時,它運行良好。爲什麼當我在更新方法中設置文本時,我的應用程序強制關閉?

public class GameThread extends Thread { 

Thread t; 
private int i; 
private boolean running; 
private long sleepTime; 
GameView gv; 

public GameThread() { 

    t = new Thread(this); 
    t.start(); 
    i = 0; 
    sleepTime = 1000; 
} 

public void initView(GameView v) { 

    this.gv = v; 
} 

public void setRunning(boolean b) { 

    this.running = b; 
} 

public boolean getRunning() { 

    return running; 
} 

public void run() { 

    while(running) { 

    i++; 
    update(); 

    try { 

    t.sleep(sleepTime); 
    } catch(InterruptedException e) { 

    } 
    } 
} 

public void update() { 

    gv.setText(i); // when this is uncommented, it causes force close 
    Log.v("Semajhan", "i = " + i); 
} 


    public class GameView extends LinearLayout { 

public TextView tv; 

public GameView(Context c) { 

    super(c); 
    this.setBackgroundColor(Color.WHITE); 
    tv = new TextView(c); 
    tv.setTextColor(Color.BLACK); 
    tv.setTextSize(20); 
    this.addView(tv); 
} 

public void setText(int i) { 

    tv.setText("i count: " + i); 
} 


    public class Exp extends Activity { 

GameThread t; 
GameView v; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     v = new GameView(this); 
     setContentView(v); 
     t = new GameThread(); 
     t.setRunning(true); 
     t.initView(v); 
    } 

public boolean onTouchEvent(MotionEvent event) { 

    if (event.getAction() == MotionEvent.ACTION_DOWN) { 

    if (t.getRunning() == true) { 

    t.setRunning(false); 
    Log.v("Semajhan", "STOPPED"); 
    } else { 

    t.setRunning(true); 
    Log.v("Semajhan", "RESTART"); 
    } 
    } 

    return true; 
} 

    protected void onDestroy() { 

    Log.v("Semajhan", "DESTROYING"); 
    super.onDestroy(); 
    } 

    protected void onStop() { 

    Log.v("Semajhan", "Stopping"); 
    super.onStop(); 
    } 

我以爲我會發布整個應用程序,因爲它是相對較小,這樣我就可以得到不混亂一些幫助。

回答

1

你必須從UI線程調用它。

欲瞭解更多信息查詢:Painless Threading

如果你決定使用一個處理程序,爲你最簡單的解決辦法是:

  1. 擴展視圖,重寫它的onDraw,在失敗中汲取的遊戲對象,你計算的遊戲數據後他們首先當然

  2. 的處理程序:(您的活動)

    private Handler playHandler = new Handler() {

    public void handleMessage(Message msg) {

    gameView.postInvalidate(); // gameView is the View that you extended 
    

    }

    };

  3. 遊戲螺紋具有簡單

Message.obtain(playHandler).sendToTarget();

在2個字,View負責繪圖(您可以在一個單獨的類移動計算和的onDraw前稱呼它),線程只負責對處理程序排定呼叫負責,而處理程序僅負責告訴視圖重繪本身。

+0

因此,爲了長期利益,我應該使用處理程序還是不使用? – semajhan 2010-11-13 22:22:40

+1

其實是的,我編輯了我的答案 – apps 2010-11-13 22:47:45

+1

就像你所說的那樣,但現在我有一件事。我創建了一個帶有活動和擴展線程類的簡單應用程序。現在我在我的活動和線程的一個實例中創建一個處理程序並啓動它。我的活動中還有一個按鈕,用於啓動線程,該線程更新按鈕的文本。這裏是我卡住的地方。我應該如何連接處理程序?我添加了Message.obtain(handler).sendToTarget();在我的線程類,但它說處理程序不能解析爲變量。 – semajhan 2010-12-10 19:41:19

0

您無法更新UI線程之外的應用程序的UI,這是您開始的「主」線程。在您的應用程序的onCreate(Context)中,您正在創建遊戲線程對象,這就是做你的用戶界面的更新。

你應該使用一個處理程序:
http://developer.android.com/reference/android/os/Handler.html

+0

哦,謝謝你的信息。我對編程相對來說比較陌生,但是如果你能以最簡單的形式演示一個處理程序的話,是否可能呢?如果你知道我的意思,我更像是一個視覺 - 嘗試 - 失敗 - 重複的學習者。 – semajhan 2010-11-13 22:16:40

3

首先,當你得到一個強制關閉對話框中,使用adb logcat,DDMS,或在Eclipse中DDMS角度來考察logcat的,並期待在與相關的堆棧跟蹤你崩潰。

在這種情況下,您的異常將會產生「無法從非UI線程修改用戶界面」的效果。您正嘗試從不支持的後臺線程調用setText()

如果使用2D/3D圖形,則使用GameThread是有意義的。它不適合基於窗口小部件的應用程序。有many,many,many,many示例演示如何在不使用GameThread的情況下創建基於窗口小部件的應用程序。

+1

我將使用2D/3D圖形。這些小部件和什麼都不是很簡單的測試。 – semajhan 2010-11-13 22:23:09

相關問題