Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/233.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android-创建同步计时器_Java_Android_Timer_Sync - Fatal编程技术网

Java Android-创建同步计时器

Java Android-创建同步计时器,java,android,timer,sync,Java,Android,Timer,Sync,我知道计时器的工作原理是让线程睡眠x个时间,但我想知道是否有某种计时器不在非UI线程的线程上运行。我曾考虑过使用一个循环,以毫秒为单位不断比较系统时间,但我想将其作为最后手段,因为它似乎不是很有效 编辑: 堆栈跟踪: 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 hiera

我知道计时器的工作原理是让线程睡眠x个时间,但我想知道是否有某种计时器不在非UI线程的线程上运行。我曾考虑过使用一个循环,以毫秒为单位不断比较系统时间,但我想将其作为最后手段,因为它似乎不是很有效

编辑:

堆栈跟踪:

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)
相关代码:

if (!onGround){

        playerVisual.setY(playerVisual.getY() + this.gravity);

    }

    if (playerVisual.getY() >= this.main.getDevice().getHeight() - 10){
        this.onGround = true;
    }
    else {
        this.onGround = false;
    }

playerVisual是一个图像视图,如果您想知道的话。

您基本上希望阻止当前线程/等待条件-好的 有几个选项-最简单的是使用:

另一个选择是:

当然:这有点滥用这些类,但它工作得很完美。 你甚至可以使用,但由于一个对象可以接收“虚假唤醒”,你必须处理这些-这并不总是像一开始看起来那么容易

基本上,您可以使用几乎所有的机制来可靠地“等待”某件事情,直到您的下一个时间片准备就绪(因此:某件事情超时)并继续在您的循环中


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

你基本上想要阻止当前线程/等待一个条件-好的 有几个选项-最简单的是使用:

另一个选择是:

当然:这有点滥用这些类,但它工作得很完美。 你甚至可以使用,但由于一个对象可以接收“虚假唤醒”,你必须处理这些-这并不总是像一开始看起来那么容易

基本上,您可以使用几乎所有的机制来可靠地“等待”某件事情,直到您的下一个时间片准备就绪(因此:某件事情超时)并继续在您的循环中


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

这是一个从计划任务更新GUI的解决方案。使用处理器而不是计时器

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

这是一个从计划任务更新GUI的解决方案。使用处理器而不是计时器

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

这是一个基于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;
    }
}

这是一个基于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;
    }
}

Swing有一个
Timer
类,该类在Swing的主线程上运行事件(该线程不是
main
运行的线程)@immibis有没有不使用Swing的方法来执行此操作?取决于您尝试执行的操作。没有单一简单方法的原因是:当计时器用完时,如果线程忙于做其他事情,会发生什么?您试图解决的实际问题是什么?为什么您关心计时器线程不是主线程?好的。然后在你的问题上添加android标记,将“主线程”替换为“UI线程”(这两个是完全不同的事情),为你的问题添加相关的代码,以及完整的堆栈跟踪,这样我们可以帮助你理解你做错了什么,以及如何修复它。Swing有一个
Timer
类,可以在Swing的主线程上运行事件(它不是运行在上的
main
)@immibis有没有一种不使用Swing的方法可以做到这一点?这取决于你正在尝试做什么。没有单一简单方法的原因是:当计时器用完时,如果线程正在忙于做其他事情会发生什么?你试图解决的实际问题是什么?为什么你关心计时器线程不是主线程?好的。然后添加android标记您的问题,将“主线程”替换为“UI线程”(这两个是完全不同的事情),将相关代码添加到您的问题中,并添加完整的堆栈跟踪,以便我们可以帮助您了解您做错了什么,以及如何修复它。这是有效的:)但是有没有一种方法可以让它重复而不仅仅是延迟?@ReadySetPawn一种方法是做一个堆栈。这是可行的:)但是有没有一种方法可以让它重复而不仅仅是延迟?@ReadySetPawn一种方法是做一个堆栈。
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
...
        new AsyncTimer(0, 1000, this).execute();
    }

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