SurfaceView源码以及崩溃剖析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的背景,可以设置为柔和的颜色


以上是关于SurfaceView源码以及崩溃剖析的主要内容,如果未能解决你的问题,请参考以下文章

SurfaceView及TextureView区别

SurfaceView为什么不能做动画?

尝试在空对象引用上调用虚拟方法 'android.view.SurfaceHolder android.view.SurfaceView.getHolder()'

LevelDB 源码剖析WAL模块:LOG 结构读写流程崩溃恢复

LevelDB 源码剖析WAL模块:LOG 结构读写流程崩溃恢复

LevelDB 源码剖析WAL模块:LOG 结构读写流程崩溃恢复