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

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(){@Overridepublic 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(){@Overridepublic 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;    }}
结果:

11-07 16:30:07.844: D/Thread1(13237): Thread one cnt: 1011-07 16:30:07.873: D/Thread2(13237): Thread two cnt: 1011-07 16:30:08.043: D/Thread1(13237): Thread one cnt: 911-07 16:30:08.173: D/Thread2(13237): Thread two cnt: 911-07 16:30:08.244: D/Thread1(13237): Thread one cnt: 811-07 16:30:08.443: D/Thread1(13237): Thread one cnt: 711-07 16:30:08.483: D/Thread2(13237): Thread two cnt: 811-07 16:30:08.680: D/Thread1(13237): Thread one cnt: 611-07 16:30:08.818: D/Thread2(13237): Thread two cnt: 711-07 16:30:08.887: D/Thread1(13237): Thread one cnt: 511-07 16:30:09.095: D/Thread1(13237): Thread one cnt: 411-07 16:30:09.164: D/Thread2(13237): Thread two cnt: 611-07 16:30:09.303: D/Thread1(13237): Thread one cnt: 311-07 16:30:09.528: D/Thread2(13237): Thread two cnt: 511-07 16:30:09.528: D/Thread1(13237): Thread one cnt: 211-07 16:30:09.735: D/Thread1(13237): Thread one cnt: 111-07 16:30:09.875: D/Thread2(13237): Thread two cnt: 411-07 16:30:10.217: D/Thread2(13237): Thread two cnt: 311-07 16:30:10.558: D/Thread2(13237): Thread two cnt: 211-07 16:30:10.904: D/Thread2(13237): Thread two cnt: 1
从结果我们可以看出,这两个线程的确是并行运行的。
(2)定义一个Thread

MainActivity.java

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 {@Overridepublic 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

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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}        mImageView.setImageBitmap(b);            }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.activity_main, menu);        return true;    }}

界面:

activity_main.xml

<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

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 {@Overridepublic 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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.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,都可以这样用。

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 {@Overridepublic 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)方法

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 {@Overridepublic 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


下一篇继续,这个有点长了。。。


更多相关文章

  1. Android之获取加载图片宽高问题(getIntrinsicWidth与getwidth的区
  2. Android异步处理特性之AsyncTask
  3. Android模拟用户点击的实现方法
  4. 浅谈android的selector,背景选择器
  5. Android应用开发试题(收集)
  6. Android提取系统所有的缩略图
  7. Android(安卓)HorizontalScrollView 水平滑动 在listview上面动
  8. Android(安卓)不同API版本 向后兼容
  9. android.os.NetworkOnMainThreadException

随机推荐

  1. Go语言并发机制图文详解
  2. go语言查看环境信息的方法
  3. golang context用来干吗
  4. 在go modules里使用go get进行包管理的介
  5. Go生成go动态库或静态库的方法
  6. golang channel有什么好处
  7. golang channel是什么
  8. go中的数据结构-字典map详解
  9. Golang Cgo是什么
  10. go中的数据结构-接口interface(详解)