当前位置:  编程技术>移动开发
本页文章导读:
    ▪Activity中运用线程的例子        Activity中使用线程的例子 转自:http://blog.csdn.net/yihui823/article/details/6741411   今天看到一段很糟糕的代码。于是做了一个工程,模拟这段代码,向大家说明一下线程在使用中要注意的几点。这.........
    ▪ 深度了解原型链        深度理解原型链 摘自http://www.cnblogs.com/maorongmaomao/archive/2012/08/29/2662258.html   写在开始之前:   早就想要好好总结下javascript的基础知识了,所以从这篇文章起,我会开始总结各种js的语法.........
    ▪ 浅谈缺、信彩信的拦截       浅谈短、信彩信的拦截   关于Android平台上短、彩信的拦截,网上已经有不少介绍性的文章。那些文章大多是介绍具体的实现方法,其提供的方法并不一定能够成功拦截。今天我们就来详深.........

[1]Activity中运用线程的例子
    来源: 互联网  发布时间: 2014-02-18
Activity中使用线程的例子

转自:http://blog.csdn.net/yihui823/article/details/6741411

 

今天看到一段很糟糕的代码。于是做了一个工程,模拟这段代码,向大家说明一下线程在使用中要注意的几点。这个例子适合给新手,也欢迎各位高手来指点一下。

首先,上代码。

第一个类LoginService,这是一个模拟类,把业务剥离出去了。只是模拟登录操作而已。

 

 

[java] view plaincopy
  • package com.study;  
  • package com.study;  
  •   
  • /** 
  •  * 虚拟的一个登录服务. 
  •  * @author yihui823 
  •  */  
  • public class LoginService {  
  •   
  •     //单例  
  •     private static LoginService oneInstance = new LoginService();  
  •       
  •     /** 
  •      * 得到唯一的一个单例 
  •      * @return 唯一的一个单例 
  •      */  
  •     public static LoginService getInstance() {  
  •         return oneInstance;  
  •     }  
  •       
  •     //登录成功标记  
  •     private boolean hadLogin = false;  
  •       
  •     /** 
  •      * 模拟登录操作 
  •      * @return true:登录成功 
  •      */  
  •     public boolean login() {  
  •         try {  
  •             Thread.sleep(2000);  
  •         } catch (InterruptedException e) {  
  •         }  
  •         hadLogin = true;  
  •         return hadLogin;  
  •     }  
  •       
  •     /** 
  •      * 判断是否登录 
  •      * @return true:已经登录 
  •      */  
  •     public boolean isLogin() {  
  •         return hadLogin;  
  •     }  
  • }  

  • 第二个类就是我们的Activity了。

     

     

     

    [java] view plaincopy
  • package com.study;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  • import android.widget.Toast;  
  •   
  • /** 
  •  * 一个段不好的代码 
  •  * @author yihui823 
  •  */  
  • public class BadCodeActivity extends Activity {  
  •       
  •     //登录服务  
  •     private LoginService lService = LoginService.getInstance();  
  •       
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •   
  •         new Thread(new Runnable() {  
  •             @Override  
  •             public void run() {  
  •                 while(!lService.isLogin() ) {  
  •                     try {  
  •                         lService.login();  
  •                         Thread.sleep(1000);  
  •                     } catch (InterruptedException e) {  
  •                         e.printStackTrace();  
  •                     }  
  •                 }  
  •                 Toast.makeText(BadCodeActivity.this, "登录成功", Toast.LENGTH_LONG).show();  
  •             }  
  •         }).start();  
  •     }  
  • }  
  •  

    [java] view plaincopy
  • <span >这个例子呢,显然运行的时候会报错的。请见我的另一篇文章:<a href="http://blog.csdn.net/yihui823/article/details/6722784" target="_blank">Android画面UI中的线程约束</a>。我们在非UI线程里去控制UI界面,就必须使用Handler来发送消息。修改代码如下:</span>  
  •  

     

     

    [java] view plaincopy
  • package com.study;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  • import android.os.Handler;  
  • import android.os.Message;  
  • import android.widget.Toast;  
  •   
  • /** 
  •  * 一个段不好的代码 
  •  * @author yihui823 
  •  */  
  • public class BadCodeActivity extends Activity {  
  •       
  •     //登录服务  
  •     private LoginService lService = LoginService.getInstance();  
  •       
  •     <span >//外线程访问UI线程的Handle  
  •     private Handler mhandle = new Handler(){  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             Toast.makeText(BadCodeActivity.this, "登录成功", Toast.LENGTH_LONG).show();  
  •         }  
  •     };</span>  
  •       
  •       
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •   
  •         new Thread(new Runnable() {  
  •             @Override  
  •             public void run() {  
  •                 while(!lService.isLogin() ) {  
  •                     try {  
  •                         lService.login();  
  •                         Thread.sleep(1000);  
  •                     } catch (InterruptedException e) {  
  •                         e.printStackTrace();  
  •                     }  
  •                 }  
  •                 <span >mhandle.sendEmptyMessage(0);</span>  
  •             }  
  •         }).start();  
  •     }  
  • }  
  •  

    [java] view plaincopy
  • <p><span >红色部分代码,就是修改的地方。现在,这段代码可以运行了,而且还貌似不错,是吧。</span></p><p><span >但是,一个好的程序,不能只是应付正常情况,还要应付错误情况,是吧。如果登录总是出错怎么样呢?我们把LoginService类略微改动,如下:</span></p>  
  •  

     

     

    [java] view plaincopy
  • package com.study;  
  •   
  • import android.util.Log;  
  •   
  • /** 
  •  * 虚拟的一个登录服务. 
  •  * @author yihui823 
  •  */  
  • public class LoginService {  
  •   
  •     private static final String TAG = "LoginService";  
  •       
  •     //单例  
  •     private static LoginService oneInstance = new LoginService();  
  •       
  •     /** 
  •      * 得到唯一的一个单例 
  •      * @return 唯一的一个单例 
  •      */  
  •     public static LoginService getInstance() {  
  •         return oneInstance;  
  •     }  
  •       
  •     //登录成功标记  
  •     private boolean hadLogin = false;  
  •       
  •     /** 
  •      * 模拟登录操作 
  •      * @return true:登录成功 
  •      */  
  •     public boolean login() {  
  •         try {  
  •             Thread.sleep(2000);  
  •         } catch (InterruptedException e) {  
  •         }  
  •         Log.d(TAG, "we are login");  
  • //      hadLogin = true;  
  •           
  •         return hadLogin;  
  •     }  
  •       
  •     /** 
  •      * 判断是否登录 
  •      * @return true:已经登录 
  •      */  
  •     public boolean isLogin() {  
  •         return hadLogin;  
  •     }  
  • }  

  • 增加了Log,以便查看登录情况。模拟业务代码只改了一行,就是登录永远是失败。现在运行一下呢。停在页面上没有动静了,logcat里也不断的打出:
    we are login
    这个也不会有什么错误,对吧。但是,我们如果按“返回”键退出页面,再看看logcat呢?
    we are login的log还在不停的输出,是吗?
    我想现在大家应该知道哪里出了问题了。就是说,我们的线程启动之后,就没法停掉了。
    这里我要说一下。我一直认为,
    new Thread(new Runnable() {…}().start();
    这种代码写的非常的不好。你直接构造了一个对象,但是这个对象你没有任何的变量去指向它。这个线程被你启动之后,你已经无法再去跟踪、调用、管理了。这个线程,只能自生自灭,永远游离在你的控制范围之外。你会不会觉得,这个线程跟僵尸一样?对,这就是僵尸进程,如果它没有停止的条件,就永远在你的系统里消耗你的资源。
    所以我觉得使用线程的一个基本认识:生成的线程类,一定要有一个变量去指向它,以便在合适的时候销毁。
    这里说到销毁,这就是另一个问题了。Thread类已经废弃了stop方法了,因为线程需要自行去释放该释放的资源,不能光依赖于运行框架的控制。我们需要在Thread里面,加上他自己停止的代码。也就是说,不论如何,线程应该会自己去停止掉,而不应该是无限制的运行。
    另外,我们在Android里面,还应该注意Activity的各个状态周转。一般来说,线程的启动在onCreate里是不合适的,我们必须考虑到onResume和onPause的情况。
    那么,我们总结下,Activity里使用线程有三个注意:
    1, 线程对象一定要有变量指向它,以便我们可以控制。
    2, 线程类一定要有停止条件,以便外界通知线程自行停止。
    3, 在onResume里启动线程,在onPause里停止线程。
    我们根据以上三点,重新写一下Activity。

     

     

     

    [java] view plaincopy
  • package com.study;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  • import android.os.Handler;  
  • import android.os.Message;  
  • import android.util.Log;  
  • import android.widget.Toast;  
  •   
  • /** 
  •  * 一个段不好的代码 
  •  * @author yihui823 
  •  */  
  • public class BadCodeActivity extends Activity {  
  •   
  •     private static final String TAG = "BadCodeActivity";  
  •       
  •     //登录服务  
  •     private LoginService lService = LoginService.getInstance();  
  •       
  •     //外线程访问UI线程的Handle  
  •     private Handler mhandle = new Handler(){  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             Toast.makeText(BadCodeActivity.this, "登录成功", Toast.LENGTH_LONG).show();  
  •         }  
  •     };  
  •       
  •     //通知停止线程的标记  
  •     private boolean stopFlag = false;  
  •       
  •     //登录成功标记  
  •     private boolean loginOk = false;  
  •       
  •     /** 
  •      * 登录用的线程类 
  •      */  
  •     private class LoginThread extends Thread {  
  •           
  •         @Override  
  •         public void run() {  
  •             while(!stopFlag) {  
  •                 loginOk = lService.isLogin();  
  •                 if (loginOk) {  
  •                     break;  
  •                 }  
  •                 try {  
  •                     lService.login();  
  •                     Thread.sleep(1000);  
  •                 } catch (InterruptedException e) {  
  •                     e.printStackTrace();  
  •                 }  
  •             }  
  •             mhandle.sendEmptyMessage(0);  
  •         }  
  •           
  •         /** 
  •          * 通知线程需要停止 
  •          */  
  •         public void stopLogin() {  
  •             stopFlag = true;  
  •         }  
  •     };  
  •   
  •     //用来登录的线程  
  •     private LoginThread loginThread = new LoginThread();  
  •       
  •       
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •         Log.d(TAG, "BadCodeActivity instance is called onCreate :" + this.hashCode());  
  •     }  
  •       
  •     public void onResume() {  
  •         super.onResume();  
  •         Log.d(TAG, "BadCodeActivity instance is called onResume :" + this.hashCode());  
  •         loginThread.start();  
  •     }  
  •       
  •     public void onPause() {  
  •         super.onPause();  
  •         loginThread.stopLogin();  
  •     }  
  • }  

  • 现在,我们的线程可以在页面退出的时候正常停止了。
     
    但是这段代码还是有问题的。我们仔细看看,线程在Activity构造的时候就已经创建了,然后在程序进到前台的时候启动,退到后台的时候停止。但是线程有这么一个特性:
    一旦线程的run()函数运行结束了,这个线程就销毁了,不能再启动了。
    现在我们的程序,在退出后将不可能再次显示,所以系统会马上回收掉Activity。如果我们的页面增加一个按钮,迁移到另一个页面,那么在那个页面返回的时候,就会有异常出现。我们修改一下代码来试试。
    增加一个Activity:

     

     

    [java] view plaincopy
  • package com.study;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  •   
  • /** 
  •  * 临时页面 
  •  * @author yihui823 
  •  */  
  • public class TempActivity extends Activity {  
  •   
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •     }  
  • }  


  •  

    [java] view plaincopy
  • <pre  name="code"></pre>  
  • <p>别忘了修改AndroidManifest.xml,增加Activity的说明:</p>  
  • <p align="left">         <activity android:name=".TempActivity"<br>  
  •                   android:label="@string/app_name"/><br>  
  • </p>  
  • <p align="left">修改BadCodeActivity:</p>  
  • <p><br>  
  • </p>  
  • <pre  name="code">package com.study;  
  •   
  • import android.app.Activity;  
  • import android.content.Intent;  
  • import android.os.Bundle;  
  • import android.os.Handler;  
  • import android.os.Message;  
  • import android.util.Log;  
  • import android.view.View;  
  • import android.view.View.OnClickListener;  
  • import android.widget.Button;  
  • import android.widget.Toast;  
  •   
  • /** 
  •  * 一个段不好的代码 
  •  * @author yihui823 
  •  */  
  • public class BadCodeActivity extends Activity {  
  •   
  •     private static final String TAG = "BadCodeActivity";  
  •       
  •     //登录服务  
  •     private LoginService lService = LoginService.getInstance();  
  •       
  •     //外线程访问UI线程的Handle  
  •     private Handler mhandle = new Handler(){  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             Toast.makeText(BadCodeActivity.this, "登录成功", Toast.LENGTH_LONG).show();  
  •         }  
  •     };  
  •       
  •     //通知停止线程的标记  
  •     private boolean stopFlag = false;  
  •       
  •     //登录成功标记  
  •     private boolean loginOk = false;  
  •       
  •     /** 
  •      * 登录用的线程类 
  •      */  
  •     private class LoginThread extends Thread {  
  •           
  •         @Override  
  •         public void run() {  
  •             while(!stopFlag) {  
  •                 loginOk = lService.isLogin();  
  •                 if (loginOk) {  
  •                     break;  
  •                 }  
  •                 try {  
  •                     lService.login();  
  •                     Thread.sleep(1000);  
  •                 } catch (InterruptedException e) {  
  •                     e.printStackTrace();  
  •                 }  
  •             }  
  •             mhandle.sendEmptyMessage(0);  
  •         }  
  •           
  •         /** 
  •          * 通知线程需要停止 
  •          */  
  •         public void stopLogin() {  
  •             stopFlag = true;  
  •         }  
  •     };  
  •   
  •     //用来登录的线程  
  •     private LoginThread loginThread = new LoginThread();  
  •       
  •       
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •           
  •  <span >       Button btn = (Button)findViewById(R.id.btn);  
  •         btn.setOnClickListener(new OnClickListener() {  
  •             @Override  
  •             public void onClick(View arg0) {  
  •                 startActivity(new Intent(BadCodeActivity.this,TempActivity.class));  
  •             }  
  •         });</span>  
  •           
  •         Log.d(TAG, "BadCodeActivity instance is called onCreate :" + this.hashCode());  
  •     }  
  •       
  •     public void onResume() {  
  •         super.onResume();  
  •         Log.d(TAG, "BadCodeActivity instance is called onResume :" + this.hashCode());  
  •         loginThread.start();  
  •     }  
  •       
  •     public void onPause() {  
  •         super.onPause();  
  •         loginThread.stopLogin();  
  •     }  
  • }  
  • </pre>  
  • <p><br>  
  • </p>  
  • <p align="left"> </p>  
  • <p>其实就是加了一个按钮,做一个页面迁移。别忘了在main.xml里面加上:</p>  
  • <pre  name="code"><Button  
  •     android:id="@+id/btn"    
  •     android:layout_width="fill_parent"   
  •     android:layout_height="wrap_content"   
  •     android:text="@string/hello"  
  •     />  
  • </pre>  
  • <p><br>  
  •  </p>  
  • <p>现在我们运行程序。运行之后,点击按钮,画面闪动一下说明是切换了页面。我们偷了个懒,两个Activity共用一个layout,所以页面没有任何变化。但是没关系,我们看log,we are login已经停止输出了。这个时候,我们再按返回键,应该是切换回BadCodeActivity。这个时候系统报错:</p>  
  • <p>java.lang.IllegalThreadStateException: Thread already started.</p>  
  • <p>显然,就是说线程已经启动过了,不能再次被利用。</p>  
  • <p>我们对代码需要做一点点修改。当然,我们也顺手改掉一个BUG:在退出的时候还会报告登录成功。</p>  
  • <p>并且,我们把控制变量都放在内部类里,做到变量最小化生存空间。</p>  
  • <p>修改后如下:</p>  
  • <pre  name="code">package com.study;  
  •   
  • import android.app.Activity;  
  • import android.content.Intent;  
  • import android.os.Bundle;  
  • import android.os.Handler;  
  • import android.os.Message;  
  • import android.util.Log;  
  • import android.view.View;  
  • import android.view.View.OnClickListener;  
  • import android.widget.Button;  
  • import android.widget.Toast;  
  •   
  • /** 
  •  * 一个段不好的代码 
  •  * @author yihui823 
  •  */  
  • public class BadCodeActivity extends Activity {  
  •   
  •     private static final String TAG = "BadCodeActivity";  
  •       
  •     //登录服务  
  •     private LoginService lService = LoginService.getInstance();  
  •       
  •     //外线程访问UI线程的Handle  
  •     private Handler mhandle = new Handler(){  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             Toast.makeText(BadCodeActivity.this, "登录成功", Toast.LENGTH_LONG).show();  
  •         }  
  •     };  
  •       
  •     /** 
  •      * 登录用的线程类 
  •      */  
  •     private class LoginThread extends Thread {  
  •   
  •         //通知停止线程的标记  
  •         private boolean stopFlag = false;  
  •           
  •         //登录成功标记  
  •         private boolean loginOk = false;  
  •           
  •         @Override  
  •         public void run() {  
  •             while(!stopFlag) {  
  •                 loginOk = lService.isLogin();  
  •                 if (loginOk) {  
  •                     break;  
  •                 }  
  •                 try {  
  •                     lService.login();  
  •                     Thread.sleep(1000);  
  •                 } catch (InterruptedException e) {  
  •                     e.printStackTrace();  
  •                 }  
  •             }  
  •             if (loginOk) {  
  •                 mhandle.sendEmptyMessage(0);  
  •             }  
  •         }  
  •           
  •         /** 
  •          * 通知线程需要停止 
  •          */  
  •         public void stopLogin() {  
  •             stopFlag = true;  
  •         }  
  •     };  
  •   
  •     //用来登录的线程  
  •     private LoginThread loginThread;  
  •       
  •       
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •           
  •         Button btn = (Button)findViewById(R.id.btn);  
  •         btn.setOnClickListener(new OnClickListener() {  
  •             @Override  
  •             public void onClick(View arg0) {  
  •                 startActivity(new Intent(BadCodeActivity.this,TempActivity.class));  
  •             }  
  •         });  
  •           
  •         Log.d(TAG, "BadCodeActivity instance is called onCreate :" + this.hashCode());  
  •     }  
  •       
  •     public void onResume() {  
  •         super.onResume();  
  •         Log.d(TAG, "BadCodeActivity instance is called onResume :" + this.hashCode());  
  •         <span >loginThread = new LoginThread();</span>  
  •         loginThread.start();  
  •     }  
  •       
  •     public void onPause() {  
  •         super.onPause();  
  •         loginThread.stopLogin();  
  •     }  
  • }  
  •   
  • </pre>  
  • <p align="left"><br>  
  •  </p>  
  • <p>现在,我们点击按钮,进入到TempActivity的时候,登录log停止输出;然后按返回键,回到BadCodeActivity的时候,登录log又继续输出。程序基本完成,没有僵尸线程存在了。红色的那行代码是关键!</p>  
  • <p>我们总结一下:</p>  
  • <p><strong>1, 线程对象一定要有变量指向它,以便我们可以控制。</strong></p>  
  • <p><strong>2, 线程类一定要有停止条件,以便外界通知线程自行停止。</strong></p>  
  • <p><strong>3, 线程启动之后,不管是不是已经停止了,都是不能再次利用的。</strong></p>  
  • <p>4,  <strong>在onResume里新建和启动线程,在onPause里停止线程。</strong></p>  
  • <p> </p>  
  • <p> </p>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  

  •     
    [2] 深度了解原型链
        来源: 互联网  发布时间: 2014-02-18
    深度理解原型链

    摘自http://www.cnblogs.com/maorongmaomao/archive/2012/08/29/2662258.html

     

    写在开始之前:

      早就想要好好总结下javascript的基础知识了,所以从这篇文章起,我会开始总结各种js的语法知识,作为一名以js开发为生计的前端工 程师,深深的着迷于js的语言魅力,而js最吸引人最强大的地方,便在于他独特的语法,能深刻的理解js的语法,是作为一个前端工程师的基本素质,在这 里,笔者在总结的同时,也希望前端朋友们给予自己的补充和见解。那么就让我们从js最最独特的语法,闭包,原型,词法作用域开始,接下来,笔者也会讨论 this,正则,浏览器的能力检测,事件代理等细节问题,以及html5,css3等前沿领域,今天我先试着总结下原型链相关的知识。笔者的经验和知识也 许会有很多不足之处,欢迎大家的更正与建议。

     

    1.首先要知道的:

      什么是原型链呢?

      我们首先来说说继承,继承是面向对象语言的重要机制,通俗地讲就是子类可以拥有父类的方法和属性,js的原型链实际上也是一种继承,在ECMAScript标准中,只支持实现继承,而其实现实现继承就是主要依靠于原型链实现的。

      那么,我们再来说说原型,原型其实就是上述所说的继承中的父类。

      这样,原型链 显而易见的 可以理解为,利用原型串起一个继承链,让一个引用类型继承另一个引用类型的属性和方法,再以此类推下去。

      构造函数,原型,与实例的关系:

      这三者的关系用一句话概括为,每个构造函数都有一个原型,当new 一个构造函数的时候就会生成一个原型链上携带该构造函数的原型的实例。

    2.原型链的生成过程:  

      上面基本了解了原型链的相关知识,那么原型链的生成过程是什么呢?

    1 function parent(){
      this.parent = "world";
    2 }
    3 parent.prototype = {
    4    a : function(){
    5    },
    6    b : "hello"
    7 }
    8  var child = new parent()

       而child就是parent的一个实例,在执行构造函数的时候,js引擎创建一个空白对象,把__proto__指向parent的 prototype,然后把这个对象作为this调用parent进行初始化,这样一个简单的原型链就形成了 即 child --> parent.prototye -->Object.prototype。

        prototype,constructor,__proto__ : 

      上面多次提到这几个属性,在原型链的概念中,如果能理解这几个属性的关系,那么离胜利就不远了。下面我们逐一的谈谈这几个属性:

      1.prototype

      prototype是构造函数的属性,指的就是构造函数的原型,在生成实例的时候,js会根据构造函数的prototype属性将该属性下的对象生成为父类,

         注意,只有构造函数这个属性才有这种效果哦~如果一个构造函数没有指定该属性,那么该属性下的__proto__会默认的指向原生Object的原型对象,该属性会变成一个对象,其中constructor属性指向本身。

      2.constructor

         constructor,如果通俗的理解,可以理解成原型对象的构造函数,当把一个对象(对象字面量)赋给一个构造函数的原型,constructor 会被复写,如果没有进行prototype的操作的话,constructor是函数声明时指定的,指定为本身:

      例如:

      function A() {}
      则 A.prototype.constructor === A;

    但是这个属性往往是不准确的:

    1 function A() {}
    2 function B() {}
    3 B.prototype = new A();
    4 var b = new B();
    5 b.constructor; // A

      上面的代码,按照constructor的含义,b的constructor应该指向B,但是确指向了A,原因如下

        A没有进行prototype操作,所以其constructor指向本身;
      B.prototype = new A();之后B.prototype被复写为A的实例,
      则B.prototype.constructor === A;
      而b是B的实例则b.constructor === A;
     
      所以constructor这个属性是不准确的,不推荐大家关注与使用。
      

      如果想要实现继承,一般要进行constructor修复,即:
      B.prototype = new A();
      B.prototype.constructor = B;

      3.__proto__
      可以这么说,js的原型链就是通过这个属性串联起来的,__proto__属性指向他的父类,在调用一个对象的属性或者方法的时候就是通过__proto__这一属性指向的对象一层一层的向上查找的。上面的一句:在生成实例的时候,js会根据构造函数的prototype属性将该属性下的对象生成为父类,在这里可以改为,在生成实例的时候,js会根据构造函数的prototype属性将该属性下的对象引用到实例的__proto__属性下。

         

     1 function parent(){
     2     this.a = "world";
     3     this.b = "world";
     4 }
     5 parent.prototype = {
     6    a : "aaa",
     7    b : "bbb",
     8    c : "!" 
     9 }
    10 function temp(){
    11    this.a = "hello";
    12 }
    13 temp.prototype = new parent();
    14 var child = new temp();
    15 console.log(child.a +" " + child.b+child.c);//hello world!

      上面的代码运行结果就为 : “hello world!”生成的原型链即是

      child(temp的实例) > __proto__ > temp.prototype(parent的实例) > __proto__  >parent.prototype > __proto__ > Object.prototype >__proto__ > null

    3.原型链的调用

      如上所示,原型链由__proto__属性串联而成,经过上面的分析,调用的理解就变得很简单了,比如上例的原型链中,当调用child.c属性时,那么程序会按如下方式运行:

      在child本层查找c,查询未果,会通过__proto__属性向上查找temp.prototype,查找未果,继续沿着 __proto__向上查找parent.prototype,oyeah~终于找到了~所以child.c在这里就会是 parent.prototype.c了~

      怎么样,简单吧^ ^

     

    最后的最后,呈上一个常用函数给大家:

      

     1 function A() {
     2      // do something here
     3 }
     4 A.prototype = {
     5      a : 'aaa',
     6      b : function() {
     7      }
     8 };
     9  function B() {
    10 }
    11 extend(B, A);
    12 function extend(child, parent) {
    13      function temp() {
    14             this.constructor = child;
    15     }
    16      temp.prototype = parent.prototype;
    17      child.prototype = new temp();
    18 }

      extend函数 两个参数都为构造函数,目的是让一个构造函数(子类)继承另一个构造函数(父类)的原型,并且不调用父类的构造函数(有时候构造函数会需要一些参数或者做一些事情破坏了原型链),这个方法可以用来生成想要的原型链哦。


        
    [3] 浅谈缺、信彩信的拦截
        来源: 互联网  发布时间: 2014-02-18
    浅谈短、信彩信的拦截
     

    关于Android平台上短、彩信的拦截,网上已经有不少介绍性的文章。那些文章大多是介绍具体的实现方法,其提供的方法并不一定能够成功拦截。今天我们就来详深入地介绍一下拦截短、彩信的内部原理,并分析一下拦截方法的优劣。

    Android接收短、彩信的原理

    正常的短信在到达手机后,会根据不同的制式(GSM、CDMA等)被解析并封装成SmsMessage对象。该对象会被SMSDispatcher进一步解析并分发。系统会将短信的“format”、“pdu”放到action为“android.provider.Telephony.SMS_RECEIVED”的Intent中。之后系统会将Intent以有序广播(Orderd Broadcast)的形式发出去。监听这两个广播的app收到广播后,通过对pdu的解析,就可以得到短信的具体内容。

    彩信的情况与短信类似,只不过运营商首先会发一条WapPush短信。这类短信不包含彩信的具体内容,而是包含一条指向真实内容的URL地址。系统会将WapPush短信解析,提取“pduType”、“header”、“pdu”、“format”等信息放到action为“android.provider.Telephony.WAP_PUSH_RECEIVED”的Intent中。同样,系统会以有序广播的形式将Intent发出去。收到广播的app将intent解析,并提取其中的URL。之后访问该URL地址并下载实际的彩信内容。

    有序广播的原理

    经过以上的分析,拦截短、彩信的关键就是拦截action为“android.provider.Telephony.SMS_RECEIVED”和“android.provider.Telephony.WAP_PUSH_RECEIVED”的广播。由于该广播是有序广播,所有Receiver 是按照顺序接受广播的。先收到广播的Receiver有权利终止该广播的传播。因此只要一个Receiver能够第一个收到广播并终止继续传播,那么就可以实现短、彩信的拦截。

    这里简单介绍一下有序广播的传播方式。BroadcastReceiver 有静态和动态两种方式注册。

    1.      静态注册:

    静态注册是指在AndroidManifest.xml 中注册。方法如下:

     

     <receiver android:name=“.XXXMessageReceiver”>

                <intent-filter android:priority=“1000”>

                    <action android:name=“android.provider.Telephony.SMS_RECEIVED” />

                </intent-filter>

            </receiver>

     

    2.      动态注册:

         动态注册是通过调用Context类的register方法来注册。方法如下:

     

         registerReceiver(BroadcastReceiver receiver,

                                                IntentFilter filter);

         registerReceiver(BroadcastReceiver receiver,

                                                IntentFilter filter,

                                                String broadcastPermission,

                                                Handler scheduler);

     

    注意,动态注册Receiver 的优先级是通过IntentFilter.setPriority(int)方法来设置的。当一个广播发生时,系统会将静态和动态的Receiver 按优先级(priority)进行排序,优先级越高越早处理。对于优先级相同的Receiver ,先处理动态的。

    第三方

    网上的通常是采用静态注册的方式注册BroadcastReceiver ,并设置一个较高的优先级,例如,1000、9999等。经过以上对于广播原理的分析,可以看出,这种方式其实并不能够保证接受者会第一时间被触发。比较好的实现方法需要注意两点:

    1.      采用动态方式而非静态方式注册。监听系统开机广播,系统启动之后采用动态方式注册BroadcastReceiver 。这样可以保证在第一时间将需要的BroadcastReceiver注册成功;

    2.      并将优先级设为最高。注意,系统的最高优先级不是网上所说的1000、9999,而是2147483647。这是int类型能够表示的最大数值。

    做到这两点可以大大增加拦截的成功率。由于第三方app本身的局限性,即使采用优化过的方法,第三方app还是不能够保证拦截的成功率。例如,如果有两个app都采用动态注册的方式,都设置其优先级为最高。那么其中一个就会被另一个拦截。

    系统级拦截方案

    拦截短、彩信的根本方法还是需要在系统层面来解决。需要在系统提供一个专用的Service(类似于ActivityManagerService、PackageManagerService),用于判断收到的短信是否需要拦截。接口如下:

     

    boolean needToBlockMsg(Intent intent);

     

    系统在收到短信后,将短信内容组装到需要广播的Intent中。然后调用该接口判断是否需要拦截。如果需要拦截,则抛弃该短信,或者将其保存到特定的数据库中;如果不需要拦截,那么就照常发送广播。这样可以一劳永逸地解决短、彩信的拦截问题。

    由于需要修改“/system/framework/framework.jar”之类的系统文件,第三方app是无法实现的,因此需要设备生产厂商的支持。

     

    更多内容请关注http://blog.sina.com.cn/u/3194858670以及sina微博@安卓安全小分队


        
    最新技术文章:
    ▪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