-1

My app crashes after clicking on the button when I call invalidate() to refresh the view. I can't figure out why. If I delete canvasView.invalidate(), the app does not crash. Is it allowed to call invalidate() from another class? I'm new to Android Studio. Surely, somebody can help me? EDIT: the problem is solved, the answer is below, and I added the LogCat.

Here is the code:

public class MainActivity extends AppCompatActivity implements 
View.OnClickListener {

    CanvasView canvasView;
    Button btnChangeColor;
    static boolean colorRed;

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

        CanvasView canvasView = new CanvasView(this, null);
        btnChangeColor = (Button) findViewById(R.id.button);

        btnChangeColor.setOnClickListener(this);

        colorRed = false;

    }

    @Override
    public void onClick(View v) {
        if(colorRed) {
            colorRed = false;
            canvasView.invalidate();
            return;
        }

        else {
            colorRed = true;
            canvasView.invalidate();
            return;
        }
    }
}




class CanvasView extends View {

    Paint paint;

    public CanvasView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        paint = new Paint();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if(MainActivity.colorRed == true)
            paint.setColor(Color.RED);
        else
            paint.setColor(Color.BLACK);

        paint.setStyle(Paint.Style.FILL);

        canvas.drawCircle(400, 400, 50, paint);
    }
}

LogCat:

05-31 21:10:41.341 27902-27902/? I/art: Late-enabling -Xcheck:jni Reinit property: dalvik.vm.checkjni= false

05-31 21:10:41.351 27902-27909/? I/art: Debugger is no longer active Starting a blocking GC Instrumentation

05-31 21:10:41.425 27902-27902/? W/System: ClassLoader referenced unknown path: /data/app/com.example.andreas.drawing_exp-2/lib/arm64

05-31 21:10:41.433 27902-27902/? I/InstantRun: starting instant run server: is main process

05-31 21:10:41.450 27902-27902/? I/HwCust: Constructor found for class android.app.HwCustActivityImpl

05-31 21:10:41.465 27902-27902/? I/HwCust: Constructor found for class android.app.HwCustHwWallpaperManagerImpl

05-31 21:10:41.477 27902-27902/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable

05-31 21:10:41.533 27902-27913/? I/art: Background sticky concurrent mark sweep GC freed 2801(763KB) AllocSpace objects, 0(0B) LOS objects, 22% free, 3MB/4MB, paused 5.329ms total 13.242ms

05-31 21:10:41.567 27902-27902/? W/VRSystemServiceManager: vr service is not alive

05-31 21:10:41.568 27902-27902/? I/HwSecImmHelper: mSecurityInputMethodService is null

05-31 21:10:41.571 27902-27902/? I/HwPointEventFilter: support AFT

05-31 21:10:41.615 27902-27922/? I/OpenGLRenderer: Initialized EGL, version 1.4

05-31 21:10:41.621 27902-27922/? W/linker: /vendor/lib64/libhwuibp.so: unused DT entry: type 0xf arg 0xe3a

05-31 21:10:41.629 27902-27902/? W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView

05-31 21:10:48.728 27902-27902/com.example.andreas.drawing_exp I/hwaps: JNI_OnLoad

05-31 21:10:48.802 27902-27902/com.example.andreas.drawing_exp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.andreas.drawing_exp, PID: 27902 java.lang.NullPointerException: Attempt to read from field 'boolean com.example.andreas.drawing_exp.CanvasView.colorRed' on a null object reference at com.example.andreas.drawing_exp.MainActivity.onClick(MainActivity.java:37) at android.view.View.performClick(View.java:5646) at android.view.View$PerformClick.run(View.java:22473) at android.os.Handler.handleCallback(Handler.java:761) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:156) at android.app.ActivityThread.main(ActivityThread.java:6523) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

05-31 21:10:48.837 27902-27902/com.example.andreas.drawing_exp I/Process: Sending signal. PID: 27902 SIG: 9

  • Please post your log also – Cao Minh Vu May 31 '18 at 02:03
  • Read http://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this for tips about how to find the source of the error. – Code-Apprentice May 31 '18 at 02:52
  • Since the color has more to do with the canvas than the activity, the `colorRed` variable should be in the `CanvasView` class. Using `static` to share variables between classes is an improper use of `static`. – Code-Apprentice May 31 '18 at 02:54
  • Possible duplicate of [Unfortunately MyApp has stopped. How can I solve this?](https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) – Vladyslav Matviienko May 31 '18 at 05:24
  • Thanks for the tips. I found out why my app crashes. If you are interested, see my answer below. – Andreas Erfurt May 31 '18 at 11:57
  • @Code-Apprentice I will keep it in my mind for future errors, thanks for the link. – Andreas Erfurt May 31 '18 at 12:13
  • This question will be more helpful to other visitors if you add the exact error message from your log cat after the crash. That way other people will be able to more easily find your solution. – Code-Apprentice May 31 '18 at 14:41

2 Answers2

1

You are using invalidate() incorrectly.

This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().

You use postInvalidate() to do this.

Naveen T P
  • 6,955
  • 2
  • 22
  • 29
ChaMinGyu
  • 26
  • 5
1

I found out why my app crashes after watching a few tutorials on how to draw in a custom view in YouTube. It is because I made the initialisation of my canvas view class the wrong way. I did not add an ID for the view and did not initialize with 'findViewById', instead I used the constructor of the class. But anyway, thanks for your answers! Here is how the changed code looks like (short excerpt of original code):

public class MainActivity extends AppCompatActivity implements 
View.OnClickListener{

    CanvasView canvasView;
    Button btnChangeColor;

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

        canvasView = (CanvasView) findViewById(R.id.canvasview);
        btnChangeColor = (Button) findViewById(R.id.button);

        btnChangeColor.setOnClickListener(this);

        canvasView.colorRed = false;

    }
  • Note that there is nothing wrong with using the constructor to create a custom view. However, you also need to add the new view to the activity's view hierarchy. Using your solution here is much simpler, assuming that the `CanvasView` is used as a tag in the XML layout. – Code-Apprentice May 31 '18 at 14:39