1:DisplayMetrics  Display 获取屏幕的基本信息

DisplayMetrics displayMetrics=new DisplayMetrics();
Display display=getWindowManager().getDefaultDisplay();
display.getMetrics(displayMetrics);Log.d(TAG, "onClick: densityDpi=="+displayMetrics.densityDpi+"--density=="+displayMetrics.density+"--heightPixels=="+displayMetrics.heightPixels+"--widthPixels=="+displayMetrics.widthPixels+"--xdpi=="+displayMetrics.xdpi+"-ydpi=="+displayMetrics.ydpi+"--=="+displayMetrics.scaledDensity);

2:keyEvent

//对应的键值,KeyEvent.KEYCODE_DPAD_LEFT;

keyEvent.getKeyCode();
//对应那种操作  按下或者抬起  KeyEvent.ACTION_DOWN;
keyEvent.getAction();
//获取按键事件触发的次数keyEvent.getRepeatCount();
//不准确  keyEvent.isLongPress();长按事件执行的流程:
长按事件执行顺序为先执行down事件getrepeatcount一直增加(判断是否为长按事件,只需要判断getrepeatcount是否大于零)
直到最后按键起来事件变为up事件getrepeatcount0

activity里面dispatchKeyEvent相关逻辑,

event.dispatch(this, decor != null
            ? decor.getKeyDispatcherState() : null, this);这个时候我们将activity自身
class Activity extends ContextThemeWrapperimplements  KeyEvent.Callback,  activity自身实现了keyevent的callback回调接口
所以 在activity里面可以得到这些回调方法

public boolean dispatchKeyEvent(KeyEvent event) {

    onUserInteraction();// Let action bars open menus in response to the menu key prioritized over
    // the window handling it
    if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&mActionBar != null && mActionBar.onMenuKeyEvent(event)) {return true;}Window win = getWindow();if (win.superDispatchKeyEvent(event)) {return true;}View decor = mDecor;if (decor == null) decor = win.getDecorView();return event.dispatch(this, decor != null
            ? decor.getKeyDispatcherState() : null, this);
}

view同样如此:view除了可以回调实现的值按键信息,还可以通过主动监听的方式实现及

but.setOnKeyListener(new View.OnKeyListener() {@Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {return false;}
});

3:LayoutInflater.Factory
实现换肤效果:主题切换
http://blog.csdn.net/llew2011/article/details/51287391

4:SurfaceHolder 是一个接口

SurfaceHolder.Callback

surfaceview

TextureView

GLSurfaceView

SurfaceTexture

5: ViewTreeObserver

ViewTreeObserver 注册一个观察者来监听视图树,当视图树的布局、视图树的焦点、视图树将要绘制、
视图树滚动等发生改变时,ViewTreeObserver都会收到通知,ViewTreeObserver不能被实例化,可以调用
View.getViewTreeObserver()来获得。

通过ViewTreeObserver .addOnPreDrawListener来获得宽高,在执行onDraw之前已经执行了
onLayout()和onMeasure(),可以得到宽高了,当获得正确的宽高后,请移除这个观察者,
否则回调会多次执行

//获得ViewTreeObserver
ViewTreeObserver observer=view.getViewTreeObserver();
//注册观察者,监听变化
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 @Override public boolean onPreDraw()
{
if(observer.isAlive()){ observer.removeOnDrawListener(this);
}
//获得宽高
int viewWidth=view.getMeasuredWidth();
int viewHeight=view.getMeasuredHeight();
return true; } });

6:Context获取各种系统服务:

public abstract Object getSystemService(@ServiceName @NonNull String name);
WINDOW_SERVICE = "window";
windowManager= (WindowManager) getSystemService(Context.WINDOW_SERVICE);

7: Window PhoneWindow https://www.jianshu.com/p/9da7bfe18374 详细流程

每一个Activity都包含一个Window对象,Window对象通常由PhoneWindow实现PhoneWindow:将Decoriew设置为整个应用窗口的根View。是Window的实现类。它是Android中的最基本的窗口系统,每个Activity 均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。DecorView:顶层视图,将要显示的具体内容呈现在PhoneWindow上.
DecorView是当前Activity所有View的祖先,它并不会向用户呈现任何东西,它主要有如下几个功能,可能不全:

  • A. Dispatch ViewRoot分发来的key、touch、trackball等外部事件;
  • B. DecorView有一个直接的子View,我们称之为System Layout,这个View是从系统的Layout.xml中解析出的,
  • 它包含当前UI的风格,如是否带title、是否带process bar等。可以称这些属性为Window decorations。
  • C. 作为PhoneWindow与ViewRoot之间的桥梁,ViewRoot通过DecorView设置窗口属性。
  • //可以这样获取 View view = getWindow().getDecorView();
  • DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。
  • DecorView里面TitleView:标题,可以设置requestWindowFeature(Window.FEATURE_NO_TITLE)
  • 取消掉ContentView:是一个id为content的FrameLayout。
  • 我们平常在Activity使用的setContentView就是设置在这里,也就是在FrameLayout上
        ViewGroup viewone= (ViewGroup) getWindow().getDecorView();Log.d(TAG, "onCreate: getChildCount=="+viewone.getChildCount());ViewGroup viewThree= (ViewGroup) viewone.getChildAt(0);if(viewThree instanceof LinearLayout){Log.d(TAG, "onCreate: LinearLayout");}Log.d(TAG, "onCreate: getChildCount=="+viewThree.getChildCount());ViewGroup viewfour= (ViewGroup) viewThree.getChildAt(1);if(viewfour instanceof FrameLayout){Log.d(TAG, "onCreate: FrameLayout");}
//      就是我们setContentView使用的view
        View viewTwo= findViewById(android.R.id.content);if(viewTwo instanceof FrameLayout){Log.d(TAG, "onCreate: FrameLayout");}if(viewTwo.equals(viewfour)){Log.d(TAG, "onCreate: 同一个对象");}//        D/MainActivity: onCreate: getChildCount==1
//        /MainActivity: onCreate: LinearLayout
//        D/MainActivity: onCreate: getChildCount==2
//        D/MainActivity: onCreate: FrameLayout
//        D/MainActivity: onCreate: FrameLayout
//        D/MainActivity: onCreate: 同一个对象

关键看Window的实现类PhoneWindow

setContentView源码简单介绍:

getWindow().setContentView(layoutResID);
installDecor();

创建decorview 获取我们设置的feature 就是为什么我们需要在setContentView之前

调用设置feature的api

getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Window是一个抽象类,提供了各种窗口操作的方法,比如设置背景标题ContentView等等PhoneWindow则是Window的唯一实现类,它里面实现了各种添加背景主题ContentView的方法,内部通过DecorView来添加顶级视图每一个Activity上面都有一个Window,可以通过getWindow获取DecorView,顶级视图,继承与FramentLayout,setContentView则是添加在它里面的@id/content里setContentView里面创建了DecorView,根据Theme,Feature添加了对应的布局文件当setContentView设置显示后会回调Activity的onContentChanged方法

启动一个Activity流程:

ViewManager接口:

add and remove child views to an Activity  也是一个系统manager  通过getSystemService()获取
addView  UpdateViewLayout RemoveView

WindowManager:窗体管理器 实现了ViewManager接口

WindowManagerImpl:WindowManager实现类

Window窗体

ViewGroup也实现了ViewManager

可以看到在Activity创建到attach的时候,对应的Window窗口也被创建起来,
而且Window也与WindowManager绑定。而mWindow,和mWindowManager则是Activity的成员变量。
可以看到这里WindiwManager的创建是context.getSystemService(Context.WINDOW_SERVICE)

在创建号Activity之后 会创建Window和WindowManager

 mWindow = new PhoneWindow(this);
mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

mWindow.setWindowManager( (WindowManager)context.getSystemService

(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(),

(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

来创建Activity以及Activity所需要的Context,Window,调用了Activity的onCreate,onStart方法,
而接下来调用了handleResumeActivity方法

performResumeActivity则是让Activity调用onResume方法

r.window = r.activity.getWindow(); //赋值 View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; //把当前的DecorView与WindowManager绑定一起 wm.addView(decor, l); }

r.window = r.activity.getWindow();
//赋值
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
 a.mWindowAdded = true;
//把当前的DecorView与WindowManager绑定一起 wm.addView(decor, l);
}

当前Activity的Window进而获取到DecorView,再获取当前Activity的WindowManager,将DecorView与WindowManager绑定一起。

详细流程图

ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现。这个好理解,在WindowManagerGlobal中实现方法中,都可以见到ViewRootImpl,也就说WindowManagerGlobal方法最后还是调用到了ViewRootImpl。addView,removeView,update调用顺序
WindowManagerImpl -> WindowManagerGlobal -> ViewRootImpl

View通过ViewRootImpl来绘制

前面说到,ViewRootImpl调用到requestLayout()来完成View的绘制操作,我们看下源码

 @Overridepublic void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {checkThread();mLayoutRequested = true;scheduleTraversals();}}

View绘制,先判断当前线程

void checkThread() {if (mThread != Thread.currentThread()) {throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");}}

scheduleTraversals中会通过handler去异步调用mTraversalRunnable接口

  final class TraversalRunnable implements Runnable {@Overridepublic void run() {doTraversal();}}

可以看到,最后真正调用绘制的是performTraversals()方法,这个方法很长核心便是

private void performTraversals() {  ......  performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);...performLayout(lp, desiredWindowWidth, desiredWindowHeight);......  performDraw();}......  }  

performTraversals方法会经过measure、layout和draw三个过程才能将一个View绘制出来,所以View的绘制是ViewRootImpl完成的,另外当手动调用invalidate,postInvalidate,requestInvalidate也会最终调用performTraversals,来重新绘制View。

View与WindowManager联系

那么View和WindowManager之间是怎么通过ViewRootImpl联系的呢。

从第三篇文章中我们知道,WindowManager是继承于ViewManager接口的,而ViewManager提供了添加View,删除View,更新View的方法。就拿setContentView来说,当Activity的onCreate调用到了setContentView后,view就会被绘制了吗?肯定不是,setContentView只是把需要添加的View的结构添加保存在DecorView中。此时的DecorView还并没有被绘制(没有触发view.measure,layout,draw)。

DecorView真正的绘制显示是在activity.handleResumeActivity方法中DecorView被添加到WindowManager时候,也就是调用到windowManager.addView(decorView)。而在windowManager.addView方法中调用到windowManagerGlobal.addView,开始创建初始化ViewRootImpl,再调用到viewRootImpl.setView,最后是调用到viewRootImpl的performTraversals来进行view的绘制(measure,layout,draw),这个时候View才真正被绘制出来。

这也就是为什么我们在onCreate方法中调用view.getMeasureHeight() = 0的原因,我们知道activity.handleResumeActivity最后调用到的是activity的onResume方法,但是按上面所说在onResume方法中调用就可以得到了吗,答案肯定是否定的,因为ViewRootImpl绘制View并非是同步的,而是异步(Handler)。

难道就没有得监听了吗?相信大家以前获取使用的大多是

view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {// TODO Auto-generated method stub}
});

没错,的确是这个,为什么呢,因为在viewRootImpl的performTraversals的绘制最后,调用了

 {if (triggerGlobalLayoutListener) {mAttachInfo.mRecomputeGlobalAttributes = false;mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();}...performDraw();
}

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView) findViewById(R.id.tv);new Thread(new Runnable() {@Overridepublic void run() {tv.setText("Hohohong Test");}}).start();}

我是在onCreate里面的子线程去更新UI的,那么会报错吗?测试后你就会知道不会报错,如果你放置个Button点击再去调用的话则会弹出报错。为什么会这样?
答案就是跟ViewRootImpl的初始化有关,因为在onCreate的时候此时View还没被绘制出来,ViewRootImpl还未创建出来,它的创建是在activity.handleResumeActivity的调用到windowManager.addView(decorView)时候,如前面说的ViewRootImpl才被创建起来

而这个AttachInfo则是View里面一个静态内部类,它的构造方法

   AttachInfo(IWindowSession session, IWindow window, Display display,ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {mSession = session;mWindow = window;mWindowToken = window.asBinder();mDisplay = display;mViewRootImpl = viewRootImpl;mHandler = handler;mRootCallbacks = effectPlayer;}

可以看到viewRootImpl在它的构造方法里赋值了,那么这个方法肯定是在ViewRootImpl创建时创建的,而ViewRootImpl的创建是在调用WindowManagerGlobal.addView的时候

     root = new ViewRootImpl(view.getContext(), display);

而构造方法中

 public ViewRootImpl(Context context, Display display) {mContext = context;mWindowSession = WindowManagerGlobal.getWindowSession();...mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);...}

可以看到View与ViewRootImpl绑定一起了。
之后就可以通过view.getViewRootImpl获取到,而在Window里面也可以获取到ViewRootImpl,因为Window里面有DecorView(这里说的Window都是讲它的实现类PhoneWindo),前三篇已经介绍过了,通过DecorView来获取到ViewRootImpl

 private ViewRootImpl getViewRootImpl() {if (mDecor != null) {ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();if (viewRootImpl != null) {return viewRootImpl;}}throw new IllegalStateException("view not added");}

另外,一个View会对应一个ViewRootImpl吗?我们做个测试,在一个布局中打印两个不同控件的ViewRootImpl的内存地址

小结

  • 之所以说ViewRoot是View和WindowManager的桥梁,是因为在真正操控绘制View的是ViewRootImpl,View通过WindowManager来转接调用ViewRootImpl
  • 在ViewRootImpl未初始化创建的时候是可以进行子线程更新UI的,而它创建是在activity.handleResumeActivity方法调用,即DecorView被添加到WindowManager的时候
  • ViewRootImpl绘制View的时候会先检查当前线程是否是主线程,是才能继续绘制下去

10:

ViewGroup.LayoutParams

最基本的布局类,  只能设置组件的宽和高。

ViewGroup.LayoutParams lp=new ViewGroup.LayoutParams(0,0);
lp.width;
lp.height;
MarginLayoutParams extends ViewGroup.LayoutParams

MarginLayotuParams 布局参数可以设置边距。

ViewGroup.MarginLayoutParams lp=new ViewGroup.MarginLayoutParams(0,0);
lp.rightMargin;
lp.bottomMargin;
lp.height;
lp.width;
lp.setMargins();
lp.leftMargin;
class LayoutParams extends ViewGroup.MarginLayoutParams

RelativeLayout.LayoutParams 是继承于MarginLayoutParams

android中api简介相关推荐

  1. 【Android】 Android中适配器简介

    1. BaseAdapter的使用实例 BaseAdapter baseAdapter = new BaseAdapter() {@Overridepublic View getView(int po ...

  2. Android中Context简介(通俗易懂)

    Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄.很多方法需要通过 C ...

  3. Android中Context简介

    Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄.很多方法需要通过 C ...

  4. Android中GPS简介及其应用

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) GPS是Global Positioning System(全球定位系统)的简称,它的作用就是为全球的物体提供 ...

  5. Android高级开发第二讲--Android中API翻译之Activity

    博客出自:刘兆贤的博客_CSDN博客-Java高级,Android旅行,Android基础领域博主,转载注明出处! All Rights Reserved ! Activity主要用来展示给用户,让用 ...

  6. [android] 多媒体播放api简介

    界面布局,水平方向四个按钮平均分布,使用权重,定义android:layout_width="0dp",定义layout_weight="1"这个属性全都一致就 ...

  7. 从源码角度解析Android中APK安装过程

    从源码角度解析Android中APK的安装过程 1. Android中APK简介 Android应用Apk的安装有如下四种方式: 1.1 系统应用安装 没有安装界面,在开机时自动完成 1.2 网络下载 ...

  8. android 序列化存储对象,android中对象序列化存储

    项目中要存储一些数据为了提高不必要的网络请求,提高效率,用到数据持久化的知识点,针对这个问题,解决办法其实有很多,以前在项目中是服务获取到webservice的xml,然后直接将xml保存在本地,之后 ...

  9. Android中基于心知天气API获取天气信息

    Android中基于心知天气获取天气信息 JSON JSON简介 JSON对象 JSON数组 JSON解析 Android中获取天气 获取天气的流程 获取心知天气的API key 获取心知天气的API ...

最新文章

  1. curl模拟多线程抓取网页(优化)
  2. Java之String类
  3. Centos 安装 NodeJS
  4. python3 的 zip
  5. 初试牛刀---css中的小细节
  6. python练习之析构函数
  7. 设置在VS2005的IDE中迅速打开xaml文件
  8. 前端学习(2955):项目中组件的全局注册
  9. python常用正则表达式_Python3常用正则表达式
  10. 后端工程师的「跨域」之旅
  11. 中fifo算法_java线程池,工作窃取算法
  12. tomcat遇到jre\lib\ext\localedata.pack 时出错
  13. 图像去雾算法(一)相关研究及链接
  14. CPython中多线程的限制
  15. 2022年高压电工操作证考试题库及在线模拟考试
  16. PX4从放弃到精通(一):开源飞控PX4简介+系列文章大纲
  17. .Net学习平台有很多,最快捷的是在这里?
  18. JavaScript数组filter方法
  19. 生命科学计算机科学结合,生命科学与计算机科学的结合发展研究.docx
  20. 南京考公上岸经验分享

热门文章

  1. 第1056期机器学习日报(2017-08-09)
  2. 使用函数输出一个整数的逆序数
  3. 联想 DM5000H混合闪存阵列助力汽车街优化数据管理
  4. wordpress用途_20个免费的多用途WordPress主题
  5. Hive学习笔记(4)—— hive练习
  6. 零基础,如何学习CAD和3Dmax,有什么学习计划吗?
  7. Solr基础教程之环境搭建(一)
  8. 100+套Axure数据可视化大屏展示原型模板
  9. 计算机软件理论考博复试,考博复试时的自我介绍
  10. 自学java基础笔记