Вы получаете доступ к элементу пользовательского интерфейса из отдельного потока, что не рекомендуется.NullPointerException
довольно прост.myCanvas = getHolder().lockCanvas();
устанавливает нулевую ссылку на атрибут myCanvas
, когда вы заканчиваете занятие нажатием кнопки «назад».
Если код был внутри вашего потока пользовательского интерфейса (то есть внутри любой функции, которая находится в жизненном цикле вашей активности), это могло бы быть обработано функциями жизненного цикла активности, такими как onStop
или onDestroy
.Однако вы пытаетесь изменить элемент пользовательского интерфейса (myCanvas
в вашем случае) из отдельного потока, отличного от потока пользовательского интерфейса, который находится вне области управления ресурсами Activity
.Следовательно, getHolder().lockCanvas()
получает нулевую ссылку на холст, а вы получаете NullPointerException
на чертеже.
Этого можно легко избежать, реализовав интерфейс в качестве прослушивателя для вашего AsyncTask
, чтобы функция прослушивателя находилась в вашем Activity
и правильно обрабатывала ресурсы.Например, вы можете подумать о создании interface
, как это.
public interface MultiplyResponseReceiver {
void onMultiplyResponseReceived(Bitmap[] bitmapArray);
}
Теперь возьмите атрибут этого интерфейса в вашем AsyncTask
вот так.
public class MultiplyTask extends AsyncTask<Void, Bitmap, Bitmap[]> {
public MultiplyResponseReceiver listener;
@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);
listener.onMultiplyResponseReceived(bitmapArray);
}
}
Теперь реализуйте интерфейс в вашем Activity
следующим образом.
public class YourActivity extends AppCompatActivity implements MultiplyResponseReceiver {
@Override
public void onMultiplyResponseReceived() {
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
}
}
И, запуская AsyncTask
в своей деятельности, не забудьте назначить ему слушателя.
MultiplyTask task = new MultiplyTask();
task.listener = this;
task.execute();
Код не проверен и может содержать ошибки.Пожалуйста, измените согласно вашей необходимости.Я думаю, у вас уже есть идея.