2012-02-28 4 views
1

스레드를 사용하여 5 초 타이머를 실행합니다. 타이머가 만료되면 몇 가지 변수를 변경하고 다시 시작하여 특정 조건이 충족되지 않을 때까지이 프로세스를 반복합니다. 내가 스레드를 연구하고 분명히 다시 설정하거나 다시 사용할 수 없지만 대신 다른 스레드를 만들어야합니다. 나는 올바른 길을 이해할 수 없다.안드로이드에서 스레드를 반복적으로 사용할 수 있습니까?

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; 
    } 

} 


} 

그래서 기본적으로 내가 테스트 I 지금은 프로그램 첫 번째 두 단계에 대한 스레드를 계속 사용하지만, 그것을 수준에 따라 다른 시간 제한을 통과하려면 :

여기 내 코드입니다.

나는이 모든 통찰력을 주셔서 감사하겠습니다. 감사합니다.

여기에 대한 답변에서받은 도움의 일부를 고소 내 코드의 수정 된 버전,하지만 난 여전히 데 문제 :

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,하지만 타이머가 끝난 후 버튼을 누르면 예외로 인해 강제 종료됩니다. 필자가해야 할 일은 카운터가 0으로 재설정되고 5 초 이내에 9 회 이상의 클릭이 눌러지면 레벨이 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)는 일반적으로 한 번만 실행될 수 있습니다.

그러나 타이머 스레드는 쓰여진대로 작동하지 않습니다. 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

안드로이드와 스레드에 관해서는 매우 경험이 없습니다.이 예제를 지적 해 주시겠습니까? 감사! – deucalion0

+1

@ deucalion0 - 일부 샘플 코드 –

+0

으로 답변을 업데이트했습니다. 고맙습니다. 지금 사용해 보시고 잘하면 내 목표를 달성 할 것입니다. 알아 내면 알려 드리겠습니다. 감사. – deucalion0

1

그런 스레드를 만들거나 파괴해서는 안됩니다. 귀하의 유스 케이스의 경우, 동일한 스레드를 계속 실행하는 것이 좋지만 변수를 변경하는 동안 동기화 프리미티브를 사용하여 차단 한 다음 준비가되었을 때 작업을 재개하십시오. 간단한 잠금에서 조건 변수 또는 다른 동기화 메커니즘까지 사용할 수 있지만 동일한 스레드를 유지합니다.

+0

그래서 동일한 스레드를 실행하는 동안 sleep()에 새 값을 할당 할 수 있습니까? 나는 동기화 프리미티브를 찾을 것이다. 감사합니다. . – deucalion0

1

직접 스레드를 만들고 다시 사용하는 것에 대해 걱정하지 마십시오.대신 실행하려는 작업에 중점을 두어 실행자가 이러한 작업을 (일반적으로 스레드 풀을 사용하여) 예약하도록하십시오. Executors 클래스에는 다양한 유형의 Executor 인스턴스를 만들기위한 여러 가지 정적 메서드 인 http://developer.android.com/reference/java/util/concurrent/Executors.html이 있습니다.

Runnable 또는 AsyncTask를 사용하여 작업을 정의 할 수 있습니다. 여기에 AsyncTask를 사용하여 수행하는 방법의 대략적인 예가 나와 있습니다.

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

API 레버 11 이후에만 사용 가능한 AsyncTask.executeOnExecutor()를 참조한다고 가정합니다. – yorkw

+0

정확합니다. 예제를 업데이트했습니다. AsyncTask를 사용할 수 없다면 일반 Runnable을 사용하여 계속 수행 할 수 있습니다. AsyncTask를 사용하면 훨씬 쉽게 작업 할 수 있습니다. –

관련 문제