Android: 尝试调用空对象引用的虚方法
Android: Attempt to invoke virtual method a null object reference
我有一些问题。在我的代码中,我试图重绘屏幕旋转时在船上绘制的图形。但我收到空对象引用异常
在我的代码中 bitmaps 是位图数组列表。
这是我的 saveInstanceState 代码
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bitArrayStore(j);
outState.putParcelableArrayList("Bits", bitmaps);
outState.putInt("j", j);
}
这里是 bitArrayStore()
public void bitArrayStore(int k) {
if (drawView.canvasBitmap.sameAs(drawView.emptyBitmap)) {
flag = true;
} else {
try {
if (flag1 == false) {
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bitmaps.set(k, Bitmap.createBitmap(drawView.getDrawingCache()));
} else {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
flag1 = false;
}
} catch (IndexOutOfBoundsException e) {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
}
drawView.destroyDrawingCache();
}
}
这是我的 onRestoreInstanceState 代码
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
redraww();
}
我的重绘方法
public void redraww()
{
try{
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e){
drawView.startNew();
}
}
drawView.redraw() 方法(这是我得到异常的地方。我已经记录了它)
public void redraw(ArrayList<Bitmap> bits, int i) {
try {
drawCanvas.drawBitmap(bits.get(i), 0, 0, canvasPaint);
invalidate();
}catch (NullPointerException e){
Log.w("Notepad",e);
}
}
这是我的日志
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)' on a null object reference
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.DrawingView.redraw(DrawingView.java:145)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.NewNote.redraww(NewNote.java:368)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.NewNote.onRestoreInstanceState(NewNote.java:395)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.Activity.performRestoreInstanceState(Activity.java:978)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1162)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.access0(ActivityThread.java:151)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.os.Handler.dispatchMessage(Handler.java:102)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.os.Looper.loop(Looper.java:135)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.main(ActivityThread.java:5254)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at java.lang.reflect.Method.invoke(Native Method)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at java.lang.reflect.Method.invoke(Method.java:372)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
绘图没有在屏幕旋转时重新绘制,而是我得到这个 exception.I 我无法解决它。请帮忙..
编辑:我的java程序代码
NewNote.java
public class NewNote extends AppCompatActivity implements View.OnClickListener {
private DrawingView drawView;
private ImageButton currPaint;
private float smallBrush = 5, mediumBrush = 10, largeBrush = 30;
String ucolor;
int i = 0, j = 0;
private boolean flag = false, flag1 = false;
ArrayList<Bitmap> bitmaps;
Bitmap[] bits;
@Bind(R.id.colornsize)
ViewGroup colorNsize;
@Bind(R.id.eraserdrawer)
ViewGroup eraserDrawer;
@Bind(R.id.blue_paint)
ImageButton bluePaint;
@Bind(R.id.small_brush)
ImageButton smallBtn;
@Bind(R.id.medium_brush)
ImageButton mediumBtn;
@Bind(R.id.large_brush)
ImageButton largeBtn;
@Bind(R.id.small_eraser)
ImageButton smallEraser;
@Bind(R.id.medium_eraser)
ImageButton mediumEraser;
@Bind(R.id.large_eraser)
ImageButton largeEraser;
@Bind(R.id.bottom_drawer)
ViewGroup btm;
@Bind(R.id.previousbtn)
ImageButton previousBtn;
@Bind(R.id.nextbtn)
ImageButton nextBtn;
@Bind(R.id.framelayout)
FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notespage_newnote);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
drawView = (DrawingView) findViewById(R.id.drawing);
currPaint = bluePaint;
currPaint.setImageResource(R.drawable.paint_pressed);
smallBrush = getResources().getInteger(R.integer.small_size);
mediumBrush = getResources().getInteger(R.integer.medium_size);
largeBrush = getResources().getInteger(R.integer.large_size);
drawView.setBrushSize(mediumBrush);
bitmaps = new ArrayList<Bitmap>();
bits = new Bitmap[40];
drawView.setDrawingCacheEnabled(true);
smallBtn.setOnClickListener(this);
mediumBtn.setOnClickListener(this);
largeBtn.setOnClickListener(this);
smallEraser.setOnClickListener(this);
mediumEraser.setOnClickListener(this);
largeEraser.setOnClickListener(this);
previousBtn.setOnClickListener(this);
nextBtn.setOnClickListener(this);
drawView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
btm.setVisibility(View.GONE);
break;
case MotionEvent.ACTION_UP:
btm.setVisibility(View.VISIBLE);
break;
default:
return false;
}
return false;
}
});
}
public void paintClicked(View view) {
//use chosen color
drawView.setErase(false);
drawView.setBrushSize(drawView.getLastBrushSize());
if (view != currPaint) {
//update color
ImageButton imgView = (ImageButton) view;
String color = view.getTag().toString();
drawView.setColor(color);
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currPaint = (ImageButton) view;
}
hideDrawer(colorNsize);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.newnote_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.clear_menuitem) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("Clear Board");
newDialog.setMessage("Do you want to clear the board (you will lose the current drawing)?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
drawView.startNew();
bitmaps.remove(j);
flag1 = true;
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
newDialog.show();
return true;
} else if (id == R.id.save_menuitem) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
bitArrayStore(j);
int k = 0;
try {
while (k <= bitmaps.size()) {
Bitmap m = null;
m = bitmaps.get(k);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(path + File.separator + "Pictures" + File.separator + k + "_image.png");
FileOutputStream ostream;
try {
file.createNewFile();
ostream = new FileOutputStream(file);
m.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
final Snackbar snackbar = Snackbar.make(frameLayout, "Note Saved", Snackbar.LENGTH_LONG);
snackbar.setAction("Close", new View.OnClickListener() {
@Override
public void onClick(View v) {
snackbar.dismiss();
}
});
snackbar.show();
} catch (Exception e) {
e.printStackTrace();
Log.w("Skoolify", e);
}
k = k + 1;
}
} catch (IndexOutOfBoundsException e) {
Log.w("Skoolify", "OutOFBonds");
}
return true;
} else if (id == R.id.brush_menuitem) {
if (colorNsize.getVisibility() == View.VISIBLE) {
hideDrawer(colorNsize);
} else {
hideDrawer(eraserDrawer);
showDrawer(colorNsize);
}
return true;
} else if (id == R.id.eraser_menuitem) {
if (eraserDrawer.getVisibility() == View.VISIBLE) {
hideDrawer(eraserDrawer);
} else {
hideDrawer(colorNsize);
showDrawer(eraserDrawer);
}
return true;
}
else if(id==R.id.delete_menuitem){
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("Discard the Notes");
newDialog.setMessage("Do you want to discard the unsaved notes?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
NewNote.this.finish();
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
newDialog.show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.small_brush) {
drawView.setBrushSize(smallBrush);
drawView.setLastBrushSize(smallBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.medium_brush) {
drawView.setBrushSize(mediumBrush);
drawView.setLastBrushSize(mediumBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.large_brush) {
drawView.setBrushSize(largeBrush);
drawView.setLastBrushSize(largeBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.small_eraser) {
drawView.setErase(true);
drawView.setBrushSize(smallBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.medium_eraser) {
drawView.setErase(true);
drawView.setBrushSize(mediumBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.large_eraser) {
drawView.setErase(true);
drawView.setBrushSize(largeBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.previousbtn) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
try {
bitArrayStore(j);
drawView.startNew();
j--;
if (bitmaps.size() > j) {
drawView.redraw(bitmaps, j);
}
} catch (IndexOutOfBoundsException e) {
j = 0;
try {
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e1){
drawView.startNew();
}
}
flag = false;
} else if (v.getId() == R.id.nextbtn) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
if (j < 50) {
bitArrayStore(j);
if (flag == false) {
j++;
}
if (bitmaps.size() > j) {
drawView.startNew();
drawView.redraw(bitmaps, j);
} else {
drawView.startNew();
}
flag = false;
} else {
Snackbar.make(v, "Reached page limit. Please save and start new note", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
}
public void bitArrayStore(int k) {
if (drawView.canvasBitmap.sameAs(drawView.emptyBitmap)) {
flag = true;
} else {
try {
if (flag1 == false) {
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bitmaps.set(k, Bitmap.createBitmap(drawView.getDrawingCache()));
} else {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
flag1 = false;
}
} catch (IndexOutOfBoundsException e) {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
}
drawView.destroyDrawingCache();
}
}
public void redraww()
{
try{
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e){
drawView.startNew();
}
}
public void hideDrawer(ViewGroup viewgrp) {
viewgrp.setVisibility(View.GONE);
}
public void showDrawer(ViewGroup viewgrp) {
viewgrp.setVisibility(View.VISIBLE);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bitArrayStore(j);
outState.putParcelableArrayList("Bits", bitmaps);
outState.putInt("j", j);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
redraww();
}
}
DrawingView.java
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF0000c4;
//canvas
private Canvas drawCanvas;
//canvas bitmap
public Bitmap canvasBitmap, emptyBitmap;
private float brushSize, lastBrushSize;
private boolean erase = false;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
private void setupDrawing() {
brushSize = getResources().getInteger(R.integer.small_size);
lastBrushSize = brushSize;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(20);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
emptyBitmap = Bitmap.createBitmap(canvasBitmap.getWidth(), canvasBitmap.getHeight(), canvasBitmap.getConfig());
}
@Override
protected void onDraw(Canvas canvas) {
//draw view
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public void setColor(String newColor) {
//set color
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
public void setBrushSize(float newSize) {
//update sizefloat pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize = pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setLastBrushSize(float lastSize) {
lastBrushSize = lastSize;
}
public float getLastBrushSize() {
return lastBrushSize;
}
public void setErase(boolean isErase) {
//set erase true or false
erase = isErase;
if (erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else drawPaint.setXfermode(null);
}
public void startNew() {
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
// Bitmap b= BitmapFactory.decodeFile("/storage/emulated/0/Pictures/image.png");
// drawCanvas.drawBitmap(b, 0, 0, null);
//
// invalidate();
}
public void redraw(ArrayList<Bitmap> bits, int i) {
try {
drawCanvas.drawBitmap(bits.get(i), 0, 0, canvasPaint);
invalidate();
}catch (NullPointerException e){
Log.w("DrawingApp","Exception");
}
}
}
drawCanvas
在方法 redraw()
中为 null。确保在调用 redraw()
方法之前实例化 drawCanvas
。
不过,发布完整代码会有所帮助,了解问题所在。
问题出在您的 onRestoreInstanceState()
上。您的对象尚未初始化,在此之前您正在调用 redraww
。我建议您删除 onRestoreInstanceState()
并在 onCreate()
中处理它以避免代码重复。
protected void onCreate(Bundle savedInstanceState){
if(savedInstanceState != null){
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
}
// go ahead with your object initialization. Once your `drawCanvas` is ready and initialized, then call `redraww`.
}
将此代码移动到 DrawingView 的构造函数中 class。
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
emptyBitmap = Bitmap.createBitmap(canvasBitmap.getWidth(), canvasBitmap.getHeight(), canvasBitmap.getConfig());
嘿,在 Henry 的帮助下,我找到了解决问题的方法。他指出我在初始化对象之前调用了 redraww() 方法。所以我通过在 onWindowFocusChanged 中调用我的方法解决了我的问题。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
if (flag2 == true) {
redraww();
}
}
}
我已经设置了 flag2,这样它就不会在第一次创建 activity 时调用 redraww() 方法。仅当存在 saveInstanceState 时才应调用它。
我有一些问题。在我的代码中,我试图重绘屏幕旋转时在船上绘制的图形。但我收到空对象引用异常
在我的代码中 bitmaps 是位图数组列表。
这是我的 saveInstanceState 代码
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bitArrayStore(j);
outState.putParcelableArrayList("Bits", bitmaps);
outState.putInt("j", j);
}
这里是 bitArrayStore()
public void bitArrayStore(int k) {
if (drawView.canvasBitmap.sameAs(drawView.emptyBitmap)) {
flag = true;
} else {
try {
if (flag1 == false) {
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bitmaps.set(k, Bitmap.createBitmap(drawView.getDrawingCache()));
} else {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
flag1 = false;
}
} catch (IndexOutOfBoundsException e) {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
}
drawView.destroyDrawingCache();
}
}
这是我的 onRestoreInstanceState 代码
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
redraww();
}
我的重绘方法
public void redraww()
{
try{
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e){
drawView.startNew();
}
}
drawView.redraw() 方法(这是我得到异常的地方。我已经记录了它)
public void redraw(ArrayList<Bitmap> bits, int i) {
try {
drawCanvas.drawBitmap(bits.get(i), 0, 0, canvasPaint);
invalidate();
}catch (NullPointerException e){
Log.w("Notepad",e);
}
}
这是我的日志
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)' on a null object reference
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.DrawingView.redraw(DrawingView.java:145)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.NewNote.redraww(NewNote.java:368)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at org.notepad.notepad.notespage.NewNote.onRestoreInstanceState(NewNote.java:395)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.Activity.performRestoreInstanceState(Activity.java:978)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1162)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.access0(ActivityThread.java:151)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.os.Handler.dispatchMessage(Handler.java:102)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.os.Looper.loop(Looper.java:135)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at android.app.ActivityThread.main(ActivityThread.java:5254)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at java.lang.reflect.Method.invoke(Native Method)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at java.lang.reflect.Method.invoke(Method.java:372)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-25 09:58:19.826 12664-12664/org.notepad.notepad W/Notepad: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
绘图没有在屏幕旋转时重新绘制,而是我得到这个 exception.I 我无法解决它。请帮忙..
编辑:我的java程序代码
NewNote.java
public class NewNote extends AppCompatActivity implements View.OnClickListener {
private DrawingView drawView;
private ImageButton currPaint;
private float smallBrush = 5, mediumBrush = 10, largeBrush = 30;
String ucolor;
int i = 0, j = 0;
private boolean flag = false, flag1 = false;
ArrayList<Bitmap> bitmaps;
Bitmap[] bits;
@Bind(R.id.colornsize)
ViewGroup colorNsize;
@Bind(R.id.eraserdrawer)
ViewGroup eraserDrawer;
@Bind(R.id.blue_paint)
ImageButton bluePaint;
@Bind(R.id.small_brush)
ImageButton smallBtn;
@Bind(R.id.medium_brush)
ImageButton mediumBtn;
@Bind(R.id.large_brush)
ImageButton largeBtn;
@Bind(R.id.small_eraser)
ImageButton smallEraser;
@Bind(R.id.medium_eraser)
ImageButton mediumEraser;
@Bind(R.id.large_eraser)
ImageButton largeEraser;
@Bind(R.id.bottom_drawer)
ViewGroup btm;
@Bind(R.id.previousbtn)
ImageButton previousBtn;
@Bind(R.id.nextbtn)
ImageButton nextBtn;
@Bind(R.id.framelayout)
FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notespage_newnote);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
drawView = (DrawingView) findViewById(R.id.drawing);
currPaint = bluePaint;
currPaint.setImageResource(R.drawable.paint_pressed);
smallBrush = getResources().getInteger(R.integer.small_size);
mediumBrush = getResources().getInteger(R.integer.medium_size);
largeBrush = getResources().getInteger(R.integer.large_size);
drawView.setBrushSize(mediumBrush);
bitmaps = new ArrayList<Bitmap>();
bits = new Bitmap[40];
drawView.setDrawingCacheEnabled(true);
smallBtn.setOnClickListener(this);
mediumBtn.setOnClickListener(this);
largeBtn.setOnClickListener(this);
smallEraser.setOnClickListener(this);
mediumEraser.setOnClickListener(this);
largeEraser.setOnClickListener(this);
previousBtn.setOnClickListener(this);
nextBtn.setOnClickListener(this);
drawView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
btm.setVisibility(View.GONE);
break;
case MotionEvent.ACTION_UP:
btm.setVisibility(View.VISIBLE);
break;
default:
return false;
}
return false;
}
});
}
public void paintClicked(View view) {
//use chosen color
drawView.setErase(false);
drawView.setBrushSize(drawView.getLastBrushSize());
if (view != currPaint) {
//update color
ImageButton imgView = (ImageButton) view;
String color = view.getTag().toString();
drawView.setColor(color);
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currPaint = (ImageButton) view;
}
hideDrawer(colorNsize);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.newnote_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.clear_menuitem) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("Clear Board");
newDialog.setMessage("Do you want to clear the board (you will lose the current drawing)?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
drawView.startNew();
bitmaps.remove(j);
flag1 = true;
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
newDialog.show();
return true;
} else if (id == R.id.save_menuitem) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
bitArrayStore(j);
int k = 0;
try {
while (k <= bitmaps.size()) {
Bitmap m = null;
m = bitmaps.get(k);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(path + File.separator + "Pictures" + File.separator + k + "_image.png");
FileOutputStream ostream;
try {
file.createNewFile();
ostream = new FileOutputStream(file);
m.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
final Snackbar snackbar = Snackbar.make(frameLayout, "Note Saved", Snackbar.LENGTH_LONG);
snackbar.setAction("Close", new View.OnClickListener() {
@Override
public void onClick(View v) {
snackbar.dismiss();
}
});
snackbar.show();
} catch (Exception e) {
e.printStackTrace();
Log.w("Skoolify", e);
}
k = k + 1;
}
} catch (IndexOutOfBoundsException e) {
Log.w("Skoolify", "OutOFBonds");
}
return true;
} else if (id == R.id.brush_menuitem) {
if (colorNsize.getVisibility() == View.VISIBLE) {
hideDrawer(colorNsize);
} else {
hideDrawer(eraserDrawer);
showDrawer(colorNsize);
}
return true;
} else if (id == R.id.eraser_menuitem) {
if (eraserDrawer.getVisibility() == View.VISIBLE) {
hideDrawer(eraserDrawer);
} else {
hideDrawer(colorNsize);
showDrawer(eraserDrawer);
}
return true;
}
else if(id==R.id.delete_menuitem){
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("Discard the Notes");
newDialog.setMessage("Do you want to discard the unsaved notes?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
NewNote.this.finish();
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
newDialog.show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.small_brush) {
drawView.setBrushSize(smallBrush);
drawView.setLastBrushSize(smallBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.medium_brush) {
drawView.setBrushSize(mediumBrush);
drawView.setLastBrushSize(mediumBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.large_brush) {
drawView.setBrushSize(largeBrush);
drawView.setLastBrushSize(largeBrush);
drawView.setErase(false);
hideDrawer(colorNsize);
} else if (v.getId() == R.id.small_eraser) {
drawView.setErase(true);
drawView.setBrushSize(smallBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.medium_eraser) {
drawView.setErase(true);
drawView.setBrushSize(mediumBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.large_eraser) {
drawView.setErase(true);
drawView.setBrushSize(largeBrush);
hideDrawer(eraserDrawer);
} else if (v.getId() == R.id.previousbtn) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
try {
bitArrayStore(j);
drawView.startNew();
j--;
if (bitmaps.size() > j) {
drawView.redraw(bitmaps, j);
}
} catch (IndexOutOfBoundsException e) {
j = 0;
try {
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e1){
drawView.startNew();
}
}
flag = false;
} else if (v.getId() == R.id.nextbtn) {
hideDrawer(colorNsize);
hideDrawer(eraserDrawer);
if (j < 50) {
bitArrayStore(j);
if (flag == false) {
j++;
}
if (bitmaps.size() > j) {
drawView.startNew();
drawView.redraw(bitmaps, j);
} else {
drawView.startNew();
}
flag = false;
} else {
Snackbar.make(v, "Reached page limit. Please save and start new note", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
}
public void bitArrayStore(int k) {
if (drawView.canvasBitmap.sameAs(drawView.emptyBitmap)) {
flag = true;
} else {
try {
if (flag1 == false) {
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bitmaps.set(k, Bitmap.createBitmap(drawView.getDrawingCache()));
} else {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
flag1 = false;
}
} catch (IndexOutOfBoundsException e) {
bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
}
drawView.destroyDrawingCache();
}
}
public void redraww()
{
try{
drawView.redraw(bitmaps, j);
}catch (IndexOutOfBoundsException e){
drawView.startNew();
}
}
public void hideDrawer(ViewGroup viewgrp) {
viewgrp.setVisibility(View.GONE);
}
public void showDrawer(ViewGroup viewgrp) {
viewgrp.setVisibility(View.VISIBLE);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bitArrayStore(j);
outState.putParcelableArrayList("Bits", bitmaps);
outState.putInt("j", j);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
redraww();
}
}
DrawingView.java
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF0000c4;
//canvas
private Canvas drawCanvas;
//canvas bitmap
public Bitmap canvasBitmap, emptyBitmap;
private float brushSize, lastBrushSize;
private boolean erase = false;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
private void setupDrawing() {
brushSize = getResources().getInteger(R.integer.small_size);
lastBrushSize = brushSize;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(20);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
emptyBitmap = Bitmap.createBitmap(canvasBitmap.getWidth(), canvasBitmap.getHeight(), canvasBitmap.getConfig());
}
@Override
protected void onDraw(Canvas canvas) {
//draw view
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public void setColor(String newColor) {
//set color
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
public void setBrushSize(float newSize) {
//update sizefloat pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize = pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setLastBrushSize(float lastSize) {
lastBrushSize = lastSize;
}
public float getLastBrushSize() {
return lastBrushSize;
}
public void setErase(boolean isErase) {
//set erase true or false
erase = isErase;
if (erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else drawPaint.setXfermode(null);
}
public void startNew() {
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
// Bitmap b= BitmapFactory.decodeFile("/storage/emulated/0/Pictures/image.png");
// drawCanvas.drawBitmap(b, 0, 0, null);
//
// invalidate();
}
public void redraw(ArrayList<Bitmap> bits, int i) {
try {
drawCanvas.drawBitmap(bits.get(i), 0, 0, canvasPaint);
invalidate();
}catch (NullPointerException e){
Log.w("DrawingApp","Exception");
}
}
}
drawCanvas
在方法 redraw()
中为 null。确保在调用 redraw()
方法之前实例化 drawCanvas
。
不过,发布完整代码会有所帮助,了解问题所在。
问题出在您的 onRestoreInstanceState()
上。您的对象尚未初始化,在此之前您正在调用 redraww
。我建议您删除 onRestoreInstanceState()
并在 onCreate()
中处理它以避免代码重复。
protected void onCreate(Bundle savedInstanceState){
if(savedInstanceState != null){
bitmaps=savedInstanceState.getParcelableArrayList("Bits");
j = savedInstanceState.getInt("j");
}
// go ahead with your object initialization. Once your `drawCanvas` is ready and initialized, then call `redraww`.
}
将此代码移动到 DrawingView 的构造函数中 class。
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
emptyBitmap = Bitmap.createBitmap(canvasBitmap.getWidth(), canvasBitmap.getHeight(), canvasBitmap.getConfig());
嘿,在 Henry 的帮助下,我找到了解决问题的方法。他指出我在初始化对象之前调用了 redraww() 方法。所以我通过在 onWindowFocusChanged 中调用我的方法解决了我的问题。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
if (flag2 == true) {
redraww();
}
}
}
我已经设置了 flag2,这样它就不会在第一次创建 activity 时调用 redraww() 方法。仅当存在 saveInstanceState 时才应调用它。