当前位置:  编程技术>移动开发
本页文章导读:
    ▪macbook pro装配双系统        macbook pro安装双系统在mac下安装双系统,一台电脑顶两台使用。刚才看到了一个安装双系统的方法。转过来供大家学习一下。其实也容易操作的。 1、正常进入MacOS(以下简称mac),在桌面上.........
    ▪ Handler知识点小结        Handler知识点总结为什么android中要使用多线程? 主线程又称为UI线程。正是因为在android中,所有与UI有关的操作(例如创建UI,刷新UI,处理UI等)都必须在主线程中进行,所以主线程又称为UI.........
    ▪ 关于Handler二三事(上)       关于Handler二三事(下) 消息的注册到业务的实现 从接触呼叫业务的第一天起,我就一直琢磨代码里成群结队的registerXXXX方法跟notifyXXXX方法究竟是个怎么关系。 一个消息(Message)从注册到.........

[1]macbook pro装配双系统
    来源: 互联网  发布时间: 2014-02-18
macbook pro安装双系统

在mac下安装双系统,一台电脑顶两台使用。刚才看到了一个安装双系统的方法。转过来供大家学习一下。其实也容易操作的。

1、正常进入MacOS(以下简称mac),在桌面上点击前往→实用工具:

2、进入“Boot Camp 助理”:

3、进来之后是介绍,直接继续:

4、这一步需要详细说明一下,先见图:
由于我的截图是在安装完Win之后,所以会和安装之前有一些不同。
黄色部分:这部分没有不同,需要提供Win7的安装光盘的镜像(ISO文件)和U盘。
红色部分:这部分也没有不同,这个选项是从网上下载MacBook在Win7里的必要的驱动程序。
蓝色部分:也许这颜色更像紫色?好吧,不同的就是这块。在安装前,这里显示的肯定是“安装 Windows 7”,由于我截图的时候已经装完了,所以这里就变成了“移除 Windows 7” 。
一般来讲在安装Win7的时候三项都要选上,然后继续。

5、再往下一步我就没法截图了,借用一下从网上找来的图吧
到图片这个画面之前还有一步,是选择Win7的镜像文件和安装文件的存储位置(这里的意思实际上是Mac把Win7的镜像文件解开后放到U盘上并把U盘制作成可引导启动的U盘),注意这里的U盘需要FAT格式。然后图中这一步就是划分硬盘空间,也就是留多大地方给MacOS,分多大地方给Win。如果你打算经常使用Win的话,最好多分一些空间给Win。

6、之后就一带而过了,往后基本上就是自动的了:将Win7安装盘镜像文件的内容复制到U盘上→下载“Windows支持软件”(这个作用就是以前从网上找、需要下载刻盘的那个驱动包)→重启后从U盘启动进入Win7安装程序。

7、到了这里就需要手动了,常规的Win7安装程序。需要注意的是,在选择安装位置的时候,一定要选择卷宗是“BOOTCAMP”的那个分区,并且谨慎起见对比一下在第5步图片中分配给Win的空间大小和这里看到的“BOOTCAMP”分区的大小是否一致。然后格式化成NTFS格式,就可以继续了。

8、这个时候Win7应该安装好了,下面要做的就是安装驱动。
在第一次的时候我忘记了那个“Windows支持软件”这么个东西,于是把刚才用于安装的U盘格式化了,在Win7里用驱动精灵来下载安装驱动。大部分的驱动都没问题,有问题的是蓝牙和声卡。蓝牙是压根没装上,声卡的问题是设备运行状况显示正常,右下角里的喇叭图标也正常,在播放声音的时候甚至会有音量的显示,但就是没有声音。后来发现应该用那个“Windows支持软件”来安装驱动。无奈又回到了MacOS,Bootcamp助理中,这时候的步骤和上面的图就是一致的了(因为我就是在这个过程中截的图)。不同的从下面开始。

9、不要选择“创建Windows 7安装磁盘”和“移除Windows7”!

为什么不选就不多解释了….也就是只选择中间的“从 Apple 下载最新的 Windows 支持软件”,点继续。

10、将“最新的 Windows 支持软件”存放到U盘上

因为MBA没有光驱,这哥们也没买外置光驱,所以依旧用U盘(其实用U盘挺好的,方便快捷绿色环保…),注意这里的U盘依旧必须为FAT格式,继续到下一步。

11、选择存储位置,其实就是选择你插入的U盘
实在抱歉,截这张图的时候把U盘拔出去了…所以…其实U盘的位置就是绿色部分那里,选择即可。至于红色部分,就是U盘里这个“最新的 Windows 支持软件”的文件夹名称,不用改。继续。

12、OK,我发现截图到此为止了,之后就是自动的了,从网上下载,自动放到U盘里,完成后重启进入Win7,安装即可。

13、好吧,我最终还是拿出了那个U盘,这是下载后存进来的内容,总共683M。
里面有说明文档(Boot Camp Installation & Setup Guide.pdf),英文的。不过实际上运行setup.exe就行了,一路下一步,到最后安装完成重启即可,文档没什么可看的。

原文地址   http://tech.mclarian.com/a/365

    
[2] Handler知识点小结
    来源: 互联网  发布时间: 2014-02-18
Handler知识点总结
为什么android中要使用多线程?
Handler是在多线程之间使用的,用于线程之间进行通信。
要想知道为什么需要Handler就首先说明android的主线程和工作线程。
主线程又称为UI线程。正是因为在android中,所有与UI有关的操作(例如创建UI,刷新UI,处理UI等)都必须在主线程中进行,所以主线程又称为UI 线程。
如果当一个程序进行下载等操作的时候,需要的时间是非常长的,这时候如果主线程在执行下载量大的工作时,就会被阻塞在当前状态。此时,就会忽略用户操作,我给他称为假死机(个人理解)。这是如果用户的操作在5秒之内没有得到相应,android系统就会弹出一个对话框—程序无响应,强制关闭当前程序还是等待。这个叫ANR(android not responding)。
这种情况是android应用程序中非常避讳的。
要解决这种问题,就需要程序再创建一个子线程,即工作线程。让工作线程进行耗费大量时间的操作,而让主线程响应用户的操作。
也就是要做到不在主线程中执行可能导致阻塞的耗时代码而是把耗时代码在工作线程中执行。主线程只负责程序的调度和控制
为什么要使用Handler?
有人可能会问:创建一个工作线程太容易了,直接new Thread()不就可以了吗?然后把下载的工作全部放在工作线程中,当下载完成之后更新视图。
其实,这样做是行不通的,因为上边已经说到,android中关于UI的所有操作都必须放在主线程中进行操作。
所以正确的做法应该是:当我们需要下载一幅图片的时候,要创建一个工作线程进行下载,以便于主线程继续响应用户的操作。当工作线程将图片下载完成之后,我们需要工作线程通过一定的消息传递机制将下载的图片传递回UI线程,然后UI线程做显示图片的操作。
Handler,Looper,Message等一些类就凸显出他们的作用。
                              
通过上边的图,我们可以看到,在多线程处理中,在Handler,Message,Looper这三个类的处理中,可以组成一个闭合的环,这样我们就可以完成多线程的操作。
最简单的实现步骤是什么?
首先声明:以下步骤只是最简单的handler的使用步骤,如果想用更深入了解还得继续看下边的内容。
1、在主线程中创建一个Handler对象,并且覆写其handleMessage方法。
2、在创建的工作线程中创建一个Message消息对象,设置其响应的属性
3、使用此handler对象将这个Message发送到主线程的消息队列中。
4、主线程中的Looper对象会不断地监听消息队列中的内容,当监听到消息队列中有新的内容时,就会从消息队列中拿到此消息,并且交给发送这个消息的handler对象进行处理。
5、具体处理的方法则是调用第一步骤中的handleMessage方法中的内容
当看完以上的步骤,也许会有很多疑问,比如Looper是哪里来的?Message是什么?Message中都有哪些内容?
要想了解以上东西,继续往下看。
重点类的重点方法和属性有什么?Looper类
1、作用:
这个是用来封装消息循环和消息队列的一个类。上边的步骤已经说过,这个Looper类负责从消息队列中获取消息,并且执行handler的handleMessage方法。
其实当Looper获取到消息对象后,会进行一系列的判断。可能会执行不同的代码。执行handler的handleMessage方法只是其中的一种可能性。
具体要执行那个方法,我们待会再讲。
2、特性:
       只有在主线程中android系统才会默认的生成一个Looper对象。
       在工作线程中,如果不手动的建立一个Looper对象,默认是不存在Looper对象的。
Message类
1、作用:
         message,顾名思义,就是消息。也就是你要传递的数据的一种载体。例如,我想要发送一个标识符为1,传递一个int类型的数值4和一个代表音乐的music对象。那么我可以设置代表标识符的属性what的值为1,代表int类型的属性值为4,代表Object的属性值为music。
2、构造方法:Message()
3、实例化方法:
   obtain()     
此方法是首先从消息池中取得消息,如果消息池中的消息使用完再新建一个消息,这种方法比直接调用构造方法创建一个新的消息对象节省资源。
   obtain(Message msg)
   obtain(Handler target)
   obtain(Handler target,Runnable callback)
   obtain(Handler target,int what)
   obtain(Handler target,int what,Object obj)
   obtain(Handler target,int what,int arg1,intarg2)
   obtain(Handler target,int what,int arg1,intarg2,Object obj)
4、主要属性
   公共:
   intwhat   代表消息的标识符,用于唯一标识消息类型
   intarg1   可以用此属性传递一个int类型的数值
   int arg2      同arg1
   Object obj         可以用此属性传递一个Object类型的数值
  私有属性
   Handler target:该属性执行消息对象的发送者(handler)
   Runnable callback:
         当调用带有Runnable类型的构造方法创建消息的时候,当Looper对象从消息队列中拿出此消息时,会直接调用实现Runnable接口的对象的run()方法进行处理。而不是调用handler对象的handleMessage方法进行处理
5、主要方法:
   Runnable getCallback()
         获取实现Runnable接口的callback对象,注意这个callback属性没有setter方法,只有getter方法
   void setTarget(Handler target)
         设置目标handler,也就是说设置Looper对象获取这个消息后会交给哪个handler对象进行处理。
         注意,如果一个消息的目标handler为handler1,而实际发送这个消息的是handler2。
那么处理这个对象的handler是handler2,而不是handler1。因为在handler对象发送message的时候,会将发送此message的handler设为目标handler。
   Handler getTarget()
   void setData(Bundle data)
         在message中也可以直接传递Bundle对象,因为Bundle对象中装的都是键值对,这样这个消息就可以承载很多键值对了
   Bundle getData()
   void sendToTarget()
         将此消息发送给目标handler进行处理。也就是说当Looper从消息队列中获取此message后会交给目标handler处理。
         注意,此方法只有在调用setTarget()方法设置目标handler之后才能调用。否则只能使用handler.setMessage()方法发送消息。
Callback
boolean  handleMessage(Message msg)
callback接口中仅仅包含这一个抽象方法。
最值得注意的是,这个handleMessage方法的返回值是boolean类型的,而handler的handleMessage是void类型的。
Handler
1、构造方法:
   Handler()
   Handler(Looper looper) 创建一个Handler对象的时候指定一个Looper对象
   Handler(Callback callabck) 创建一个Handler对象的时候指定一个Callback对象
   Handler(Looper looper,Callback callback)
2、重要私有属性
   Looper looper
   Callback callback
3、主要方法:
   Looper getLooper()
         获取Looper对象。
         注意Looper对象没有setter方法。只能在调用构造方法的时候传递一个Looper对象
   boolean sendMessage(Message msg)
         发送一个message对象
   boolean sendMessageAtFrontOfQueue(Messagemsg)
         发送一个message对象,并且让此对象处于消息队列的头部,首先会被Looper对象拿走
   boolean sendMessageAtTime(Message msg,longtime)
         在一个时间点发送message对象
   boolean sendMessageDelayed(Message msg,longdelayMillis)
         延迟多长时间之后发送message消息
   boolean sendEmptyMessage(int what)
         发送一个只带有消息标识符的空消息
   boolean sendEmptyMessageAtTime(int what,longtime)
   boolean sendEmptyMessageDelayed(intwhat,long delayed)
   boolean post(Runnable callback)
         发送一个带有callback属性的消息
         这个方法的效果相当于
         Messagemessage  = Message. obtain(Handlertarget,Runnable callback)
         handler.sendMessage(message);
         上边的方法只是对以上两句代码的封装
         值得注意的是,并不是将一个实现Runnable接口的对象发送到消息队列,而是把一个封转好的消息发送到消息队列。我记得某个比较出名的视频里边就讲错了。特此更正一下。
   boolean postAtFrontOfQueue(Runnablecallback)
   boolean postAtTime(Runnable callback,longtime)
   boolean postDelayed(Runnable callback,longdelayed)
4、Handler的特性:
  1)Handler对象在创建时必须被关联到一个Looper(关联到消息队列)
    如果构造时未明确指定handler对象关联的Looper
    则默认关联到其创建时所在线程的Looper,如果该线程中不存在Looper
    则Handler创建失败
2)Handler对象,只能向其关联的消息队列发送消息
  3)消息处理原则:
     判断消息中是否包含Runnable对象(m.getCallback()!=null)
     如果消息中包含Runnable对象,则调用该对象的run方法,消息处理结束
     如果不包含Runnable对象,则进一步判断消息的发送者(m.getTarget())
     中是否包含callback对象(m.getTarget().getCallback()!=null)
       如果包含callback,则调用callback的handleMessage方法进行消息处理
         如果callback的handleMessage方法返回trueze消息处理结束
         否则,调用handler的handleMessage方法,消息处理结束
       如果不包含callback,则直接调用handler的handleMessage方法处理,消息
       处理结束
创建消息和发送消息一共有多少种方法?创建消息一共有三种方法:
1、  调用Message的构造方法
2、  调用Message的obtain()方法
3、  调用Handler对象的obtainMessage()的方法
发送消息一共有四种方法:
1、  调用Handler对象的sendMessage方法
2、  调用Handler对象的sendEmptyMessage方法
3、  调用Handler对象的Post方法
4、  调用Message对象的sendToTarget方法
消息处理的逻辑顺序是什么?
/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
1楼xiaoyingkm5天前 23:441)Handler对象在创建时必须被关联到一个Looper(关联到消息队列)n 如果构造时未明确指定handler对象关联的Loopern 则默认关联到其创建时所在线程的Looper,如果该线程中不存在Loopern 则Handler创建失败

    
[3] 关于Handler二三事(上)
    来源: 互联网  发布时间: 2014-02-18
关于Handler二三事(下)

消息的注册到业务的实现

从接触呼叫业务的第一天起,我就一直琢磨代码里成群结队的registerXXXX方法跟notifyXXXX方法究竟是个怎么关系。

一个消息(Message)从注册到被处理(handleMessage)都经过了哪些步骤?为什么要通过这种设计来完成线程间通信?是什么决定哪些消息在哪些类中被处理?消息上报之后,framework层都完成了哪些工作?

诸如此类,一言难尽。

在过去的总结中,我倾向于通过业务层不同呼叫状态的实例含义来理解整个通话的过程,而不是专注于dial,hangup,rejectCall,acceptCall这类的具体通话流程。换句话说,我觉得,如果能掌握不断改变的通话状态与android系统所做的处理之间的联系,也就能明白呼叫业务、甚至是android通信流程的真正脉络。

而这个Register-Notify模型,恐怕就是理解它的钥匙之一。

 

当我们正在谈论注册(register)的时候,它们在干什么

所谓的registerXXX,简单的说就是在某个特定的泛型列表中添加一个新的泛型节点。

两个有趣的地方。

第一,  为什么要通过不同的泛型列表来搜集不同的消息?

第二,  添加的这个新的泛型节点都包括哪些内容?

 

首先来看第二个问题,一个新的泛型节点通常包含了以下三样东西:

Handler h, int what, Object obj

在一个注册方法被调用时,h代表了能处理这个消息,同时也继承了Hanlder类的线程名称,what代表了该消息标签名称,而obj代表了以基本对象为格式所封装的消息内容。

再来看一个新的Registrant泛型节点用这些参数都构成了什么。

public
    Registrant(Handler h, int what, Object obj)
    {
        refH = new WeakReference(h);
        this.what = what;
        userObj = obj;
    }

套用上一节发快递来理解Handler的思路,这个注册新节点,其实就是个对消息打包过程,我在一则消息中标注了它的收件人信息(refH),签名(what),以及消息本身(userObj)。

 

这时候再来看第一个问题,如果把同样的收件人(refH),同样签名(what)的消息放到同一个队列当中,维护这个队列实际上就维护了所有同类注册的消息。相对的,从这个队列中取出的每个节点也都有同样的属性,可以用一种方式进行处理。

那么,为什么我会在意这个问题?

因为android系统为了“更直观”地向用户表达变量的含义,通常会给代表同种类型事件的消息以相同名称的泛型列表来维护。

譬如说,就“通话状态发生变化”这个事件而言,android系统用相同名称的泛型列表mPreciseCallStateRegistrants来维护了不同的签名(what)的消息触发,代码结构上从下到上是这样的:

在CallManager.java中

phone.registerForPreciseCallStateChanged(mHandler,EVENT_PRECISE_CALL_STATE_CHANGED, null);

在PhoneUtils.java中

cm.registerForPreciseCallStateChanged(mConnectionHandler,PHONE_STATE_CHANGED, cm);

两者调用的形参,被引用的对象都不一样,只有方法名称是相同的。但就是这个相同的名称,在最开始把我弄的稀里糊涂,以为同一个泛型列表可以收录同种事件,但是内容不一样的消息,这是错误的。希望大家能够区分清楚这是两条不同的列表,只是代表的事件类型相同罢了。

 

当我们正在谈论通知(notify)的时候,它们在干什么

注册完一个消息,从某种意义上说,只是准备好了包裹而没有投递它。真正的投递过程是在notfiy过程完成的。

注意,我说的投递过程,而不是处理过程。

在一开始学习Register-Notify模型的时候,我一直想当然的以为那些处于handleMessage代码段中的notifyXXXX就是这个消息的处理。

但愿你不是这么想的,因为这是个直观但是错误的认知。

 

我们来看notifyXXXX实现了什么。

一段合格的notfiy代码,必然带着AsyncResult类型的形参一块被调用。追根溯源,其实调用的是RegistrantList.java里的这个方法:

private synchronized void
    internalNotifyRegistrants (Object result,Throwable exception)
    {
       for (int i = 0, s = registrants.size();i < s ; i++) {
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result,exception);
       }
    }

诸位见到了,Ar格式的形参数据,其实包含了一个结果消息result,以及封装在内的异常信息exception。

再来看Registrant.java类的这个方法:

    /*package*/ void
    internalNotifyRegistrant (Object result,Throwable exception)
    {
        Handler h = getHandler();
 
        if (h == null) {
            clear();
        } else {
            Message msg = Message.obtain();
 
            msg.what = what;
           
            msg.obj = new AsyncResult(userObj,result, exception);
           
            h.sendMessage(msg);
        }
    }

这下清楚了。它从我的收件人(refH)封装中取出对应的收件人信息(h=getHandler()),然后从消息池中挖出一个消息,把之前写在包裹上的标签(what)给标注在消息上,然后根据消息的内容(userObj),结果信息(result)以及异常信息(exception)重新打包为消息的内容。

接着把它发出去。就像上一节我们看到的sendMessage方法一样,把这个包裹扔到待处理的线程消息队列中去。

然后……然后就像上一节描述的那样样,系统的回调机制会分发这条消息,最终在指定的Handler对象的handleMessage方法中完成这个消息的处理。

 

这里可能有人要问,既然同样是消息内容,都可以为基本对象格式,那么result与UserObj内容有什么区别。

我是这么理解的。直观的看UserObj内容在消息注册时由register方法给定,而result内容则是消息在投递时由notify方法给定,两者的内容来源不同,设计者根据情况需要进行不同的消息设计。

当然,在实际运用中,由于消息触发的嵌套机制,A消息收到的UserObj内容可能就是B消息的result内容,这也是有可能的。

 

不算结束的总结

零零碎碎说了这么多,想起之前总结的内容,关于Register-Notify模型一节的内容,确实还有一些不恰当的地方,这里做一个修正,希望能够与诸位不断的深入理解android Handler机制。

其实,Register-Notify的模型这么画也许更合适:


当然,这只是个诸多消息回调中比较典型的一种罢了。

最后再补一句。

在android  framework层并非所有的消息都是通过Handler回调机制来完成的。譬如跟RIL层接口的ril.java文件,尽管也用到了obtain和send方法来实现消息的产生与投递,但事实上它的收发机制是socket套接字的方式与RILD进行数据交互,所以对它的消息收发仍需要仔细研究代码才可以。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3