安卓小知识2

一:SurfaceView

普通的Android控件,例如TextView、Button和CheckBox等,它们都是将自己的UI绘制在宿主窗口的绘图表面之上,这意味着它们的UI是在应用程序的主线程中进行绘制的,由于应用程序的主线程除了要绘制UI之外,还需要及时地响应用户输入,否则的话,系统就会认为应用程序没有响应而出现ANR,对于一些游戏,摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行高效的绘制,因此,它们的UI就不适合在应用程序的主线程中进行绘制,这时候就必须要给那些需要复杂而高效UI的视图生成一个独立的绘图表面,以及使用一个独立的线程来绘制这些视图的UI。
在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面,由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行行绘制,又由于不占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。

SurfaceView的绘制方式效率非常高,因为SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下)

Thread.yield(): 与Thread.sleep(long millis):的区别:

Thread.yield(): 是暂停当前正在执行的线程对象 ,并去执行其他线程。
Thread.sleep(long millis):则是使当前线程暂停参数中所指定的毫秒数然后在继续执行线程。
SurfaceView和View的区别

总的归纳起来SurfaceView和View不同之处有:

  1. SurfaceView允许其他线程更新视图对象(执行绘制方法)而View不允许这么做,它只允许UI线程更新视图对象。

  2. SurfaceView是放在其他最底层的视图层次中,所有其他视图层都在它上面,所以在它之上可以添加一些层,而且它不能是透明的。

  3. 它执行动画的效率比View高,而且你可以控制帧数。

  4. SurfaceView在绘图时使用l了双缓冲机制,而View没有。

二:何为句柄 (Too many open files 句柄泄露的问题)

一个进程在初始化时,系统将为他分配一个句柄表(handle table),这个句柄表仅仅供内核对象使用,不适用于用户对象,用于创建内核对象的任何函数都会返回一个与进程相关的句柄,这个句柄可以由同一个进程中运行的所有线程使用,系统用索引来标识内核对象的信息保存在进程句柄表中的位置,要得到实际索引值,就需要得到句柄。句柄和索引之间的关系在大部分操作系统中是使句柄值右移两位。
所以我们通常说句柄标识一个对象,这句话没有错误,说它是一个指针就有问题了,因为我们是通过使用某个对象的句柄从而得到该对象在句柄表中的索引,最终得到该对象在内存中的地址,即指针。
查看当前句柄详情:adb shell lsof -p <pid>
查看当前句柄总数:adbshell lsof -p <pid> |wc –l
可查看相详情

  • 句柄是用来标识某一资源的,是用来获取资源地址的。
  • 句柄其实是一个索引

一个应用程序在执行的时候并不是所有的代码都放进内存,即使放入了内存,也不可能在整个运行期间一直停留在内存,毕竟内存还是比较珍贵的资源,所以对于某一资源,在不同的时刻物理地址可能不一样,但是在内核对象表中,句柄其实是一个索引,根据该索引我们可以很快的找到此时资源的物理地址。而句柄比较稳定,所以window操作系统就引入了句柄的概念。

三:Handler

如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。我遇到的一种的实际情况,就是地图数据的获取(直接放到主线程中),就会导致程序崩溃。
  我们需要把这些耗时的操作,放在一个子线程中。而主线程主要负责界面的更新。
Handler就是解决子线程和主线程通信的问题;Handler是运行在主线程中的(UI线程中), 它与子线程是通过Message对象来传递数据的。
Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) ,然后完成UI的更新的工作。
Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) ,然后完成UI的更新的工作。

Handler的特点:

(1)安排消息或Runnable 在某个主线程中某个地方执行;

(2)安排一个动作在不同的线程中执行。

Handler分发消息的方法:

post(Runnable)

postAtTime(Runnable,long)

postDelayed(Runnable long)

sendEmptyMessage(int)

sendMessage(Message)

sendMessageAtTime(Message,long)

sendMessageDelayed(Message,long)

post类方法是排列一个Runnable对象到主线程队列中,

sendMessage类方法, 是发送Message对象到队列中,等待更新。

这里需要把整个过程理清楚:

image

在子线程中通过Handler向发送Message,Handler先把这些消息放到消息队列中。然后Looper通过DisopatchMessage分发消息,分发的目标就是Handler。然后Hander调用回调函数(如果设置callback的话),如果没有就调用子类的中的handleMessage来处理和更新UI

Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列的。Looper不断地从MessageQueue中抽取Message执行。

Android Looper和Handler

  • Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

  • Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

  • MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

  • Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消 息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该 线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。 如下例所示:

class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

这样你的线程就具有了消息处理机制了,在Handler中进行消息处理。
Runnable是一个接口,不是一个线程,一般线程会实现Runnable。所以如果使用匿名内部类实现Runnable是运行在UI主线程的,如果使用实现这个Runnable接口的线程类,则是运行在对应线程的。

Runnable 并不一定是新开一个线程,比如下面的调用方法就是运行在UI主线程中的:

 Handler mHandler=new Handler(); 
 mHandler.post(new Runnable(){ 
    @Override public void run() 
    { // TODO Auto-generated method stub 
     } 
 });

调用handler的post方法,把Runnable对象(一般是Runnable的子类)传过去;handler会在looper中调用这个Runnable的Run方法执行。

其实主要过程就是:

子线程通过Handler----->发送Msg或者Runnable到---->Message Queue消息队列;

Looper从消息队列中取出消息--------->DispatchMessage然后分发消息——--->分发的目标就是Handler------>Handler调用回调函数或者Handler的子类的handleMessage来处理消息,并且更新UI

Handler类有好几种构造函数,一种是带looper的,一种是带callback回调函数的。

public Handler(Looper L){
……………………
}
public Handler(Looper L,Callback callback){
…………………………
}
如果Handler对象使用的是带callback的Handler的构造函数,那么凡是发送到这个Handler的消息,都会被这个Callback函数处理。

如果Handler对象使用的是不带callback的Handler的构造函数,那么发送到这个Handler的消息,会被类Handler中的handleMessage()这个函数处理。
更多详情请看此网址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 问题:有时我们需要在spark的程序中读取一些外部的配置文件,解决的方式也是比较多的,我这里记录一下我测试解决的方...
    light01阅读 3,883评论 0 0
  • 每个人都很奇怪呵。 街边的小吃店,低头不语的行人,33路公车路过的下一站,你,还会在吗? 突然,就喜欢...
    你好啊鹿阅读 1,520评论 4 2
  • 补16.11.12日: 看了无锡马拉松的宣传视频,时间大体是在明年3月25日,人生总要去跑一次马拉松的冲动终于还是...
    梁余音阅读 295评论 0 0
  • 原以为《Me before you》(遇到你之前)是一个老套的故事:活泼开朗的女孩给全身瘫痪人生无望的男主角带来了...
    拾光人生阅读 233评论 0 1
  • 今天是大暑,外面似蒸笼,静坐依然会挥汗如雨,心里却是拔凉拔凉的,如入隆冬,恐一触碰,便会心碎一地……手捧书本,却无...
    水滴_fd45阅读 430评论 7 5