关于Java Generic Deep Copy 在java中的应用和注意事项,请参考:http://blog.csdn.net/yang_hui1986527/article/details/7039425
而关于在android程序中通过clone方法来进行浅复制和深复制,请参考:http://blog.csdn.net/yang_hui1986527/article/details/7036818
众所周知,android上层使用的是java语言,因此理论上于Java Generic Deep Copy 方法,同样适用于android程序中对象的深度拷贝。但是,上次在一个android的demo中使用试图通过该方法来进行深度拷贝,一直未成功。出错提示如下:
W/ActivityManager( 154): Launch timeout has expired, giving up wake lock! W/ActivityManager( 154): Activity idle timeout for HistoryRecord{40540f08 com.clone/.CloneActivity} E/dalvikvm( 3080): Could not find class 'javax.print.attribute.standard.PrinterStateReason', referenced from method com.ajexperience.utils.DeepCopyUtil.a W/dalvikvm( 3080): VFY: unable to resolve instanceof 97 (Ljavax/print/attribute/standard/PrinterStateReason;) in Lcom/ajexperience/utils/DeepCopyUtil; D/dalvikvm( 3080): VFY: replacing opcode 0x20 at 0x011d D/dalvikvm( 3080): VFY: dead code 0x011f-0131 in Lcom/ajexperience/utils/DeepCopyUtil;.a (Ljava/lang/Object;Ljava/lang/Object;Lcom/ajexperience/utils/DeepCopyUtil$a;)Ljava/lang/Object; W/System.err( 3080): java.lang.RuntimeException: com.ajexperience.utils.DeepCopyException: java.lang.NoSuchFieldException: modifiers W/System.err( 3080): at com.clone.CloneUtil.getDeepCloneUtil(CloneUtil.java:14) W/System.err( 3080): at com.clone.CloneUtil.<init>(CloneUtil.java:8) W/System.err( 3080): at com.clone.CloneView.<init>(CloneView.java:24) W/System.err( 3080): at com.clone.CloneActivity.onCreate(CloneActivity.java:12) W/System.err( 3080): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) W/System.err( 3080): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722) W/System.err( 3080): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784) W/System.err( 3080): at android.app.ActivityThread.access$1500(ActivityThread.java:123) W/System.err( 3080): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939) W/System.err( 3080): at android.os.Handler.dispatchMessage(Handler.java:99) W/System.err( 3080): at android.os.Looper.loop(Looper.java:130) W/System.err( 3080): at android.app.ActivityThread.main(ActivityThread.java:3835) W/System.err( 3080): at java.lang.reflect.Method.invokeNative(Native Method) W/System.err( 3080): at java.lang.reflect.Method.invoke(Method.java:507) W/System.err( 3080): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841) W/System.err( 3080): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599) W/System.err( 3080): at dalvik.system.NativeStart.main(Native Method) W/System.err( 3080): Caused by: com.ajexperience.utils.DeepCopyException: java.lang.NoSuchFieldException: modifiers W/System.err( 3080): at com.ajexperience.utils.DeepCopyUtil.<init>(SourceFile:99) W/System.err( 3080): at com.clone.CloneUtil.getDeepCloneUtil(CloneUtil.java:12) W/System.err( 3080): ... 16 more W/System.err( 3080): Caused by: java.lang.NoSuchFieldException: modifiers W/System.err( 3080): at java.lang.ClassCache.findFieldByName(ClassCache.java:446) W/System.err( 3080): at java.lang.Class.getDeclaredField(Class.java:666) W/System.err( 3080): at com.ajexperience.utils.DeepCopyUtil.<init>(SourceFile:95) W/System.err( 3080): ... 17 more D/dalvikvm( 424): GC_EXPLICIT freed 5K, 51% free 3666K/7367K, external 0K/0K, paused 95ms I/ActivityManager( 154): Displayed com.clone/.CloneActivity: +20s115ms
于是,通过邮件向作者咨询该问题。今天,终于又收到作者的邮件,通知Java Generic Deep Copy 有更新,让我再试试。
下载最新版DeepCopyUtil-1.5,替换以前的库,运行成功。
主要思路:
1、创建TextBox,然后根据TextBox复制出一个对象TextBox2(点击屏幕,进行复制);
2、改变TextBox2的位置,方便观察比较差异。
3、改变TextBox2内部文本的位置。如果是浅复制,那么TextBox2内部文本改变位置的同时,TextBox内部文本的位置会随着改变。否则,如果是深度复制,TextBox内部文本的位置不会改变。
效果如下:
注:请注意文本“test”在文本框内的位置。
深复制:
源程序:
CloneActivity.java
package com.clone; import android.app.Activity; import android.os.Bundle; public class CloneActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); CloneView mCloneView = new CloneView(this); setContentView(mCloneView); } }
package com.clone; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class CloneView extends View { private Document mDocument = null; public Paint mPaint= null; public TextBox mTextBox = null; public TextBox mTextBox2 = null; private CloneUtil mCloneUtil = null; public CloneView(Context context) { super(context); mDocument = new Document(); mPaint = new Paint(); try { mCloneUtil = new CloneUtil(); } catch (Exception e) { e.printStackTrace(); } initData(); } public CloneView(Context context, AttributeSet attrs) { super(context, attrs); mDocument = new Document(); mPaint = new Paint(); try { mCloneUtil = new CloneUtil(); } catch (Exception e) { e.printStackTrace(); } initData(); } public CloneView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDocument = new Document(); } public void initData() { PointF textpos = new PointF(30,30); String text = new String("test"); mTextBox = new TextBox(50, 50, 100, 100, textpos, text); mDocument.add(mTextBox); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.WHITE); mDocument.draw(canvas, mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { if (mCloneUtil != null) { mTextBox2 = (TextBox) mCloneUtil.clone(mTextBox); //深克隆 } if(mTextBox2 != null) { mTextBox2.moveBound(); mTextBox2.changeData(); mDocument.add(mTextBox2); } } invalidate(); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; default: break; } return super.onTouchEvent(event); } }
Document.java
package com.clone; import java.util.Vector; import android.graphics.Canvas; import android.graphics.Paint; public class Document { private Vector<Object> objs = null; public Document() { objs = new Vector<Object>(); } public void add(Object obj){ objs.add(obj); } void draw(Canvas canvas, Paint paint) { canvas.save(); for (int i = 0; i < objs.size(); i++) { Object obj = objs.get(i); obj.draw(canvas, paint); } canvas.restore(); } }
Object.java
package com.clone; import android.graphics.Canvas; import android.graphics.Paint; public abstract class Object{ protected float posx = 0; protected float posy =0; protected float width = 0; protected float height = 0; public Object() { posx = 0; posy =0; width = 0; height = 0; } public Object(float posx,float posy,float width,float height){ this.posx = posx; this.posy = posy; this.width = width; this.height = height; } public void moveBound() { this.posx += 100; this.posy += 100; } abstract void draw(Canvas canvas,Paint paint); abstract void changeData(); }
TextBox.java
package com.clone; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PointF; public class TextBox extends Object{ private PointF mtextpos = null; private String mtextString = null; public TextBox() { posx = 0; posy =0; width = 0; height = 0; mtextpos = new PointF(); mtextString = new String(); } public TextBox(float posx, float posy, float width, float height,PointF textpos,String text) { this.posx = posx; this.posy = posy; this.width = width; this.height = height; mtextpos = new PointF(textpos.x,textpos.y); mtextString = new String(text); } @Override void draw(Canvas canvas, Paint paint) { canvas.save(); paint.setColor(Color.BLUE); paint.setStyle(Style.STROKE); canvas.drawRect(posx, posy, posx+width, posy+height, paint); canvas.translate(posx, posy); paint.setColor(Color.BLACK); paint.setTextSize(20); canvas.drawText(mtextString, mtextpos.x, mtextpos.y, paint); canvas.restore(); } @Override void changeData() { if(mtextpos != null) mtextpos.offset(20, 50); } }
CloneUtil.java
package com.clone; import com.ajexperience.utils.DeepCopyException; import com.ajexperience.utils.DeepCopyUtil; public class CloneUtil { private DeepCopyUtil deepCopyUtil = getDeepCloneUtil(); private DeepCopyUtil getDeepCloneUtil() { try { return new DeepCopyUtil(); } catch (DeepCopyException e) { throw new RuntimeException(e); } } public Object clone(Object object) { try { return deepCopyUtil.deepCopy(object); } catch (DeepCopyException e) { throw new RuntimeException(e); } } }