2012-02-28 21 views
1

スレッドを使用して5秒のタイマーを実行しています。タイマーが不足しています。いくつかの変数を変更して再起動し、一定の条件が満たされなくなるまでこのプロセスを繰り返します。私はスレッドを研究しており、再設定や再利用はできませんが、代わりに別のスレッドを作成する必要があります。私は正しい方法を理解できません。ここでAndroidでスレッドを繰り返し使用できますか?

は私のコードです:

package com.deucalion0; 

import android.app.Activity; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 

public class FirstOneActivity extends Activity { 
/** Called when the activity is first created. */ 


MediaPlayer ourSong; 
int counter; 
Button add; 
Thread timer; 
TextView display; 
TextView lvl; 
int level = 1; 
int time; 




@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    ourSong = MediaPlayer.create(FirstOneActivity.this, R.raw.click); 
    counter = 0; 
    add = (Button) findViewById (R.id.bAdd); 
    display = (TextView) findViewById (R.id.tvDisplay); 
    lvl = (TextView) findViewById (R.id.lvldisplay); 

    add.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      counter++; 
      //ourSong.start(); 
      display.setText("Your total is "+ counter); 

      if(counter ==1) 

      { 
       set(); 
      } 
     } 
    }); 


    timer = new Thread(){ 
     public void run(){ 
      try{ 
       sleep(time); 
      }catch(InterruptedException e){ 
       e.printStackTrace(); 
      }finally{ 
       test(); 

      } 
     } 


    }; 

} 


public void test(){ // Method that does two things after the timer runs out, depending on the value held in counter 

if(counter>= 10 && level == 1 || counter>= 15 && level == 2) 
    {  
     level++; 
     counter =0; 
     display.setText("Your total is 0"); 

     //The timer must be reset for the next level 


    } 

    else if(counter<10 && level == 1 || counter< 15 && level == 2){ 

     Intent openNext = new Intent("com.deucalion0.NEXT"); 
     startActivity(openNext); 
    } 


} 


public void set(){ 


     if(level == 1) 
    { lvl.setText("Level is "+ level); 
     time = 5000; // The value passed to the sleep method in the thread, this is the length of the timer 
    } 

    else if (level == 2) 
    {lvl.setText("Level is "+level); 
     time = 5000; 
    } 

} 


} 

だから、基本的に、私は今のプログラム私は最初の2つのレベルのテストのために、スレッドを使用し続けるが、それをレベルに応じて異なる時間制限を渡したいです。

私はthis.Thanksに任意の洞察力をいただければ幸いです。

ここでの回答で受信されたヘルプの一部を訴え私のコードの改訂版が、私はまだ持っています問題:

package com.deucalion0; 

import android.app.Activity; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.os.Handler; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 

public class FirstOneActivity extends Activity { 
/** Called when the activity is first created. */ 


MediaPlayer ourSong; 
int counter; 
Button add; 
Thread timer; 
TextView display; 
TextView lvl; 
int level = 1; 
int time; 
boolean completed = false; 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    ourSong = MediaPlayer.create(FirstOneActivity.this, R.raw.click); 
    counter = 0; 
    add = (Button) findViewById (R.id.bAdd); 
    display = (TextView) findViewById (R.id.tvDisplay); 
    lvl = (TextView) findViewById (R.id.lvldisplay); 

    add.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      counter++; 
      completed=false; 
      //ourSong.start(); 
      display.setText("Your total is "+ counter); 

      if(counter ==1) 

      { 
       set(); 
       timer.start(); // start the timer loop: 
      } 
     } 
    }); 


    // create a Handler for the thread to use when interacting with the UI 
    final Handler handler = new Handler(); 

    // create the timer object 
    timer = new Thread() { 
     public void run() { 
      // create a Runnable that will execute on the UI thread 
      Runnable updater = new Runnable() { 
       public void run() { 

       } 
      }; 

      while (!completed) { 
       try { 
        sleep(time); 
       } catch(InterruptedException e) { 
        e.printStackTrace(); 
       } finally { 
        handler.post(updater); 
        test(); 
       } 
      } 
     } 
    }; 




} 

public void reset()//Resets the variables so the level increments, the counter is reset to 0 
{ 
    completed=true; 
    level++; 
    counter =0; 

} 


public void test(){ // Method that does two things after the timer runs out, depending on the value held in counter 

if(counter>= 10 && level == 1 || counter>= 15 && level == 2) 
    { 
     reset();  
    } 

    else if(counter<10 && level == 1 || counter< 15 && level == 2){ 

     Intent openNext = new Intent("com.deucalion0.NEXT"); 
     startActivity(openNext); 
    } 
} 


public void set(){ 


     if(level == 1) 
    { lvl.setText("Level is "+ level); 
     time = 5000; // The value passed to the sleep method in the thread, thi is the length of the timer 
    } 

    else if (level == 2) 
    {lvl.setText("Level is "+level); 
     time = 5000; 
    } 
} 
} 

ゲームが実行され、タイマーが開始されたときにカウンター= 1であるが、タイマーが切れた後にボタンを押すと、例外のため強制終了します。私が必要とするのは、5秒以内に9回以上のクリックが押された場合、カウンタは0にリセットされ、レベルは2になります。 LogCatのエラーは次のとおりです。

02-29 09:47:36.313: D/AndroidRuntime(279): Shutting down VM 
02-29 09:47:36.313: W/dalvikvm(279): threadid=1: thread exiting with uncaught exception  (group=0x4001d800) 
02-29 09:47:36.333: E/AndroidRuntime(279): FATAL EXCEPTION: main 
02-29 09:47:36.333: E/AndroidRuntime(279): java.lang.IllegalThreadStateException:  Thread already started. 
02-29 09:47:36.333: E/AndroidRuntime(279): at java.lang.Thread.start(Thread.java:1322) 
02-29 09:47:36.333: E/AndroidRuntime(279): at com.deucalion0.FirstOneActivity$1.onClick(FirstOneActivity.java:51) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.view.View.performClick(View.java:2408) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.view.View$PerformClick.run(View.java:8816) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.os.Handler.handleCallback(Handler.java:587) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.os.Handler.dispatchMessage(Handler.java:92) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.os.Looper.loop(Looper.java:123) 
02-29 09:47:36.333: E/AndroidRuntime(279): at android.app.ActivityThread.main(ActivityThread.java:4627) 
02-29 09:47:36.333: E/AndroidRuntime(279): at java.lang.reflect.Method.invokeNative(Native Method) 
02-29 09:47:36.333: E/AndroidRuntime(279): at java.lang.reflect.Method.invoke(Method.java:521) 
02-29 09:47:36.333: E/AndroidRuntime(279): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
02-29 09:47:36.333: E/AndroidRuntime(279): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
02-29 09:47:36.333: E/AndroidRuntime(279): at dalvik.system.NativeStart.main(Native Method) 

この情報が私の問題を示すのに役立ちます。

答えて

2

Threadオブジェクトは、好きなだけ何度でもstart()にできます。 start()を呼び出すたびに新しいスレッドが起動します。他のスレッド状オブジェクト(例えば、AsyncTask,TimerTask)は、一般に1回しか実行できません。

書かれたとしてしかし、あなたのタイマーのスレッドが動作しません。 test()メソッドは表示を変更し、UIスレッドで実行する必要があります。

Handlerを作成し、Runnableのタイマースレッドポストからハンドラにtest()を呼び出します。他のアプローチもありますが、これはおそらくあなたの既存のコードを修正する必要はありません。

あなたが欲しいものを行うためAsyncTaskを使用して見なければなりません。また、開発中にStrictModeを有効にして、スレッドエラーの検出を支援する必要があります。

// create a Handler for the thread to use when interacting with the UI 
final Handler handler = new Handler(); 

// create the timer object 
timer = new Thread() { 
    public void run() { 
     // create a Runnable that will execute on the UI thread 
     Runnable updater = new Runnable() { 
      public void run() { 
       test(); 
      } 
     } 
     while (!exitConditionMet()) { 
      try { 
       sleep(time); 
      } catch(InterruptedException e) { 
       e.printStackTrace(); 
      } finally { 
       handler.post(updater); 
      } 
     } 
    } 
}; 

// start the timer loop: 
timer.start(); 

上記のコードは、スレッドが終了する必要がある場合trueを返すメソッドexitConditionMet()があることを前提としています

は、ここにあなたが何をしようとして私が思うでしょう、あなたのコードの簡単な修正です。

+0

私はAndroidや、一般的なスレッドに関しては非常に経験が不足していますが、おそらくこれの例を指摘できますか?ありがとう! – deucalion0

+1

@ deucalion0 - いくつかのサンプルコードで回答を更新しました –

+0

ありがとう、私は今それを試して使用し、うまくいけば目標を達成します。ありがとう。 – deucalion0

1

あなたはそのようなスレッドを作成し、破壊することは避けてください。あなたのユースケースでは、同じスレッドを実行し続ける方が良いかもしれませんが、変数を変更して準備ができたら作業を再開している間に同期プリミティブを使用してブロックします。単純なロックから条件変数、または他の同期メカニズムまで何でも使用できますが、私は同じスレッドを維持します。

+0

同じスレッドを実行中にsleep()に新しい値を割り当てることはできますか?同期プリミティブを検索します。おかげさまで – deucalion0

1

直接スレッドを作成し、再使用して心配しないでください。代わりに、実行したいタスクに焦点を当てて、エグゼキュータがそれらのタスクのスケジューリングを世話するようにします(通常はスレッドのプールを使用します)。 Executorsクラスには、異なるタイプのExecutorインスタンスを作成するためのいくつかの静的メソッドがあります。http://developer.android.com/reference/java/util/concurrent/Executors.html

RunnableまたはAsyncTaskを使用してタスクを定義できます。

Executor executor = ... 
AsyncTask task = ... 
task.executeOnExecutor(executor, ...); 
+0

AsyncTask.executeOnExecutor()を参照して、APIレバー11以降でしか使用できないとします。 – yorkw

+0

正しいですか。私は例を更新しました。 AsyncTaskを使用できない場合は、通常のRunnableでAsyncTaskを使用することができますが、AsyncTaskを使用するだけで作業が簡単になります。 –

関連する問題