Android - 创建同步计时器

时间:2015-07-25 13:50:29

标签: java android timer sync

我知道计时器通过使线程休眠x个时间来工作但是我想知道是否存在某种不在UI线程的线程上运行的计时器。我想过使用一个不断比较系统时间的循环(以毫秒为单位),但是我想把它作为最后的手段,因为它看起来效率不高。

编辑:

堆栈跟踪:

val someValue: String = "key" 
val someOtherValue: Double = 0.1 

val P: Map[String, Map[String, Map[String, Double]]] =
  HashMap("a" -> HashMap(
    "aa" -> HashMap(
      "aaa" -> 0.25,
      "aab" -> 1 // implicitly converted to Double
    ),
    "ab" -> HashMap(
      "aba" -> 0.2,
      "abb" -> 0.8)
    ),
    "b" -> HashMap(
      "ba" -> HashMap(
        "baa" -> -0.3,
        "bab" -> -0.4,
        "bac" -> -0.2
      ),
      "bb" -> HashMap(
        // would not compile, though it would compile in the original example
        // messing up the result type completely and good luck finding this
        // with the original formatting
        /* someOtherValue -> someValue, */
        "bba" -> 0.3,
        "bbb" -> 0.4,
        "bbc" -> 0.4
      )
    ),
    "c" -> HashMap(
      "ca" -> HashMap(
        "caa" -> 0.2,
        "cab" -> 0.001
      ),
      "cb" -> HashMap() // Map[String, Double] inferred
    )
  )


val m = P("a")("aa")("aab") // -> 1.0
val m2 = P("a")("ab")("aba") // -> 0.2

相关代码:

07-25 14:38:38.037  22108-22124/com.example.myapp E/ViewRootImpl﹕ com.example.myapp.Main : Only the original thread that created a view hierarchy can touch its views.
java.lang.RuntimeException
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6355)
        at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:929)
        at android.view.ViewGroup.invalidateChildFast(ViewGroup.java:4466)
        at android.view.View.invalidateViewProperty(View.java:11112)
        at android.view.View.setTranslationY(View.java:10472)
        at android.view.View.setY(View.java:10400)
        at com.example.myapp.Player.update(Player.java:29)
        at com.example.myapp.Main.update(Main.java:70)
        at com.example.myapp.Main.access$000(Main.java:15)
        at com.example.myapp.Main$1.run(Main.java:33)
        at java.util.Timer$TimerImpl.run(Timer.java:284)
如果你想知道,

playerVisual是一个ImageView。

3 个答案:

答案 0 :(得分:1)

这是一个基于AsyncTask的解决方案:

class AsyncTimer extends AsyncTask<Void, Void, Void>
{
    boolean alive = true;
    long startMS;
    long intervalMS;
    MainActivity activity;

    public AsyncTimer(long startMS, long intervalMS, MainActivity activity)
    {
        this.startMS = startMS;
        this.intervalMS = intervalMS;
        this.activity = activity;
    }

    protected Void doInBackground(Void... params)
    {
        try
        {
            Thread.sleep(startMS);
        }
        catch (Exception e)
        {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }

        while (alive)
        {
            try
            {
                alive = activity.updateUI();
                Thread.sleep(intervalMS);
            }
            catch (Exception e)
            {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
        }

        return null;
    }
}

在MainActivity中使用它:

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
...
        new AsyncTimer(0, 1000, this).execute();
    }

    public boolean updateUI()
    {
        Log.d("Timer", "tick");
...
        return true;
    }

答案 1 :(得分:0)

这是从计划任务更新GUI的解决方案。使用Handler而不是Timer

 final Handler handler = new Handler(); 
 final Runnable myRunnable = new Runnable()
{
public void run() 
{
    handler.postDelayed(myRunnable, 1000);  //1 second
    /*UPDATE GUI*/
    update();
}
};
myRunnable.run();

答案 2 :(得分:-1)

你基本上想要阻止当前线程/等待条件 - 好吧 有几种选择 - 最简单的方法是使用Semaphore

final Semaphore semaphore = new Semaphore(0); //not available at first
try
{
   semaphore.tryAcquire(1, TimeUnit.SECONDS); //block for 1 second since it isnt available
}
catch(InterruptedException ex)
{
   //do something sensible here
}

另一个选项是CountDownLatch

final CountDownLatch latch = new CountDownLatch(1); //1 latch available
try
{
   latch.await(1, TimeUnit.SECONDS) //since currently one latch is available this will timeout
}
catch(InterruptedException ex)
{
   //do something sensible here
}

当然:这有点滥用这些课程,但它的工作完美无缺。 你甚至可以使用Object.wait但是因为一个对象可以接收到#e;的虚假唤醒&#34;你将不得不处理那些 - 这并不像最初看起来那么容易。

基本上,您可以使用几乎任何机制,让您可靠地等待&#34;关于某事 - 直到你的下一个时间片准备好被采取(因此:某事物超时)并继续你的循环。

在Java之外的语言中,它可以(可靠地)暂停/暂停当前线程一段固定的时间 - 这甚至更好但是它打破了相当多的编程范例并且很难理解;最好不要触及线程本身,除非你真正经验丰富且对这些事情有很多了解,阻塞方法调用几乎总是最好的选择,即使这意味着编写一些额外的代码行。