【问题标题】:Run loop every second java每秒运行一次循环java
【发布时间】:2023-03-11 21:04:01
【问题描述】:
int delay = 1000; // delay for 1 sec. 
int period = 10000; // repeat every 10 sec. 
Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new TimerTask() 
    { 
        public void run() 
        { 
            displayData();  // display the data
        } 
    }, delay, period);  

其他:

while(needToDisplayData)
{
    displayData(); // display the data
    Thread.sleep(10000); // sleep for 10 seconds
}   

它们都不起作用(应用程序被强制关闭)。我还可以尝试哪些其他选择?

【问题讨论】:

  • 提及异常或记录猫
  • 请显示logcat错误
  • 你应该在后台线程中这样做......

标签: java android


【解决方案1】:

您的代码失败,因为您在后台线程中执行睡眠,但显示数据必须在 UI 线程中执行。

您必须从 runOnUiThread(Runnable) 运行 displayData 或定义处理程序并向其发送消息。

例如:

(new Thread(new Runnable()
        {

            @Override
            public void run()
            {
                while (!Thread.interrupted())
                    try
                    {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() // start actions in UI thread
                        {

                            @Override
                            public void run()
                            {
                                displayData(); // this action have to be in UI thread
                            }
                        });
                    }
                    catch (InterruptedException e)
                    {
                        // ooops
                    }
            }
        })).start(); // the while thread will start in BG thread

【讨论】:

  • 你能解释一下吗?您的回答将被接受,因为它有效,但我想了解它。
  • 所有 UI 更改都必须在主 UI 线程中,因为后台线程是异步的,无法在 UI 中执行更改(并且 ui 线程是同步的,因此如果您在此线程中启动耗时的操作,所有按钮、视图和其他 UI 元素甚至整个手机都会被冻结,因为系统无法处理界面操作(点击等)。 runOnUiTThread 在 UI 线程中启动此函数的主体,从那里您必须避免繁重的操作,只进行更改和处理 UI 操作。检查:stackoverflow.com/questions/3652560/…
  • 你的应用程序崩溃了,异常如下:stackoverflow.com/questions/5161951/… .
  • 您可以将线程(第一行的新线程)保存在变量中,然后中断它。
  • 例如最终线程 myThread = new Thread(new Runnable(...)); myThread.start();从你的方法中你可以调用 myThread.interrupt();
【解决方案2】:

使用从您的任何ViewHandler 访问的onPostDelayed()。通过不创建Timer 或新的Thread 来节省内存。

private final Handler mHandler = new Handler();

private final Runnable mUpdateUI = new Runnable() {
    public void run() {
        displayData();
        mHandler.postDelayed(mUpdateUI, 1000); // 1 second
        }
    }
};

mHandler.post(mUpdateUI);

【讨论】:

  • 这种方法是错误的,我试过这个......它有时会大量添加值,有时会添加少量
【解决方案3】:

试试这个:

@Override                    
    public void run() {   
            TextView tv1 = (TextView) findViewById(R.id.tv);
            while(true){
               showTime(tv1);                                                                
               try {
                   Thread.sleep(1000);
               }catch (Exception e) {
                   tv1.setText(e.toString());
               }           
            } 
    }       

你也可以试试这个

您还可以使用另一种方法在特定时间间隔内更新 UI。以上两个选项都是正确的,但取决于您可以使用替代方法在特定时间间隔更新 UI 的情况。

首先声明一个全局变量供 Handler 从 Thread 更新 UI 控件,如下所示

处理程序 mHandler = new Handler(); 现在创建一个 Thread 并使用 while 循环使用线程的 sleep 方法定期执行任务。

new Thread(new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                try {
                    Thread.sleep(10000);
                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            // Write your code here to update the UI.
                        }
                    });
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        }
    }).start();

【讨论】:

  • 如果我们想在非 UI 线程中使用你的代码的第一部分,它会导致异常。因为您尝试更改属于UITextView 的文本值。请编辑您的代码,并在 UI 线程上执行 setText。
【解决方案4】:

你犯了几个错误:

  1. 你不应该在主线程上调用 Thread.sleep() (你也不应该长时间阻塞它)。一旦主线程被阻塞超过 5 秒,就会发生 ANR(应用程序无响应)并被强制关闭。

  2. 你应该避免在 android 中使用 Timer。改用处理程序。 handler 的好处是它是在主线程上创建的 -> 可以访问 Views(不像 Timer,它在自己的线程上执行,不能访问 Views)。

    class MyActivity extends Activity {
    
        private static final int DISPLAY_DATA = 1;
        // this handler will receive a delayed message
        private Handler mHandler = new Handler() {
            @Override
            void handleMessage(Message msg) {
                if (msg.what == DISPLAY_DATA) displayData();
            }
         };
    
         @Override
         void onCreate(Bundle b) {
             //this will post a message to the mHandler, which mHandler will get
             //after 5 seconds
             mHandler.postEmptyMessageDelayed(DISPLAY_DATA, 5000);
         }
     } 
    

【讨论】:

    【解决方案5】:

    当我试图解决无法在 Android 的 DigitalClock 小部件中隐藏秒数的问题时,我遇到了这个线程。 DigitalClock 现在已弃用,现在推荐使用的小部件是 TextClock。这对旧 API 不起作用......因此我不得不编写自己的 24 小时制时钟。我不知道这是否是一个好的实现,但它似乎有效(并且每秒更新一次):

        import java.util.Calendar;
    
        import android.os.Handler;
        import android.view.View;
        import android.widget.TextView;
    
    
        /**
         * A 24 hour digital clock represented by a TextView
         * that can be updated each second. Reads the current
         * wall clock time.
         */
        public class DigitalClock24h {
    
                private TextView mClockTextView; // The textview representing the 24h clock
                private boolean mShouldRun = false; // If the Runnable should keep on running
    
                private final Handler mHandler = new Handler();
    
                // This runnable will schedule itself to run at 1 second intervals
                // if mShouldRun is set true.
                private final Runnable mUpdateClock = new Runnable() {
                        public void run() {
                                if(mShouldRun) {
                                        updateClockDisplay(); // Call the method to actually update the clock
                                        mHandler.postDelayed(mUpdateClock, 1000); // 1 second
                                }
                        }
                };
    
    
                /**
                 * Creates a 24h Digital Clock given a TextView.
                 * @param clockTextView
                 */
                public DigitalClock24h(View clockTextView) {
                        mClockTextView = (TextView) clockTextView;
                }
    
                /**
                 * Start updating the clock every second.
                 * Don't forget to call stopUpdater() when you
                 * don't need to update the clock anymore.
                 */
                public void startUpdater() {
                        mShouldRun = true;
                        mHandler.post(mUpdateClock);
                }
    
                /**
                 * Stop updating the clock.
                 */
                public void stopUpdater() {
                        mShouldRun = false;
                }
    
    
                /**
                 * Update the textview associated with this
                 * digital clock.
                 */
                private void updateClockDisplay() {
    
                        Calendar c = Calendar.getInstance();
                        int hour = c.get(Calendar.HOUR_OF_DAY); // 24 hour
                        int min = c.get(Calendar.MINUTE); 
    
                        String sHour;
                        String sMin;
    
                        if(hour < 10) {
                                sHour = "0" + hour;
                        } else sHour = "" + hour;
    
                        if(min < 10) {
                                sMin = "0" + min;
                        } else sMin = "" + min;
    
                        mClockTextView.setText(sHour + ":" + sMin);
                }
    
        }
    

    感谢 biegleux 为我指出正确的方向!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      相关资源
      最近更新 更多