I created a file called JoyStickView
which extends SurfaceView
.
In my JoyStickView.java
file, I have the following function which calls the AsyncTask
to draw two joysticks:
private void drawJoystick(float hatX, float hatY) {
// Only draw the joystick when SurfaceView has been created
if (getHolder().getSurface().isValid()) {
new MultiplyTask().execute();
}
}
And the inner class AsyncTask
is shown below:
public class MultiplyTask extends AsyncTask<Void, Bitmap, Bitmap[]> {
@Override
protected void onPreExecute() {
//super.onPreExecute();
}
@Override
protected Bitmap[] doInBackground(Void... progress_data) {
Bitmap[] bitmapArray = new Bitmap[2];
bitmapArray[0] = BitmapFactory.decodeResource(getResources(), R.drawable.joystick_base);
bitmapArray[1] = BitmapFactory.decodeResource(getResources(), R.drawable.joystick_hat);
//publishProgress(bitmapArray);
return bitmapArray;
}
@Override
protected void onProgressUpdate(Bitmap... bitmapArray) {
//super.onProgressUpdate(values);\
}
@Override
protected void onPostExecute(Bitmap[] bitmapArray) {
// super.onPostExecute(s);
myCanvas = getHolder().lockCanvas();
myCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
switch (getId()) {
case R.id.joystickRight:
// draw_joystick_base(myCanvas, R.drawable.joystick_base);
float c = bitmapArray[0].getWidth() / 2;
float d = bitmapArray[0].getHeight() / 2;
myCanvas.drawBitmap(bitmapArray[0], centerX - c, centerY - d, new Paint());
break;
case R.id.joystickLeft:
// draw_joystick_base(myCanvas, R.drawable.joystick_base);
float c1 = bitmapArray[0].getWidth() / 2;
float d1 = bitmapArray[0].getHeight() / 2;
myCanvas.drawBitmap(bitmapArray[0], centerX - c1, centerY - d1, new Paint());
break;
}
float a = bitmapArray[1].getWidth() / 2;
float b = bitmapArray[1].getHeight() / 2;
myCanvas.drawBitmap(bitmapArray[1], hatX_tmp - a, hatY_tmp - b, new Paint());
getHolder().unlockCanvasAndPost(myCanvas);
// Do things like update the progress bar
}
void stopTask() {
MultiplyTask a = new MultiplyTask();
a.cancel(true);
}
}
Everything works great until I hit the back button, and the app just crashes and gave me the following null pointer error.
06-03 15:06:15.505 4478-4478/com.example.android.toybot E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.toybot, PID: 4478
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at com.example.android.toybot.JoyStickView$MultiplyTask.onPostExecute(JoyStickView.java:304)
at com.example.android.toybot.JoyStickView$MultiplyTask.onPostExecute(JoyStickView.java:274)
at android.os.AsyncTask.finish(AsyncTask.java:661)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:678)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
JoyStickView.java:304
is this line: myCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
I thought of cancelling my AsyncTask
during onstop()
but this does not seem to work. Anyone have any advice on what I can do?
Update:
Following this post, I was able to follow the LunarLander example and implement a new Runnable()
to achieve what I needed.