Android 建立线程 Thread详细使用方法

转载,感谢你原作者

注:建立线程很好学习的教材,本人还是建立采用第二种方法, 继承Thread类的方法,这样可以面向对象的方法,使用和灵活性更好

1.创建Android线程

参考官方文档是个好习惯。

http://developer.android.com/reference/java/lang/Thread.html

http://developer.android.com/guide/components/processes-and-threads.html

创建线程有两种方式:一是在创建线程的时候传入一个Runnable对象,另一种是继承Thread类,实现run()方法。这两种方法没啥区别嘛。。。

Game start....

(1)用Runnable对象

源码MainActivity.java

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.util.Log;  
  6. import android.view.Menu;  
  7.   
  8. public class MainActivity extends Activity {  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.activity_main);  
  14.           
  15.         /** 
  16.          * 线程1 
  17.          */  
  18.         new Thread(new Runnable(){  
  19.             @Override  
  20.             public void run() {  
  21.                 int cnt = 10;  
  22.                 while(cnt>0) {  
  23.                     Log.d("Thread1""Thread one cnt: " + cnt--);  
  24.                     try {  
  25.                         Thread.sleep(200);  
  26.                     } catch (InterruptedException e) {  
  27.                         e.printStackTrace();  
  28.                         break;  
  29.                     }  
  30.                 }  
  31.             }  
  32.         }).start();  
  33.           
  34.         /** 
  35.          * 线程2 
  36.          */  
  37.         new Thread(new Runnable(){  
  38.             @Override  
  39.             public void run() {  
  40.                 int cnt = 10;  
  41.                 while(cnt>0) {  
  42.                     Log.d("Thread2""Thread two cnt: " + cnt--);  
  43.                     try {  
  44.                         Thread.sleep(300);  
  45.                     } catch (InterruptedException e) {  
  46.                         e.printStackTrace();  
  47.                         break;  
  48.                     }  
  49.                 }  
  50.             }  
  51.         }).start();  
  52.     }  
  53.   
  54.     @Override  
  55.     public boolean onCreateOptionsMenu(Menu menu) {  
  56.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  57.         return true;  
  58.     }  
  59. }  
结果:

[java]  view plain copy
  1. 11-07 16:30:07.844: D/Thread1(13237): Thread one cnt: 10  
  2. 11-07 16:30:07.873: D/Thread2(13237): Thread two cnt: 10  
  3. 11-07 16:30:08.043: D/Thread1(13237): Thread one cnt: 9  
  4. 11-07 16:30:08.173: D/Thread2(13237): Thread two cnt: 9  
  5. 11-07 16:30:08.244: D/Thread1(13237): Thread one cnt: 8  
  6. 11-07 16:30:08.443: D/Thread1(13237): Thread one cnt: 7  
  7. 11-07 16:30:08.483: D/Thread2(13237): Thread two cnt: 8  
  8. 11-07 16:30:08.680: D/Thread1(13237): Thread one cnt: 6  
  9. 11-07 16:30:08.818: D/Thread2(13237): Thread two cnt: 7  
  10. 11-07 16:30:08.887: D/Thread1(13237): Thread one cnt: 5  
  11. 11-07 16:30:09.095: D/Thread1(13237): Thread one cnt: 4  
  12. 11-07 16:30:09.164: D/Thread2(13237): Thread two cnt: 6  
  13. 11-07 16:30:09.303: D/Thread1(13237): Thread one cnt: 3  
  14. 11-07 16:30:09.528: D/Thread2(13237): Thread two cnt: 5  
  15. 11-07 16:30:09.528: D/Thread1(13237): Thread one cnt: 2  
  16. 11-07 16:30:09.735: D/Thread1(13237): Thread one cnt: 1  
  17. 11-07 16:30:09.875: D/Thread2(13237): Thread two cnt: 4  
  18. 11-07 16:30:10.217: D/Thread2(13237): Thread two cnt: 3  
  19. 11-07 16:30:10.558: D/Thread2(13237): Thread two cnt: 2  
  20. 11-07 16:30:10.904: D/Thread2(13237): Thread two cnt: 1  
从结果我们可以看出,这两个线程的确是并行运行的。
(2)定义一个Thread

MainActivity.java

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.util.Log;  
  6. import android.view.Menu;  
  7.   
  8. public class MainActivity extends Activity {  
  9.   
  10.     /** 
  11.      *定义一个简单的线程SimpleThread 
  12.      */  
  13.     public class SimpleThread extends Thread {  
  14.         @Override  
  15.         public void run() {  
  16.             int cnt = 10;  
  17.             while(cnt>0) {  
  18.                 Log.d("Thread""Thread cnt: " + cnt--);  
  19.                 try {  
  20.                     Thread.sleep(200);  
  21.                 } catch (InterruptedException e) {  
  22.                     e.printStackTrace();  
  23.                     break;  
  24.                 }  
  25.             }  
  26.         }  
  27.           
  28.     }  
  29.       
  30.     @Override  
  31.     public void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.           
  35.         SimpleThread thread1 = new SimpleThread();  
  36.         SimpleThread thread2 = new SimpleThread();  
  37.         thread1.start();  
  38.         thread2.start();  
  39.           
  40.     }  
  41.   
  42.     @Override  
  43.     public boolean onCreateOptionsMenu(Menu menu) {  
  44.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  45.         return true;  
  46.     }  
  47. }  
运行结果,突然发现截图比较不错:
Android 建立线程 Thread详细使用方法_第1张图片

可以看到是有两个线程14912和14913都在运行。

接下来,我们需要了解一下,为什么需要线程。


2.线程啊线程

Android中有一个UI线程,这个线程专门负责用户可以看到的和接触到的内容,比如图片啊,Button等。Google为了提高界面的流畅度和体验,禁止阻塞UI线程。什么意思呢,比如我要在界面上显示一张图片,而这张图片是从网络上下载下来的。

源码:

MainActivity.java

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.MalformedURLException;  
  5. import java.net.URL;  
  6.   
  7. import android.os.Bundle;  
  8. import android.app.Activity;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.BitmapFactory;  
  11. import android.view.Menu;  
  12. import android.widget.ImageView;  
  13.   
  14. public class MainActivity extends Activity {  
  15.       
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.           
  21.         ImageView mImageView = (ImageView)findViewById(R.id.imageView1);  
  22.           
  23.         Bitmap b = null;  
  24.         try {  
  25.             b = BitmapFactory.decodeStream(new URL("http://www.baidu.com/img/baidu_sylogo1.gif").openConnection()  
  26.                     .getInputStream());  
  27.         } catch (MalformedURLException e) {  
  28.             // TODO Auto-generated catch block  
  29.             e.printStackTrace();  
  30.         } catch (IOException e) {  
  31.             // TODO Auto-generated catch block  
  32.             e.printStackTrace();  
  33.         }  
  34.         mImageView.setImageBitmap(b);  
  35.           
  36.     }  
  37.   
  38.     @Override  
  39.     public boolean onCreateOptionsMenu(Menu menu) {  
  40.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  41.         return true;  
  42.     }  
  43. }  

界面:

activity_main.xml

[html]  view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent" >  
  5.   
  6.     <TextView  
  7.         android:id="@+id/textView1"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_centerHorizontal="true"  
  11.         android:layout_centerVertical="true"  
  12.         android:text="@string/hello_world"  
  13.         tools:context=".MainActivity" />  
  14.   
  15.     <ImageView  
  16.         android:id="@+id/imageView1"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_above="@+id/textView1"  
  20.         android:layout_centerHorizontal="true"  
  21.         android:layout_marginBottom="90dp" />  
  22.   
  23. </RelativeLayout>  
需要的权限:<uses-permission android:name="android.permission.INTERNET"/>

我们希望的结果是:

Android 建立线程 Thread详细使用方法_第2张图片

在Android2.1上面,这段代码是可以运行的,但是在4.xx的模拟器上(我现在机器启动不了4.XX的模拟器,正在想办法解决。。。),因为下载图片是网络交互,会Block阻塞住UI界面,如果这个图片很大或者网络不给力,这个下载需要好几分钟,那么在图片下载完成前,你是做不了任何事情的。你会用这样一个会几分钟不动弹的程序吗?No,估计几秒钟我都等不了了,直接结束掉。。。所以线程的用武之地到了。。。

现在我们就需要把图片的下载放到线程里面去:

MainActivity.java

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.MalformedURLException;  
  5. import java.net.URL;  
  6.   
  7. import android.os.Bundle;  
  8. import android.app.Activity;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.BitmapFactory;  
  11. import android.view.Menu;  
  12. import android.widget.ImageView;  
  13.   
  14. public class MainActivity extends Activity {  
  15.       
  16.     private ImageView mImageView;  
  17.       
  18.     public class ImageDownloadThread extends Thread {  
  19.         @Override  
  20.         public void run() {  
  21.             Bitmap b = null;  
  22.             try {  
  23.                 b = BitmapFactory.decodeStream(  
  24.                         new URL("http://www.baidu.com/img/baidu_sylogo1.gif").  
  25.                         openConnection().getInputStream());  
  26.             } catch (MalformedURLException e) {  
  27.                 // TODO Auto-generated catch block  
  28.                 e.printStackTrace();  
  29.             } catch (IOException e) {  
  30.                 // TODO Auto-generated catch block  
  31.                 e.printStackTrace();  
  32.             }  
  33.             mImageView.setImageBitmap(b);  
  34.         }  
  35.     }  
  36.       
  37.     @Override  
  38.     public void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.activity_main);  
  41.           
  42.         mImageView = (ImageView)findViewById(R.id.imageView1);  
  43.           
  44.         ImageDownloadThread thread = new ImageDownloadThread();  
  45.         thread.start();  
  46.           
  47.     }  
  48.   
  49.     @Override  
  50.     public boolean onCreateOptionsMenu(Menu menu) {  
  51.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  52.         return true;  
  53.     }  
  54. }  

运行结果:

报错:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

在Android里,只有UI线程可以操作界面。用GOOGLE的话说,用其他线程操作界面会造成不可预测的后果。用我们的话说,用其他线程操作UI会报错。。。

所以我们应该将下载图片放在线程里面,把设置图片在UI线程(可以叫主线程吧?)里面完成。

如何在主线程更新UI?Android给我们提供了至少3中方法:

1)View.post(Runnable) 方法

View是什么呢?不需要解释了吧,一个按钮,它的类不是叫ButtonView么,List的叫ListView,都可以这样用。

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.MalformedURLException;  
  5. import java.net.URL;  
  6.   
  7. import android.os.Bundle;  
  8. import android.app.Activity;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.BitmapFactory;  
  11. import android.view.Menu;  
  12. import android.widget.ImageView;  
  13.   
  14. public class MainActivity extends Activity {  
  15.       
  16.     private ImageView mImageView;  
  17.       
  18.     public class ImageDownloadThread extends Thread {  
  19.         @Override  
  20.         public void run() {  
  21.             try {  
  22.                 final Bitmap b = BitmapFactory.decodeStream(  
  23.                         new URL("http://www.baidu.com/img/baidu_sylogo1.gif").  
  24.                         openConnection().getInputStream());  
  25.                   
  26.                 mImageView.post(new Runnable() {  
  27.                     public void run() {  
  28.                         mImageView.setImageBitmap(b);  
  29.                     }  
  30.                 });  
  31.             } catch (Exception e) {  
  32.                 return//报错了直接结束,可能的原因,网络啊,url地址等。  
  33.             }  
  34.         }  
  35.     }  
  36.       
  37.     @Override  
  38.     public void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.activity_main);  
  41.           
  42.         mImageView = (ImageView)findViewById(R.id.imageView1);  
  43.           
  44.         ImageDownloadThread thread = new ImageDownloadThread();  
  45.         thread.start();  
  46.           
  47.     }  
  48.   
  49.     @Override  
  50.     public boolean onCreateOptionsMenu(Menu menu) {  
  51.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  52.         return true;  
  53.     }  
  54. }  
结果:图片显示正确。

2)Activity.runOnUiThread(Runnable)方法

[java]  view plain copy
  1. package com.example.siqi;  
  2.   
  3. import java.net.URL;  
  4.   
  5. import android.os.Bundle;  
  6. import android.app.Activity;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.BitmapFactory;  
  9. import android.view.Menu;  
  10. import android.widget.ImageView;  
  11.   
  12. public class MainActivity extends Activity {  
  13.       
  14.     private ImageView mImageView;  
  15.       
  16.     //定义一个线程  
  17.     public class ImageDownloadThread extends Thread {  
  18.         @Override  
  19.         public void run() {  
  20.             try {  
  21.                 final Bitmap b = BitmapFactory.decodeStream(  
  22.                         new URL("http://www.baidu.com/img/baidu_sylogo1.gif").  
  23.                         openConnection().getInputStream());  
  24.                   
  25.                 MainActivity.this.runOnUiThread(new Runnable() {  
  26.                     public void run() {  
  27.                         mImageView.setImageBitmap(b);  
  28.                     }  
  29.                 });  
  30.             } catch (Exception e) {  
  31.                 return//报错了直接结束,可能的原因,网络啊,url地址等。  
  32.             }  
  33.         }  
  34.     }  
  35.       
  36.     @Override  
  37.     public void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.         setContentView(R.layout.activity_main);  
  40.           
  41.         mImageView = (ImageView)findViewById(R.id.imageView1);  
  42.           
  43.         //实例化一个线程并运行  
  44.         ImageDownloadThread thread = new ImageDownloadThread();  
  45.         thread.start();  
  46.           
  47.     }  
  48.   
  49.     @Override  
  50.     public boolean onCreateOptionsMenu(Menu menu) {  
  51.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  52.         return true;  
  53.     }  
  54. }  
感觉不错哦,可以用在很多地方。

3)View.postDelayed(Runnable,long)

这个跟View.post没多大区别哈,自己参考文档去,后面那个参数是延迟的时间,在这个时间之后才更新UI

你可能感兴趣的:(Android 建立线程 Thread详细使用方法)