0
votes

I'm practising an android app development and writing score board of billiards.

public class Board extends AppCompatActivity {
    private Rack rack;
    private int currentPlayer;

    public Board() {
        rack = new Rack();
        currentPlayer = 0;
    }

    public void setCurrentPlayer(int n) {
        currentPlayer = n;
    }

    public void pocket(int ballNumber) {
        TextView scoreView = (TextView) findViewById(R.id.pocketed0);
        scoreView.setText("FOO");
    }
}

Having instantiated this board in MainActivity,

public class MainActivity extends AppCompatActivity {
    Board board;

    String pocketedHistory = "";
    String pointString = "";
    int points = 0;
    String selectedPocket = "S";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        board = new Board();
    }


    public void pocket5(View v) {
        board.pocket(5);
    }

pocket5() is called when I tap a button and this exception was raised.

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.android.japan9_ballscorer, PID: 10399 java.lang.IllegalStateException: Could not execute method for android:onClick at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414) at android.view.View.performClick(View.java:4473) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992) at android.view.View$PerformClick.run(View.java:18799) at android.os.Handler.handleCallback(Handler.java:808) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5341) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409) at android.view.View.performClick(View.java:4473)  at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)  at android.view.View$PerformClick.run(View.java:18799)  at android.os.Handler.handleCallback(Handler.java:808)  at android.os.Handler.dispatchMessage(Handler.java:103)  at android.os.Looper.loop(Looper.java:193)  at android.app.ActivityThread.main(ActivityThread.java:5341)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:515)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)  at dalvik.system.NativeStart.main(Native Method)  Caused by: java.lang.NullPointerException at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152) at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:103) at android.content.Context.obtainStyledAttributes(Context.java:389) at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:839) at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:806) at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:630) at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:223) at com.example.android.japan9_ballscorer.Board.pocket(Board.java:21) at com.example.android.japan9_ballscorer.MainActivity.pocket5(MainActivity.java:27) at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:515)  at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)  at android.view.View.performClick(View.java:4473)  at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)  at android.view.View$PerformClick.run(View.java:18799)  at android.os.Handler.handleCallback(Handler.java:808)  at android.os.Handler.dispatchMessage(Handler.java:103)  at android.os.Looper.loop(Looper.java:193)  at android.app.ActivityThread.main(ActivityThread.java:5341)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:515)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)  at dalvik.system.NativeStart.main(Native Method) 

Could anyone shed a light about this? I'm at a loss what to do..

3
Thank you all for your answers. Am so impatient that stopped a video of Udacity and started writing. I thought it would be intuitive and straightforward for me to have Board object access views by findViewById(). That's why I stupidly had Board extend AppCompatActivity. - uemurm

3 Answers

2
votes

you have:

public class Board extends AppCompatActivity 
...

but you don't have an onCreate or a setContentView, which is why your app is crashing. this leads me to believe that you don't have a complete understanding of what exactly is an activity


board = new Board();

you shouldn't be creating a new instance of an activity like this either, you have to launch an activity using an intent

0
votes

I guess you are new in android the things are not correct you need to learn more.

For this problem you can try like this:-

    public class Board{
    private Rack rack;
    private int currentPlayer;

    public Board() {
        rack = new Rack();
        currentPlayer = 0;
    }

    public void setCurrentPlayer(int n) {
        currentPlayer = n;
    }

    public String pocket(int ballNumber) {
        return "FOO";
    }
}

Your Activity would be like this:-

 public class MainActivity extends AppCompatActivity {
    Board board;

    String pocketedHistory = "";
    String pointString = "";
    int points = 0;
    String selectedPocket = "S";
    TextView scoreView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        scoreView = scoreView.findViewById(R.id.pocketed0);
        board = new Board();

    }

    public void pocket5(View v) {
        scoreView.setText(board.pocket(5));
    }
}
-1
votes

The problem here is usage and understanding of Activities and Classes. Your Board class doesn't need to be an Activity just to use the findViewById parameter. What you can do is pass the context of the MainActivity to the Board class as a constructor parameter.

Modify Board class as this:

public class Board {
    private Rack rack;
    private int currentPlayer;
    private Activity mActivity;

    public Board(Activity activity) {
        mActivity = activity;
        rack = new Rack();
        currentPlayer = 0;
    }

    public void setCurrentPlayer(int n) {
        currentPlayer = n;
    }

    public void pocket(int ballNumber) {
        TextView scoreView = (TextView) 
        mActivity.findViewById(R.id.pocketed0);
        scoreView.setText("FOO");
    }
}

And modify your MainActivity as such:

public class MainActivity extends AppCompatActivity {
    Board board;

    String pocketedHistory = "";
    String pointString = "";
    int points = 0;
    String selectedPocket = "S";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        board = new Board(this);
    }


    public void pocket5(View v) {
        board.pocket(5);
    }
}