0

I'm new in Java programming for android and I have a trouble with Threads. I want to make a simple apk with counter. I want to increment counter and show value. Android Studio 3.4.2 JRE 1.8.0

enter image description here

there is my code:

public class MainActivity extends AppCompatActivity {
private Button my_button;
private boolean  start_stop = false;
private int counter = 0;
private TextView my_text;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    my_button = findViewById(R.id.My_Button);
    my_text = findViewById(R.id.my_text);
}
public void onClick_button(View view) {
    if(start_stop != true) {
        my_button.setText("STOP");
        start_stop = true;

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (start_stop) {
                    my_text.setText(Integer.toString(counter));
                    counter++;
                    try {
                        Thread.sleep(1000);     // sleep 1 sec
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }else {
        my_button.setText("START");
        start_stop = false;
    }
}
@Override
protected void onDestroy() {
    super.onDestroy();
    start_stop = false;
}
}

In this case i have a crash of my app with message "unfortunately, switch_picture has stopped". In Log cat i have this:

11-07 21:41:29.194 27684-27724/com.example.switch_pictures E/AndroidRuntime: FATAL EXCEPTION: Thread-416 Process: com.example.switch_pictures, PID: 27684 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357) at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909) at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690) at android.view.View.invalidateInternal(View.java:11801) at android.view.View.invalidate(View.java:11765) at android.view.View.invalidate(View.java:11749) at android.widget.TextView.checkForRelayout(TextView.java:6872) at android.widget.TextView.setText(TextView.java:4057) at android.widget.TextView.setText(TextView.java:3915) at android.widget.TextView.setText(TextView.java:3890) at com.example.switch_pictures.MainActivity$1.run(MainActivity.java:34) at java.lang.Thread.run(Thread.java:818) 11-07 21:41:29.867 27684-27702/com.example.switch_pictures D/EGL_emulation: eglMakeCurrent: 0xb432f100: ver 2 0 (tinfo 0xb429fdc0)

Kishan Viramgama
  • 893
  • 1
  • 11
  • 23
  • use a Handler https://stackoverflow.com/questions/15136199/when-to-use-handler-post-when-to-new-thread & https://stackoverflow.com/a/40058010/2308683 – OneCricketeer Nov 07 '19 at 23:06

1 Answers1

2

The problem with your code is that you are trying to interact with UI elements from a background thread. The solution is

new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (start_stop) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    my_text.setText(Integer.toString(counter));
                                }
                            });
                            counter++;
                            try {
                                Thread.sleep(1000);     // sleep 1 sec
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();

Here is the documentation of runOnUiThread

Amine
  • 2,241
  • 2
  • 19
  • 41