0

Basically, I need to use a TimerTask inside a fragment but this error appears:

04-04 15:01:02.710 28397-28528/com.example.sdilab.pap E/AndroidRuntime: FATAL EXCEPTION: Timer-1
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5471)
    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1007)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.support.v4.widget.DrawerLayout.requestLayout(DrawerLayout.java:1255)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:334)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:334)
    at android.view.View.requestLayout(View.java:15850)
    at android.view.View.requestLayout(View.java:15850)
    at android.widget.TextView.checkForRelayout(TextView.java:6615)
    at android.widget.TextView.setText(TextView.java:3753)
    at android.widget.TextView.setText(TextView.java:3608)
    at android.widget.TextView.setText(TextView.java:3583)
    at com.example.sdilab.pap.StepsFragment$1.run(StepsFragment.java:87)
    at java.util.Timer$TimerImpl.run(Timer.java:284)

And this is the code that I need to use:

timer.schedule( new TimerTask() {
            public void run() {
                double value = Double.parseDouble(readFromFile());
                String roundedvalue = Math.round(passos) + "";
                textView.setText(roundedvalue);

            }
        }, 0, 1*1000);

My question is: How can I use this code / achieve the same result so I can use this code inside my fragment?

Tom Sabel
  • 3,935
  • 33
  • 45
António Paulo
  • 351
  • 3
  • 18

3 Answers3

1

Use runOnUiThread() method to update TextView

timer.schedule( new TimerTask() {
                public void run() {
                    double value = Double.parseDouble(readFromFile());
                    String roundedvalue = Math.round(passos) + "";

         runOnUiThread(new Runnable() {
                public void run() {
                   textView.setText(roundedvalue);  
                 }
             });



                }
            }, 0, 1*1000);
N J
  • 27,217
  • 13
  • 76
  • 96
0

Your problem is that you are trying to update your views outside of the main thread. An easy way to deal with this is to use a handler to ensure that you are updating your views in the right way. Here's an example:

private Handler updateHandler = new Handler();

timer.schedule( new TimerTask() {
        public void run() {
            double value = Double.parseDouble(readFromFile());
            String roundedvalue = Math.round(passos) + "";
            updateHandler.postRunnable(new Runnable() {
                public void run() {
                    textView.setText(roundedvalue); 
                }
            });
        }
    }, 0, 1*1000);

There is also a runOnUiThread() method, if you are inside an activity, that will do the same.

Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
0

You can also use this code. This should be done inside the onCreateView method. Fir example, I want a ViewPager to automatically move to the next slide, wait for 6 seconds and slide to the next content.

//Create a new Timer and Handler object
Timer timer = new Timer;
Handler updateSlide = new Handler();
private static int delay = 300; //delay before moving to the next slide.
private static int wait = 6000;
timer.schedule(new TimerTask (){
   @Override
   public void run (){
      //gets the list, and puts the last into the front
      updateSlide.postAtFrontOfQueue(new Runnable(){ 

       @Override
       public void run (){

         if(viewPager.getCurrentItem() < sliderList.size() -1){

            viewPager.setCurrentItem(viewPager.getCurrentItem() +1);

         }
         else{

              viewPager.setCurrentItem(0);

         }

       }

      });
   }
}, delay, wait);

With this, I hope you understand it. This code give you the privilege to use a TimerTask inside a Fragment with the Use of Handler(). In an Activity, using the MainActivity.runOnUiThread(nee Runnable().... Works very fine.

So I suggest you use the above code sample in your fragments. Thanks.