【问题标题】:Android view updater thread allowing view to update only once every N milliseconds and only on demandAndroid 视图更新线程允许视图每 N 毫秒仅更新一次,并且仅按需更新
【发布时间】:2017-04-20 15:21:59
【问题描述】:

我有一个线程要等待事件发生。当通知该线程时,我希望它唤醒,如果它比 REFRESH_TIME 长,那么它将通过调用 postInvalidate 使视图无效。否则它将在下一个 REFRESH_TIME 时休眠。同时,如果其他事件试图通知它绘制,则应设置一些标志,以便在下一个 REFRESH_TIME 再次过去后立即重新绘制。否则,它将无限期地等待直到下一次通知(或请求停止,但为简单起见忽略该部分)。

我试图在带有等待和通知的同步锁中开发它,但我似乎不能只使用它。对于 c++,我想到了带有超时的 WaitForSingleObject,但是在 java 中我还没有机会做类似的事情。最适合这个问题的用途是什么?

如果我在运行更新时收到 100 条通知,我应该将它们视为单个通知并仅添加一个无效通知,在下一个通知后下降 REFRESH_TIME 毫秒。换一种说法。不能错过更新。

这里有一些不完整的代码。我怎么能完成它?

public class ViewInvalidator extends Thread {

private View m_view;

Object lock = new Object();
boolean ready = false;
long m_refreshTimeMilliseconds;
boolean m_threadRequestedToStop = false;

public ViewInvalidator(View view, long refreshTimeMilliseconds) {

    m_view = view;
    m_refreshTimeMilliseconds = refreshTimeMilliseconds;
}

public void postInvalidate() {

    synchronized(lock) {

        ready = true;
        lock.notifyAll();
    }
}

public void stopThread() {

    synchronized (lock) {

        while(!ready)
            lock.notifyAll();
    }
}

@Override
public void run() {

    long lastPostInvalidate = System.currentTimeMillis(), timeSince;

    while(true) {

        if (this.m_threadRequestedToStop)
            break;

        try {

            synchronized (lock) {

                while (!ready)
                    lock.wait();

            }
        } catch(InterruptedException e) {

            System.out.println(e.getMessage());
            e.printStackTrace();
            break;
        }

        // someone just woke us up.  Check if it was a request to stop.  If it was, stop.
        if (this.m_threadRequestedToStop)
            break;

        // if less time than our refresh time, sleep for the difference, then invalidate.  Otherwise just invalidate.
        timeSince = System.currentTimeMillis() - lastPostInvalidate;
        if(timeSince < m_refreshTimeMilliseconds)
            try {
                Thread.sleep(m_refreshTimeMilliseconds - timeSince);
            } catch(InterruptedException e) {}

        m_view.postInvalidate();
    }
}

非常感谢, 迈克

【问题讨论】:

  • 你能更详细地描述这个线程的目的吗?目前还不清楚为什么你需要这个线程而不是仅仅使用阻塞或计时器
  • 我有一堆线程负责分别更新用户界面。我想合并他们的电话,以便他们在没有被 REFRESH_TIME 分隔时不会不必要地调用无效。更新线程将执行此操作并取消中间的额外线程,将它们视为 1,以便各个线程可以只说他们需要重绘。
  • 我理解那部分,但似乎没有理由为什么你不能只使用布尔值表示无效并在程序正常重绘时检查它
  • 我没看到。知道如何修改我添加到问题中的代码吗?
  • 我明天晚上会更多地探索你的代码,但是对于初学者来说,还没有睡觉,而且我认为这必须发生在某个地方......我自己的睡眠也会有所帮助。我很迷茫。 :)

标签: java multithreading invalidation throttling


【解决方案1】:
long lastPostInvalidate;
bool running;
bool valid;

public void f(){
if(running)if(!valid)synchronized(valid){valid=true;}
else {
running = true;
while(func()){};
running = false;
}

private bool func() {
synchronized (valid){valid = false;}
synchronized (lastPostInvalidate) {
long next = System.currentTimeMillis();
long x = next - timeSincelastPostInvalidate;
x = m_refreshTimeMilliseconds-x;
if(x>0)sleep(x);
m_view.postInvalidate();
timeSincelastPostInvalidate = next;
}return valid;
}

忘记了使用条件。它实际上应该看起来像这样。也就是说,如果您希望在更新中频繁更新,这样做可能会锁定您的更新线程,如果您还将这些线程用于其他事情,这将很重要。但是,如果您希望更新如此频繁,您不妨按照最初的计划使用该线程,但不要将其停用,并检查每个间隔是否需要运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 2011-12-07
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多