-2

I'm trying to change button colour dynamically, so I created a thread to do it but following error is coming

W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setBackgroundColor(int)' on a null object reference

the following is my code

public class MainActivity extends AppCompatActivity implements View.OnClickListener,Runnable {
Button b1, b2, b3, b4;
Random r = new Random();
int random_selection;
Thread t1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    b1 = (Button) findViewById(R.id.button);
    b2 = (Button) findViewById(R.id.button2);
    b3 = (Button) findViewById(R.id.button3);
    b4 = (Button) findViewById(R.id.button4);
    b1.setBackgroundColor(Color.BLUE);
    b2.setBackgroundColor(Color.BLUE);
    b3.setBackgroundColor(Color.BLUE);
    b4.setBackgroundColor(Color.BLUE);
    b1.setOnClickListener(this);
    b2.setOnClickListener(this);
    b3.setOnClickListener(this);
    b4.setOnClickListener(this);
    delay(7000);

    main();


}

private void main() {
    // Thread t1 = new Thread(new MainActivity());
    // this wi run() function
    t1 = new Thread(new MainActivity());
    System.out.println("inside main");
    t1.start();
    System.out.println("after t1.start()");

}

@Override
public void onClick(View v) {

    switch (v.getId()) {

        case R.id.button:

            break;
        case R.id.button2:

            break;
        case R.id.button3:

            break;
        case R.id.button4:

            break;


        default:
            android.widget.Toast.makeText(getBaseContext(), "Wrong Selection",
                    android.widget.Toast.LENGTH_SHORT).show();
            break;
    }

}


public int randomgen() {

    random_selection = r.nextInt(4) + 1;
    return random_selection;
}

public void delay(int t) {
    try {
        Thread.sleep(t);
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}


//@Override•
public void run() {
    try {
        System.out.println("inside run");
        int x, count = 0;
        for (; ; ) {

            count = count + 1;
            x = randomgen();
            //     android.widget.Toast.makeText(getBaseContext(), x,android.widget.Toast.LENGTH_SHORT).show();
            if (x == 1) {
              b1.setBackgroundColor(Color.BLACK);
                delay(5000);
              b1.setBackgroundResource(android.R.drawable.btn_default);
                System.out.println(this.b1);
            } else if (x == 2) {
              b2.setBackgroundColor(Color.BLACK);
                delay(5000);
              b2.setBackgroundResource(android.R.drawable.btn_default);
                System.out.println(this.b2);
            } else if (x == 3) {
              b3.setBackgroundColor(Color.BLACK);
                delay(5000);
              b3.setBackgroundResource(android.R.drawable.btn_default);
                System.out.println(this.b3);
            } else if (x == 4) {
              b4.setBackgroundColor(Color.BLACK);
                delay(5000);
              b4.setBackgroundResource(android.R.drawable.btn_default);
                System.out.println(this.b4);

            }

            if (count == 4) {
                break;
            }
        }

    } catch (Exception e) {
        System.out.println("inside catch");
        e.printStackTrace();
    }
}

}

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.hellotape.hdl.test_bomber.MainActivity">

    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_marginStart="51dp"
        android:layout_marginTop="127dp"
        android:id="@+id/button"
        android:visibility="visible" />

    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="52dp"
        android:id="@+id/button2" />

    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_alignEnd="@+id/button"
        android:layout_marginTop="113dp"
        android:id="@+id/button3" />

    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button3"
        android:layout_alignEnd="@+id/button2"
        android:id="@+id/button4"
        android:elevation="5dp" />

</RelativeLayout>

While debugging I got that as soon as I enter thread t1, the button variables b1,b2,b3,b4 become null, what is the reason of this error and how to solve it?

2 Answers2

0

You have 2 objects of MainActivity. First your app will start onCreate() and your fields will be initialized. Then you call new Thread(new MainActivity()) which means you create a new object of MainActivity. Then you access the buttons of the thread which are not initialized because if you call new MainActivity the onCreate() won't be called.

beeb
  • 1,615
  • 1
  • 12
  • 24
0

Basically MainActivity is running in UI thread, all buttons are accessible in UI thread. Since we started new thread and we are trying to modify buttons property in that, buttons will not be accessible. If we are to modifying any UI elements we have to do it using Handler or runOnUiThread, like below

someActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
           // Code here will run in UI thread
        }
});

or

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Update UI elements in run().

Nagesh Jatagond
  • 344
  • 2
  • 13