简体   繁体   English

Android 开发:在 UI 线程中运行 TimerTask

[英]Android Dev: Run TimerTask in UI Thread

Im trying to update a TextView .我正在尝试更新TextView

This method is located in my Main Class and it is called in onCreate() ;此方法位于我的 Main Class 中,并在onCreate()中调用;

I have tried using runOnUiThread() to no avail..我试过使用runOnUiThread()无济于事..

As soon as the 30 seconds is reached and it tries to update the TextView it crashes!一旦达到 30 秒并尝试更新 TextView,它就会崩溃!

Any help is appreciated:任何帮助表示赞赏:

public void updateDisplay() {
    Timer timer = new Timer();


    timer.schedule(new TimerTask() {


                       public void run() {
                           Calendar c = Calendar.getInstance();
                           int mYear = c.get(Calendar.YEAR);
                           int mMonth = c.get(Calendar.MONTH);
                           int mDay = c.get(Calendar.DAY_OF_MONTH);
                           int mHour = c.get(Calendar.HOUR_OF_DAY);
                           int mMinute = c.get(Calendar.MINUTE);

                           textView3.setText(new StringBuilder()
                                   // Month is 0 based so add 1
                                   .append(mDay).append("/")
                                   .append(mMonth + 1).append("/")
                                   .append(mYear)
                                   .append(" - ")
                                   .append(mHour)
                                   .append(":")
                                   .append(mMinute));
                       }
                   }

            ,0,30000);//Update text every 30 seconds
}

And the error is:错误是:

E/AndroidRuntime: FATAL EXCEPTION: Timer-0
              Process: ggrgroup.com.workforceapp, PID: 21879
              android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7261)
                  at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1100)
                  at android.view.ViewGroup.invalidateChild(ViewGroup.java:5219)
                  at android.view.View.invalidateInternal(View.java:12900)
                  at android.view.View.invalidate(View.java:12860)
                  at android.view.View.invalidate(View.java:12844)
                  at android.widget.TextView.checkForRelayout(TextView.java:7459)
                  at android.widget.TextView.setText(TextView.java:4390)
                  at android.widget.TextView.setText(TextView.java:4247)
                  at android.widget.TextView.setText(TextView.java:4222)
                  at ggrgroup.com.workforceapp.MainActivity$1.run(MainActivity.java:77)
                  at java.util.Timer$TimerImpl.run(Timer.java:284)
    public void updateDisplay() {   
      Timer timer = new Timer();
      timer.schedule(new TimerTask() {

    @Override
    public void run() {
        // Your logic here...

        // When you need to modify a UI element, do so on the UI thread. 
        // 'getActivity()' is required as this is being ran from a Fragment.
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // This code will always run on the UI thread, therefore is safe to modify UI elements.
                myTextBox.setText("my text");
            }
        });
    }
}, 0, 30000); // End of your timer code.   

 }

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触其视图。

because you edit textView3 in thread因为你在线程中编辑 textView3

try it:尝试一下:

public void updateDisplay() { Timer timer = new Timer(); public void updateDisplay() { 计时器 timer = new Timer();

timer.schedule(new TimerTask(){


    public void run() {

        runOnUiThread(new Runnable(){
            @Override
            public void run() {
                Calendar c = Calendar.getInstance();
                int mYear = c.get(Calendar.YEAR);
                int mMonth = c.get(Calendar.MONTH);
                int mDay = c.get(Calendar.DAY_OF_MONTH);
                int mHour = c.get(Calendar.HOUR_OF_DAY);
                int mMinute = c.get(Calendar.MINUTE);

                textView3.setText(new StringBuilder()
                    // Month is 0 based so add 1
                    .append(mDay).append("/")
                    .append(mMonth + 1).append("/")
                    .append(mYear)
                    .append(" - ")
                    .append(mHour)
                    .append(":")
                    .append(mMinute));
            }
        });

    }
}

, 0, 30000);//Update text every 30 seconds

} }

Use a handler as stated by @Ezio使用@Ezio 所述的处理程序

Handler handler = new Handler(Looper.getMainLooper());
    
Runnable runnable = new Runnable() {

    public void run() {
        Calendar c = Calendar.getInstance();
        int mYear = c.get(Calendar.YEAR);
        int mMonth = c.get(Calendar.MONTH);
        int mDay = c.get(Calendar.DAY_OF_MONTH);
        int mHour = c.get(Calendar.HOUR_OF_DAY);
        int mMinute = c.get(Calendar.MINUTE);

        textView3.setText(new StringBuilder()
            // Month is 0 based so add 1
            .append(mDay).append("/")
            .append(mMonth + 1).append("/")
            .append(mYear)
            .append(" - ")
            .append(mHour)
            .append(":")
            .append(mMinute));

        //repeat every 30secs
        handler.postDelayed(this, 30000);
    }
}

handler.postDelayed(runnable, 30000);
  • Looper.getMainLooper() will run the runnable on the UI Thread Looper.getMainLooper()将在 UI 线程上运行 runnable
  • handler.postDelayed(this, 30000); will make it repeat every 30secs将使其每 30 秒重复一次

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM