runOnUiThread()在使用Thread.sleep()

时间:2017-05-06 21:10:45

标签: android multithreading

我使用的代码如下:

_thread = new Thread(){
            @Override
            public void run() {
                try {
                    while (true) {
                        operate();
                        Thread.sleep(DELAY);
                    }
                } catch (InterruptedException e) {
                    // Doesn't matters...
                }
            }
  };

操作函数如下所示:

    // does things....
    activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            // adds an ImageView to the screen
        }
    });
    // does other things...

在底线,我想要实现的是偶尔发生的操作,不会中断主线程和UI,比如游戏循环。

在运行()的前2次运行中,它添加了ImageView,一切正常,但是在2或3次后它停止添加ImageViews,但UI仍然照常运行。当我调试问题时,我发现3次之后不再调用Runnable的run()方法,甚至认为操作函数被调用了。

有线的东西(对我而言)是当我删除Thread.sleep时,一切正常(当然要快得多......)。我尝试用很长的for循环替换它(仅用于检查)并且它有效,但当然它不适合解决问题。

我读到了这个问题,大多数提出这个问题的人在主线程上做了一个thread.sleep或一个无限循环,但是,正如我所看到的,我没有做过这样的事情。很多人写道你应该用Handler.postDelayed替换Thread.sleep。我试图这样做,但它没有用,也许我做错了。我甚至尝试用我在互联网上找到的其他选项替换runOnUiThread,但所有这些选项都给了我相同的结果。我试图替换我将视图添加到活动的方法,但所有这些方法再次给出了相同的结果。

等待对此应用程序至关重要。我必须找到一种方法来等待某个时间然后在UI线程上执行一个函数,因为这个模式在我的应用程序中至少返回了几次。

2 个答案:

答案 0 :(得分:2)

听起来你想要一个帖子延迟,以便你可以在延迟一段时间后在UI线程上执行代码。 Handler Post Delay

private static final int DELAY = 500;
private Handler mHandler;
private Runnable mRunnable;

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

    start();
}

private void start()
{
    mHandler = new Handler();
    mRunnable = new MyRunnable(this);
    mHandler.postDelayed(mRunnable, DELAY);
}

private void stop()
{
    mHandler.removeCallbacks(mRunnable);
}

private void doSomething()
{
    // Do your stuff here.

    // Reschedule.
    mHandler.postDelayed(mRunnable, DELAY);
}

创建Runnable的推荐方法。

private static class MyRunnable implements Runnable
{
    private WeakReference<MainActivity> mRef;

    // In here you can pass any object that you need.
    MyRunnable(MainActivity activity)
    {
        mRef = new WeakReference<MainActivity>(activity);
    }

    @Override
    public void run()
    {
        // Safety check to avoid leaking.
        MainActivity activity = mRef.get();
        if(activity == null)
        {
            return;
        }

        // Do something here.
        activity.doSomething();
    }
}

答案 1 :(得分:0)

可能有几个原因导致UI Runnable没有被执行。可能activity变量有些东西搞砸了,或者它错误地引用了上下文,或者正如你所说Thread.sleep()可能导致问题。此时需要查看更多代码部分以更好地解决问题。

实现逻辑的更好方法是使用预定的Timer,而不是使用带有Thread.sleep()的无限循环。它将在后台线程中执行代码。然后使用Handler更新UI而不是activity.runOnUiThread()。这是一个例子:

// Global variable within the activity
private Handler handler;

// Activity's onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
    handler = new Handler(getMainLooper());
    Timer timer = new Timer("ScheduledTask");
    // Timer must be started on the Main UI thread as such.
    timer.scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            operate();
        }
    }, 0L, DELAY);
}

private void operate() {
    // does things in background....
    handler.post(new Runnable() {
        @Override
        public void run() {
            // adds an ImageView to the screen from within the Main UI thread
        }
    });
    // does other things in the background...
}