标签:surfaceview 1 在eclipse中查看Android源代码 假设我们想参看Activity类的源代码,按着Ctrl键,左击它,现实的结果却看不到代码的,提示的信息便是“找不到Activity.class文件”。下载好Android源码之后,点击Attached Source,选择External location External Folder文件夹菜单,选择Android所在的目录即可 2 SurfaceView的继承关系 public class android.view.SurfaceView extendsandroid.view.View 3 如何知道Activity控件渲染完毕,可以监听事件Activity是否获得焦点 当activity获得焦点之后,activity是加载完毕的了,这个方法的技巧性比较强,很难想到。 1. @Override 2. publicvoid onWindowFocusChanged(boolean hasFocus) { 3. // TODOAuto-generated method stub 4. super.onWindowFocusChanged(hasFocus); 5. if(hasFocus){ 6. showPopupWindow(getApplicationContext()); 7. } 8. } 4 Surface的创建与有效性 当SurfaceView被实例化时,Surface并没有立即创建。相反,它是异步创建的。每当活动暂停或再次恢复而重新创建时,该Surface都将被销毁 只要Surface没有生效,我们就不能从SurfaceHolder中获取Canvas。不过,我们可以通过下面的语句来查看Surface是否已被创建: boolean isCreated =surfaceHolder.getSurface().isValid(); 如果该方法返回true,我们就可安全的锁定该Surface并通过接收到的Canvas来在其上进行绘制。我们必须绝对确保在调用SurfaceHolder.lockCanvas()之后再次解锁Surface,否则我们的活动可能会锁定手机。 参考 5 Thread与SurfaceView View组件由UI线程(主线程)所执行。如果需要迅速更新UI画面或UI画图需要较长时间,则需要使用SurfaceView。它可由后台线程(background thread)来执行,而View只能由UI(主)线程执行。SurfaceView内有高效的rendering机制,可以让后台线程快速刷新Surface的内容。 View ---> UI(主)线程 SurfaceView ---> 后台线程 参考 7 在找findViewById的过程中,由于开始忽略子类ViewGroup对View方法的重写,导致在View.class万行代码中陷入死循环 8 viewRoot 的目的,实际上在什么地方渲染控件 每个activity有个window,window被windowmanager管理. 每个window都有decorview. 每个window都有ViewRoot. 绘制发起从ViewRoot. 事件传递发起冲ViewRoot. 绘制传递canvas, canvas来自surface. 9 SurfaceView传递给底层NDK出错提示如下: E/ExtMediaPlayer-JNI: env->IsInstanceOffails E/MediaPlayer-JNI: JNIMediaPlayerFactory:bIsQCMediaPlayerPresent 0 private SurfaceHolder holder; 在查看的例子当中都是使用holder = this.getHolder();获取SurfaceHolder, 而没有通过参数的传递获取到SurfaceHolder变量 public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub holder = this.getHolder(); } 10 使用SurfaceView出现的崩溃信息 java.lang.RuntimeException: Could not read input channel file descriptors from parcel. at android.view.InputChannel.nativeReadFromParcel(Native Method) at android.view.InputChannel.readFromParcel(InputChannel.java:148) at android.view.InputChannel$1.createFromParcel(InputChannel.java:39) at android.view.InputChannel$1.createFromParcel(InputChannel.java:36) at com.android.internal.view.InputBindResult.<init>(InputBindResult.java:68) at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:112) at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:109) at com.android.internal.view.IInputMethodManager$Stub$Proxy.windowGainedFocus(IInputMethodManager.java:735) at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:1232) at android.view.inputmethod.InputMethodManager.onPostWindowFocus(InputMethodManager.java:1456) at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3410) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5438) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629) 11 创建简单Surface测试例子 import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.os.MessageQueue; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.Surface; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; public class MySurfaceView extends SurfaceView implements Callback{ int m_nWidth = 0; int m_nHeight = 0; static boolean m_isInitial = false; static boolean m_Initialend = false; public static boolean canTouch = true; SurfaceHolder holder = null; Surface m_surface = null; Context m_context = null; @SuppressWarnings("deprecation") public MySurfaceView(Context context) { super(context); init(context); } public MySurfaceView(Context context, AttributeSet sets) { super(context, sets); init(context); } private void init(Context context) { m_context = context; Display d = ((Activity) context).getWindowManager().getDefaultDisplay(); m_nWidth = d.getWidth(); m_nHeight = d.getHeight(); holder = getHolder(); holder.addCallback(this); setZOrderOnTop(false); } @Override public void surfaceChanged(SurfaceHolder surfaceholder, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder surfaceholder) { m_surface = surfaceholder.getSurface(); Thread newThread = new Thread(new Runnable() { @Override public void run() { Canvas c = null; try { synchronized (holder) { c = holder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。 c.drawColor(Color.BLUE);//设置画布背景颜色 Paint p = new Paint(); //创建画笔 p.setColor(Color.WHITE); Rect r = new Rect(100, 50, 300, 250); c.drawRect(r, p); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { if(c!= null) { holder.unlockCanvasAndPost(c);//结束锁定画图,并提交改变。 } } } }); newThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder surfaceholder) { } } 12 Surface渲染的时候黑屏一下,然后才显示界面 主要是Surface的背景是黑色的,如果渲染的时间过长,就可以明显的看到没有渲染完成的过程,其实这个时候可以设置一下Surface的背景,可以设置为柔和的颜色 SurfaceView源码以及崩溃剖析 标签:surfaceview 原文: