Android之线程

来源:互联网 发布:微信秀是什么软件 编辑:程序博客网 时间:2024/06/06 16:41
对android的单线程模型,有两个简单的规则
1、不阻塞UI线程

2、不从UI线程之外访问ANDROID的UI工具,即不在UI线程之外更新UI

工作线程
由于上面对线程模型的规则,不阻塞UI线程,对应用的UI反应是至关重要的
如果操作不是瞬间就能完成的话,需要保证该工作运行在单独的线程中

例如下面的程序,在一个线程中下载一个图片,并且显示在ImageView中

public void onClick(View v) {    new Thread(new Runnable() {        public void run() {            Bitmap b = loadImageFromNetwork("http://example.com/image.png");            mImageView.setImageBitmap(b);        }    }).start();}

虽然上面的程序运行起来很好,并且创建了一个单独的线程来处理网络操作,但是违反了第二个原则
该例子在工作线程中修改ImageView,而不是UI线程中,可能产生未定义或者是意想不到的结果
为了弥补这个错误,ANDROID中提供了几种在线程中访问UI的方法,
下面是这些方法的列表

Activity.runOnUiThread(Runnable)View.post(Runnable)View.postDelayed(Runnable, long)


例如用View.post方法来修复上面的BUG

public void onClick(View v) {    new Thread(new Runnable() {        public void run() {            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");            mImageView.post(new Runnable() {                public void run() {                    mImageView.setImageBitmap(bitmap);                }            });        }    }).start();}

当前的实现时线程安全的,网络操作是从一个单一的线程,同时ImageView从UI线程中设置
然而,当操作的复杂性增加的时候,这种代码的变得很难维护。为了解决这种工作线程的复杂操作,或许可以考虑利用Handler来


处理UI线程发来的消息。或许最好的解决方法是来继承AsyncTask类,该类简化了工作线程需要和UI交互的任务


AsyncTask 允许在用户界面执行异步工作,她可以阻断工作线程,然后将结果发布到UI线程中,不需要自定义处理线程
使用该方法的时候,需要继承AsyncTask 并且实现doInBackground()回调方法,该方法运行在一个后台线程池中
为了更新UI,还必须实现onPostExecute()方法,该方法将doInBackground()中的结果发送到UI线程中并且运行起来。因此可以安全的更新UI。

在UI线程中运行该任务需要调用execute()方法
例如用下面的方法实现上面的例子:

public void onClick(View v) {    new DownloadImageTask().execute("http://example.com/image.png");}private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {    protected Bitmap doInBackground(String... urls) {        return loadImageFromNetwork(urls[0]);    }        protected void onPostExecute(Bitmap result) {        mImageView.setImageBitmap(result);    }}


 AsyncTask 工作的过程
1、可以利用泛型指定参数的类型,进度值和任务的最终结果
2、 doInBackground()方法在工作线程中自动的执行
3、onPreExecute(), onPostExecute(), and onProgressUpdate()都是在UI线程中被唤醒的
4、 doInBackground()中的 返回值被发送到onPostExecute()里
5、在doInBackground()中可以随时的调用publishProgress()方法来执行onProgressUpdate()方法对UI线程进行更新
6、可以在任何时候,从任意的线程中取消任务

原创粉丝点击