2012-05-09 7 views
1

Androidアプリで作業していて、30秒ごとにバックグラウンドを更新したいと考えています。2回目のタイマーでアプリがクラッシュする

私はタイマーを使用していましたが、動作しますが、1回だけです!アプリがクラッシュする2回目。

public Timer mTimer = null;  

public void loadColor() 
    { 
     setContentView(R.layout.color); 

     cur_scr = (LinearLayout) findViewById(R.id.colorScreen); 
    } 

    public void onClick(View v) throws InterruptedException 
    { 
     int id = v.getId(); 

     switch (id) 
     { 
       case R.id.nextColor: 
        loadColor(); 

        mTimer = new Timer(); 

        mTimer.scheduleAtFixedRate(new TimerTask() 
        { 
         public void run() 
         { 
         Random gen = new Random(); 
         cur_scr.setBackgroundColor(Color.argb(255, gen.nextInt(256), gen.nextInt(256), gen.nextInt(256))); 
         } 
        }, 0, 2000); 

        break; 
     } 
    } 

LOGCAT:

05-10 15:46:12.325: W/dalvikvm(346): threadid=9: thread exiting with uncaught exception (group=0x40015560) 
05-10 15:46:12.344: E/AndroidRuntime(346): FATAL EXCEPTION: Timer-0 
05-10 15:46:12.344: E/AndroidRuntime(346): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.ViewRoot.checkThread(ViewRoot.java:2932) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.ViewRoot.invalidateChild(ViewRoot.java:642) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:668) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.View.invalidate(View.java:5279) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.View.setBackgroundDrawable(View.java:7626) 
05-10 15:46:12.344: E/AndroidRuntime(346): at android.view.View.setBackgroundColor(View.java:7516) 
05-10 15:46:12.344: E/AndroidRuntime(346): at com.haxad0x.tools.Core$1.run(Core.java:162) 
05-10 15:46:12.344: E/AndroidRuntime(346): at java.util.Timer$TimerImpl.run(Timer.java:284) 
05-10 15:46:14.194: D/AndroidRuntime(346): Shutting down VM 
05-10 15:46:14.194: W/dalvikvm(346): threadid=1: thread exiting with uncaught exception (group=0x40015560) 
05-10 15:46:14.194: I/Process(346): Sending signal. PID: 346 SIG: 9 

私を助けてください!みんなありがとう!


 case R.id.nextColor: 
      loadColor(); 

      mTimer = new Timer(); 

      mTimer.scheduleAtFixedRate(new TimerTask() 
      { 
       public void run() 
       { 
        runOnUiThread(new Runnable() 
        { 
         public void run() { 
         Random gen = new Random(); 
         cur_scr.setBackgroundColor(Color.argb(255, gen.nextInt(256), gen.nextInt(256), gen.nextInt(256))); 
         } 
        }); 
       } 
      }, 0, 2000); 

      break; 

コードはこのように動作します。私はそれについて1つの質問しか持っていません:それは長いコードですか?というのは;すべてのボイドのためにパフォーマンスに影響を及ぼしますか?それを短くすることはできますか?

+0

ログカットであなたに伝えるエラーメッセージは...?また、30秒ごとにfindViewById()を呼び出そうとしないでください。これは比較的高価なメソッドで、onCreate()の中で一度呼び出すだけで、参照を保持し、その参照に必要な回数だけ.setBackgroundcolor()を呼び出すだけです。 – FoamyGuy

+0

本当にちょうど私のソリューションを使用して、それを働かせて、あなたのコードとして投稿してください、私の投稿を投票しない、または受け入れたことをマークして、投稿を改善する方法を明確に投稿したとき、 –

答えて

1

アクティビティが破棄され、ビューが存在しなくなったため(findViewByIdが失敗する)、別のビューが表示される可能性があります。

あなたがする必要があるのは、活動のためにonDestroyのタイマーを停止することです。

ですから、

public class YourActivity extends Activity { 
    private Timer mTimer = null; 

    public void onCreate(Bundle state) { 
    //setContentView 
    mTimer = new Timer(); 
    mTimer.scheduleAtFixedRate(new TimerTask() 
    { 
     public void run() 
     { 
     Random gen = new Random(); 
     cur_scr = (LinearLayout) findViewById(R.id.colorScreen); 
     cur_scr.setBackgroundColor(Color.argb(255, gen.nextInt(256), gen.nextInt(256), gen.nextInt(256))); 
     } 
    }, 0, 30000); 
    } 

    public void onDestroy() { 
    mTimer.cancel(); 
    } 
} 

を持っていると思います。..クラスレベルの変数、おそらくmTimerとして をごタイマ変数を作成します - 更新 - を私はまだあなたが上記の変更を行う必要があります同意する一方で、それが見えますTimerTaskは新しいスレッド(メインのUIスレッドではない)で実行されます。 UIスレッドでUIで動作するコードを実行する必要があります。このようなActivity.runOnUiThreadを使用します。

mTimer.scheduleAtFixedRate(new TimerTask() 
{ 
     public void run() 
     { 
     Random gen = new Random(); 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       //actually you should probably put a try catch around the code below so it doesn't crash your app if somehow the view isn't found any longer.. It should work as long as you remove the timer task on onDestroy but to be safe i would put a try catch in. 
       cur_scr = (LinearLayout) findViewById(R.id.colorScreen); 
       cur_scr.setBackgroundColor(Color.argb(255, gen.nextInt(256), gen.nextInt(256), gen.nextInt(256))); 
      } 
     }); 

     } 
} 

おそらくハンドラを使用してこれを実行する方が簡単である別の方法があります。

これは、私はそれを行うだろうかです:

public class YourActivity extends Activity { 
    private static final int BG_CHANGE_INTERVAL = 30 * 1000; 
    private Handler mHandler = null; 
    private Runnable mUpdateBgRunnable = new Runnable() { 
    Random gen = new Random(); 
    @Override 
    public void run() { 
     cur_scr = (LinearLayout) findViewById(R.id.colorScreen); 
     cur_scr.setBackgroundColor(Color.argb(255, gen.nextInt(256), gen.nextInt(256), gen.nextInt(256))); 
     updateBg(); 
    } 

    } 
    public void onCreate(Bundle state) { 
    //setContentView 
    mHandler = new Handler(); 
    updateBg(); 
    } 

    private void updateBg() { 
    mHandler.removeCallbacks(mUpdateBgRunnable); 
    mHandler.postDelayed(mUpdateBgRunnable, BG_CHANGE_INTERVAL); 
    } 

    public void onDestroy() { 
    mTimer.cancel(); 
    } 
} 

はタイマー対ハンドラに関する詳しい情報は、このarticleを参照してください。

+0

ねえねえ!私はonCreate()イベントでfindViewById()を追加しました。私もMatt Wolfeの提案を試しましたが、クラッシュしています。 -700文字が残っているので、私はlogcatを投稿できません。どうすれば投稿できますか?ありがとう! –

+0

あなたのコードをもっと投稿できますか? –

+0

何時でも、たまには何時でもクラッシュしますか?そのクラスが常にクラッシュしていると、クラスキャスト例外が発生している可能性があります。つまり、探しているビューが正しいタイプではないということです。少なくとも、エラーのスタックトレースを見てアイデアを得る必要があります。 –

関連する問題