2017-06-25 21 views
1

我希望countdowntimer在一个单独的线程,并为它更新每个滴答的UI。每当我点击开始应用程序刚关闭,我得到'应用程序已停止'的错误信息。CountdownTimer崩溃应用程序。试图更新线程上的UI线程

public class Activity_MultiplayerGame extends AppCompatActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity__multiplayer_game); 
} 

public void btnStart_onClick(View view){ 
    CountDownTimer timer = new CountDownTimer(15000, 1000){ 

     @Override 
     public void onTick(final long millisUntilFinished) { 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        TextView countdownText = (TextView) findViewById(R.id.countdown); 
        Integer timeUntilFinished = (int) millisUntilFinished/1000; 
        countdownText.setText(timeUntilFinished); 
       } 
      }); 
     } 

     @Override 
     public void onFinish() { 
      TextView countdownText = (TextView) findViewById(R.id.countdown); 
      countdownText.setText("Finished"); 
     } 
    }; 

    timer.start(); 
} 
} 

我所做的假设,即创建一个CountDownTimer给它自己的线程?

+0

提供你的堆栈跟踪。 –

+0

什么是错误? –

回答

0

您无法从android上的主(ui)线程以外的其他线程更新UI。有很多方法可以解决这个问题,但我想你应该从AsyncTask开始,如果你真的需要另一个线程。检查doInBackround和onProgressUpdate方法。

如果你不需要其他线程(如果这只是关于计数器你不'),你可以检查Handler类和postAtTime(Runnable,long),postDelayed(Runnable,long)方法。或者,您可以创建Handler类的子类并使用sendMessageDelayed(android.os.Message,long)和overrideMessageMes​​sage()的组合。

0

这是你的问题:

countdownText.setText(timeUntilFinished); 

你传递给setText(int)方法,它其实需要字符串资源ID,而不是整数要显示的整数。您应该使用方法setText(String)

试试这个:

countdownText.setText(String.valueOf(timeUntilFinished)); 
1

可以使用Handler。我写了一个样品给你

这个代码增加一个计数器每隔一秒显示和更新上TextView的计数器值。

public class MainActivity extends Activity { 


    private Handler handler = new Handler(); 
    private TextView textView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     textView = (TextView) findViewById(R.id.text); 
     startTimer(); 
    } 


    int i = 0; 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      i++; 
      textView.setText("counter:" + i); 
      startTimer(); 
     } 
    }; 

    public void startTimer() { 
     handler.postDelayed(runnable, 1000); 
    } 

    public void cancelTimer() { 
     handler.removeCallbacks(runnable); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     cancelTimer(); 
    } 
} 
+0

但不是绑定到UI线程的处理程序?所以当它调用setText时,这不会导致用户界面滞后或冻结吗? 我希望用户能够输入到文本框中,并在倒数计时生效时与按钮交互。 – Jamanfi

+0

它是工作!我在手机上测试了它。我也看到之前,ExoPlayer使用此代码来更新videoplayer中的进度条 –

+0

只是测试代码,看看会发生什么 –

0

此代码还解决它下降(无论你想或增加)计数器,并显示在文本视图中,您还可以停止或通过点击计数器复位相同的按钮。

public class MainActivity extends AppCompatActivity { 


TextView textView; 
Button count; 

boolean timelapseRunning = true; 
int NUM_OF_COUNT=15; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    textView=(TextView)findViewById(R.id.textview); 
    count=(Button)findViewById(R.id.count); 
    runTimer(); 

} 
public void onclick(View view){ 
    if (!timelapseRunning) { 
     timelapseRunning=true; 
    } else { 
     timelapseRunning = false; 

    } 
    if(NUM_OF_COUNT==0){ 
     NUM_OF_COUNT=15; 
    } 
} 
private void runTimer() { 
      final Handler handler = new Handler(); 
    handler.post(new Runnable() { 
     @Override 
     public void run() { 
      textView.setText(""+NUM_OF_COUNT); 
      if (!timelapseRunning && NUM_OF_COUNT>0) { 
       NUM_OF_COUNT--; 
      } 
      handler.postDelayed(this, 1000); 
     } 
    }); 
} 
} 
0

CountDownTimer在同一个线程中给出回调,它在其中创建。因此,如果在UI线程上调用CountDownTimer构造函数,则onTick中的runOnUiThread绝对不是必需的。

此外,

TextView countdownText = (TextView) findViewById(R.id.countdown); 

被称为在onTick方法是设计差,如findViewById方法消耗相当大的处理能力。

最后,Nabin Bhandari指出的实际问题是传递给setText方法的整数值。你需要把它包装成字符串。 这段代码就够了

final TextView countdownText = (TextView) findViewById(R.id.countdown); 
    CountDownTimer timer = new CountDownTimer(15000, 1000) { 
     @Override 
     public void onTick(long millisUntilFinished) { 
      countdownText.setText(String.valueOf(millisUntilFinished/1000)); 
     } 

     @Override 
     public void onFinish() { 
      countdownText.setText("Finished"); 
     } 
    }; 
    timer.start();