SurfaceView源码以及崩溃剖析

简介:

1 在eclipse中查看Android源代码

假设我们想参看Activity类的源代码,按着Ctrl键,左击它,现实的结果却看不到代码的,提示的信息便是“找不到Activity.class文件”。下载好Android源码之后,点击Attached Source,选择External location

External Folder文件夹菜单,选择Android所在的目录即可

http://jingyan.baidu.com/article/5d368d1e01df803f60c057f8.html


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,否则我们的活动可能会锁定手机。

参考

http://www.2cto.com/kf/201302/188341.html


5 Thread与SurfaceView

     View组件由UI线程(主线程)所执行。如果需要迅速更新UI画面或UI画图需要较长时间,则需要使用SurfaceView。它可由后台线程(background thread)来执行,而View只能由UI(主)线程执行。SurfaceView内有高效的rendering机制,可以让后台线程快速刷新Surface的内容。

     View ---> UI(主)线程

     SurfaceView ---> 后台线程 

参考

http://blog.csdn.net/myarrow/article/details/14223493


7 在找findViewById的过程中,由于开始忽略子类ViewGroup对View方法的重写,导致在View.class万行代码中陷入死循环 

http://www.2cto.com/kf/201506/410705.html 

 

8 viewRoot 的目的,实际上在什么地方渲染控件

每个activity有个window,window被windowmanager管理.

每个window都有decorview.

每个window都有ViewRoot.

绘制发起从ViewRoot.

事件传递发起冲ViewRoot.

绘制传递canvas, canvas来自surface.

http://blog.csdn.net/jacklam200/article/details/50038989



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的背景,可以设置为柔和的颜色






    本文转自fengyuzaitu 51CTO博客,原文链接:http://blog.51cto.com/fengyuzaitu/1946720,如需转载请自行联系原作者



相关文章
|
3月前
|
Android开发
Android中SurfaceView的双缓冲机制和普通View叠加问题解决办法
本文介绍了 Android 平台上的 SurfaceView,这是一种高效的图形渲染控件,尤其适用于视频播放、游戏和图形动画等场景。文章详细解释了其双缓冲机制,该机制通过前后缓冲区交换来减少图像闪烁,提升视觉体验。然而,SurfaceView 与普通 View 叠加时可能存在 Z-Order 不一致、同步问题及混合渲染难题。文中提供了使用 TextureView、调整 Z-Order 和创建自定义组合控件等多种解决方案。
159 9
|
iOS开发
iOS开发 - 关于MJRefresh刷新崩溃的问题
iOS开发 - 关于MJRefresh刷新崩溃的问题
175 0
|
消息中间件 Android开发
读源码长知识 | Android卡顿真的是因为”掉帧“?
掉帧是因为生产帧速度跟不上消费帧速度。Choreographer 用于同步生产和消费帧的速度。以读源码方式还原掉帧时软件层面发生的事情。
273 0
|
前端开发 Java Linux
内存泄露,OOM,ANR ,Devik 进程,Framework原理,Activity 生成一个 view,Android 中的动画,SurfaceView和V
内存泄露,OOM,ANR ,Devik 进程,Framework原理,Activity 生成一个 view,Android 中的动画,SurfaceView和V
245 0
|
缓存 开发者
关于recyclerview复用导致应用卡顿崩溃
recyclerview复用导致应用卡顿崩溃
247 0
|
缓存 Android开发
Android笔记:使用Glide加载图片刷新时会闪烁
Android笔记:使用Glide加载图片刷新时会闪烁
1298 0
|
Android开发 数据格式 XML
Android8.0 适配解决页面跳转过程出现短暂黑屏的问题
      小菜在适配 Android8.0 过程中,遇到很多问题,有很多很常见的问题,今天来整理一下页面跳转时黑屏的问题。 问题猜测 猜测一:       显示 Activity 页面之前会优先开启一个 Starting Window(Preview Window),等待 Activity 加载完成之后显示 UI 界面,猜测在这个等待过程中可能会出现页面跳转时的短暂黑屏。
3242 0