您的位置:首页 > 移动开发 > Android开发

Android Tthread 建立线程使用方法

2014-11-04 14:36 405 查看


感谢原作者的教材

注:本人推荐使用第二个方法建立线程,继承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
plaincopy

package com.example.siqi;

import android.os.Bundle;

import android.app.Activity;

import android.util.Log;

import android.view.Menu;

public class MainActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

/**

* 线程1

*/

new Thread(new Runnable(){

@Override

public void run() {

int cnt = 10;

while(cnt>0) {

Log.d("Thread1", "Thread one cnt: " + cnt--);

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

break;

}

}

}

}).start();

/**

* 线程2

*/

new Thread(new Runnable(){

@Override

public void run() {

int cnt = 10;

while(cnt>0) {

Log.d("Thread2", "Thread two cnt: " + cnt--);

try {

Thread.sleep(300);

} catch (InterruptedException e) {

e.printStackTrace();

break;

}

}

}

}).start();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

结果:

[java] view
plaincopy

11-07 16:30:07.844: D/Thread1(13237): Thread one cnt: 10

11-07 16:30:07.873: D/Thread2(13237): Thread two cnt: 10

11-07 16:30:08.043: D/Thread1(13237): Thread one cnt: 9

11-07 16:30:08.173: D/Thread2(13237): Thread two cnt: 9

11-07 16:30:08.244: D/Thread1(13237): Thread one cnt: 8

11-07 16:30:08.443: D/Thread1(13237): Thread one cnt: 7

11-07 16:30:08.483: D/Thread2(13237): Thread two cnt: 8

11-07 16:30:08.680: D/Thread1(13237): Thread one cnt: 6

11-07 16:30:08.818: D/Thread2(13237): Thread two cnt: 7

11-07 16:30:08.887: D/Thread1(13237): Thread one cnt: 5

11-07 16:30:09.095: D/Thread1(13237): Thread one cnt: 4

11-07 16:30:09.164: D/Thread2(13237): Thread two cnt: 6

11-07 16:30:09.303: D/Thread1(13237): Thread one cnt: 3

11-07 16:30:09.528: D/Thread2(13237): Thread two cnt: 5

11-07 16:30:09.528: D/Thread1(13237): Thread one cnt: 2

11-07 16:30:09.735: D/Thread1(13237): Thread one cnt: 1

11-07 16:30:09.875: D/Thread2(13237): Thread two cnt: 4

11-07 16:30:10.217: D/Thread2(13237): Thread two cnt: 3

11-07 16:30:10.558: D/Thread2(13237): Thread two cnt: 2

11-07 16:30:10.904: D/Thread2(13237): Thread two cnt: 1

从结果我们可以看出,这两个线程的确是并行运行的。

(2)定义一个Thread

MainActivity.java

[java] view
plaincopy

package com.example.siqi;

import android.os.Bundle;

import android.app.Activity;

import android.util.Log;

import android.view.Menu;

public class MainActivity extends Activity {

/**

*定义一个简单的线程SimpleThread

*/

public class SimpleThread extends Thread {

@Override

public void run() {

int cnt = 10;

while(cnt>0) {

Log.d("Thread", "Thread cnt: " + cnt--);

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

break;

}

}

}

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

SimpleThread thread1 = new SimpleThread();

SimpleThread thread2 = new SimpleThread();

thread1.start();

thread2.start();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

运行结果,突然发现截图比较不错:



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

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


2.线程啊线程

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

源码:

MainActivity.java

[java] view
plaincopy

package com.example.siqi;

import java.io.IOException;

import java.net.MalformedURLException;

import java.net.URL;

import android.os.Bundle;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.Menu;

import android.widget.ImageView;

public class MainActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ImageView mImageView = (ImageView)findViewById(R.id.imageView1);

Bitmap b = null;

try {

b = BitmapFactory.decodeStream(new URL("http://www.baidu.com/img/baidu_sylogo1.gif").openConnection()

.getInputStream());

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

mImageView.setImageBitmap(b);

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

界面:

activity_main.xml

[html] view
plaincopy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<TextView

android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:text="@string/hello_world"

tools:context=".MainActivity" />

<ImageView

android:id="@+id/imageView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_above="@+id/textView1"

android:layout_centerHorizontal="true"

android:layout_marginBottom="90dp" />

</RelativeLayout>

需要的权限:<uses-permission android:name="android.permission.INTERNET"/>

我们希望的结果是:



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

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

MainActivity.java

[java] view
plaincopy

package com.example.siqi;

import java.io.IOException;

import java.net.MalformedURLException;

import java.net.URL;

import android.os.Bundle;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.Menu;

import android.widget.ImageView;

public class MainActivity extends Activity {

private ImageView mImageView;

public class ImageDownloadThread extends Thread {

@Override

public void run() {

Bitmap b = null;

try {

b = BitmapFactory.decodeStream(

new URL("http://www.baidu.com/img/baidu_sylogo1.gif").

openConnection().getInputStream());

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

mImageView.setImageBitmap(b);

}

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mImageView = (ImageView)findViewById(R.id.imageView1);

ImageDownloadThread thread = new ImageDownloadThread();

thread.start();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

运行结果:

报错: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
plaincopy

package com.example.siqi;

import java.io.IOException;

import java.net.MalformedURLException;

import java.net.URL;

import android.os.Bundle;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.Menu;

import android.widget.ImageView;

public class MainActivity extends Activity {

private ImageView mImageView;

public class ImageDownloadThread extends Thread {

@Override

public void run() {

try {

final Bitmap b = BitmapFactory.decodeStream(

new URL("http://www.baidu.com/img/baidu_sylogo1.gif").

openConnection().getInputStream());

mImageView.post(new Runnable() {

public void run() {

mImageView.setImageBitmap(b);

}

});

} catch (Exception e) {

return; //报错了直接结束,可能的原因,网络啊,url地址等。

}

}

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mImageView = (ImageView)findViewById(R.id.imageView1);

ImageDownloadThread thread = new ImageDownloadThread();

thread.start();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

结果:图片显示正确。

2)
Activity.runOnUiThread(Runnable)
方法

[java] view
plaincopy

package com.example.siqi;

import java.net.URL;

import android.os.Bundle;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.Menu;

import android.widget.ImageView;

public class MainActivity extends Activity {

private ImageView mImageView;

//定义一个线程

public class ImageDownloadThread extends Thread {

@Override

public void run() {

try {

final Bitmap b = BitmapFactory.decodeStream(

new URL("http://www.baidu.com/img/baidu_sylogo1.gif").

openConnection().getInputStream());

MainActivity.this.runOnUiThread(new Runnable() {

public void run() {

mImageView.setImageBitmap(b);

}

});

} catch (Exception e) {

return; //报错了直接结束,可能的原因,网络啊,url地址等。

}

}

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mImageView = (ImageView)findViewById(R.id.imageView1);

//实例化一个线程并运行

ImageDownloadThread thread = new ImageDownloadThread();

thread.start();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

感觉不错哦,可以用在很多地方。

3)
View.postDelayed(Runnable,long)


这个跟View.post没多大区别哈,自己参考文档去,后面那个参数是延迟的时间,在这个时间之后才更新UI
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐