ui线程与工作线程的通信有两种常用的方式

ui线程与工作线程的通信有两种常用的方式
1:AsyncTask(异步任务)
特点:框架成熟,按照框架要求填写代码即可。将工作线程(耗时操作)放在doinbackground方法中,在dopostexcture方法中更新ui界面
要求,理解三个泛型和四个步骤
2:Handler方式
2-1:用handler发送和处理Message,要求设计好Message消息类
2-2:用handler发送和处理Runnable对象,用handler的post方法,在工作线程中修改UI控件,虽然handler的post方法写工作线程中,但实际是在UI线程中执行的。
例子:从网络上下载一幅图片加载到手机activity的imageview上
先上效果图
第一种方式
异步任务:

package com.hnkjwlxy.ch03_ansyctask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivityone extends Activity implements View.OnClickListener {

    private Button btn_download;
    private ImageView iv_img;
    private String IMAGE_PATH="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1168991478,3075700071&fm=26&gp=0.jpg";
    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.bi);
        initView();
        progressDialog=new ProgressDialog(this);
        progressDialog.setTitle("提示信息");
        progressDialog.setMessage("正在下载,请等待");
        //没有下载完成前不允许取消对话框
        progressDialog.setCancelable(false);
        //风格为线条的形式
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    }

    private void initView() {
        btn_download = (Button) findViewById(R.id.btn_download);
        iv_img = (ImageView) findViewById(R.id.iv_img);
        btn_download.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_download:
                //启动异步任务
                new DownImageAsyncTask().execute(IMAGE_PATH);
                break;
        }
    }

    //创建下载图片的异步内部类
    /** 泛型1:代表下载的路径
     */泛型3:代表后台子线程结束后返回位图对象
     //三个参数
    //String:下载图片的地址
   //Integer:子线程的下载进度
   //Bitmap:位图对象
    class DownImageAsyncTask extends AsyncTask<String,Integer,Bitmap>{
        @Override
        /**
         * String...
         * UI线程在启动工作线程时,可以传入多个参数,
         * 此次的string参数是一个数组,是字符串数组
         */
        protected Bitmap doInBackground(String... strings) {
            Bitmap bitmap=null;
            byte[] image=new byte[]{};
            byte[] data=new byte[1024];
            //获取传入的下载路径,trim()去空格;
            try{
                String path=strings[0].trim();
                URL url=new URL(path);
                HttpURLConnection httpURLConnection=(HttpURLConnection)url.openConnection();
                //httpURLConnection.getInputStream()获取网络输入流

                //构建输入流
                InputStream inputStream=httpURLConnection.getInputStream();
                //字节数组输出流
                ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();

                //获得图片大小--输入流的大小
                int filelength=httpURLConnection.getContentLength();
                int totallength=0,length=0;//1:总共下载的大小,2:当前下载的大小
                Log.i("Tag",filelength+"filelength");
                while((length=inputStream.read(data))!=-1){
                    totallength+=length;
                    //计算下载进度
                    int progress=(int)((totallength)/(float)(filelength)*100);

                    //构建图片,将网络输入流内容写入data字节数组中
                    byteArrayOutputStream.write(data,0,length);
                    //将下载进度反馈给onprogressupdate方法
                    publishProgress(progress);
                }
                image=byteArrayOutputStream.toByteArray();
                bitmap=BitmapFactory.decodeByteArray(image,0,image.length);
                inputStream.close();
                byteArrayOutputStream.close();

                //利用网络输入流构建位图对象
              //  bitmap= BitmapFactory.decodeStream(httpURLConnection.getInputStream());
            }catch (Exception e){
                Log.i("tag",e.getMessage());
            }
            return bitmap;
        }

        @Override
       //在doinbackground方法执行前执行的方法,通常做一些准备工作,例如将progressdialog显示出来
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog.show();//显示进度对话框
        }

        //doinbackground执行完之后,该方法执行
        //该方法参数即为doinbackground方法的返回
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            iv_img.setImageBitmap(bitmap);
            //后台子线程执行完之后,更新UI
            //销毁对话框
            progressDialog.dismiss();
        }

        //异步框架向UI线程反馈后台线程的执行进度
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //参数values是数组
            progressDialog.setProgress(values[0]);
        }
    }
}

第二种方式
Handler
1:发送和处理Message
2:发送和处理runnable对象
工作线程利用handler发送message/runnable对象给消息队列,主线程用looper(消息循环器)从消息队列中取出队首消息进行处理
Message:线程之间通信的信息载体
如果线程之间的信息载体比较复杂,建议使用setData和getData传送Bundler对象
如果线程之间的信息载体比较简单,建议直接使用Message类中的arg1,arg2,obj,what. 设计Message消息类需要思考的:
工作线程有两个信息要传递给ui线程 下载进度,下载完成的位图
what表示哪一种消息
下载进度 what:1; 通过arg1传递下载进度
下载完成的位图的字节数组 what:2;setData/getData传递位图

package com.hnkjwlxy.message;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends Activity implements View.OnClickListener {

    private Button btn_bb;
    private ImageView img_img;
    private ProgressDialog pd;
    
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                //把下载进度进行更新
                case 1:
                    pd.show();
                    pd.setProgress(msg.arg1);//更新进度,进度放在message的arg1属性里面的
                    break;
             case 2:
                 //下载完成,把位图呈现在imageview控件上
                 pd.dismiss();//销毁进度对话框
                 //bundle对象可以传递字节数组
                 Bundle bundle=msg.getData();//从消息中过去数据
                 byte[] image=bundle.getByteArray("myimage");//从bundle获取key为myimage的字节数组
                 //从子数组中构建位图
                 Bitmap bitmap= BitmapFactory.decodeByteArray(image,0,image.length);
                 img_img.setImageBitmap(bitmap);
                 break;
        }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        btn_bb = (Button) findViewById(R.id.btn_bb);
        img_img = (ImageView) findViewById(R.id.img_img);

        pd=new ProgressDialog(this);
        pd.setTitle("提示信息");
        pd.setMessage("正在下载,请稍后");
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        btn_bb.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_bb:
                new DownImageTread().start();//启动工作线程
                break;
        }
    }

    //工作线程
    class DownImageTread extends Thread{
        @Override
        public void run() {
            super.run();
            String path="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1168991478,3075700071&fm=26&gp=0.jpg";
            try{
                URL url=new URL(path);
                HttpURLConnection connection=(HttpURLConnection)url.openConnection();
                InputStream inputStream=connection.getInputStream();
                //字节数组输出流,在内存中创建一个字节数组的缓存区,所有发送到输出流的数据,都保存在该缓存区
                ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
                byte[] data=new byte[1024];//字节数组
                byte[] image=new byte[]{};//字节数组对象,{}相当于构造函数

                //文件大小是通过网络连接对象
                int filesize=connection.getContentLength();
                Log.i("filesize",filesize+"");
                int length=0,totallength=0;
                while((length=inputStream.read(data))!=-1){
                    totallength+=length;
                    int prograss=(int)(totallength/(float)filesize)*100;
                    //将字节数组data中的数组放入字节数组缓存区
                    byteArrayOutputStream.write(data,0,length);
                    //Message对象不能new,只能获得
                    // 两种方法获得:
                   // 方式1:Message.obtain();
                    Message message=Message.obtain();
                    message.what=1;
                    message.arg1=prograss;
                    handler.sendMessage(message);
                   Thread.sleep(100);
                }
                image=byteArrayOutputStream.toByteArray();
                //将字节数组缓存区中的内容构建为字节数组
                Message message=Message.obtain();
                message.what=2;
                Bundle bundle=new Bundle();
                bundle.putByteArray("myimage",image);
                message.setData(bundle);
                handler.sendMessage(message);
                //关闭流
                inputStream.close();
                byteArrayOutputStream.close();
            }catch (Exception ex){
                Log.i("tag",ex.getMessage());
            }
        }
    }
}

利用runnable对象传递

package com.hnkjwlxy.message;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity1 extends Activity implements View.OnClickListener {

    private Button btn_bb;
    private ImageView img_img;
    private ProgressDialog pd;
    private Handler handler=new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        btn_bb = (Button) findViewById(R.id.btn_bb);
        img_img = (ImageView) findViewById(R.id.img_img);

        pd=new ProgressDialog(this);
        pd.setTitle("提示信息");
        pd.setMessage("正在下载,请稍后");
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        btn_bb.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_bb:
                new DownImageTread().start();//启动工作线程
                break;
        }
    }

    //工作线程
    class DownImageTread extends Thread{
        @Override
        public void run() {
            super.run();
            String path="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1168991478,3075700071&fm=26&gp=0.jpg";
            try{
                URL url=new URL(path);
                HttpURLConnection connection=(HttpURLConnection)url.openConnection();
                InputStream inputStream=connection.getInputStream();
                //字节数组输出流,在内存中创建一个字节数组的缓存区,所有发送到输出流的数据,都保存在该缓存区
                ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
               final byte[] data=new byte[1024];//字节数组
                //文件大小是通过网络连接对象
                int filesize=connection.getContentLength();
                Log.i("filesize",filesize+"");
                int length=0,totallength=0;
                while((length=inputStream.read(data))!=-1){
                    totallength+=length;
                    final int prograss=(int)(totallength/(float)filesize)*100;
                    //将字节数组data中的数组放入字节数组缓存区
                    byteArrayOutputStream.write(data,0,length);
                    //
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            pd.show();
                            pd.setProgress(prograss);
                        }
                    });
                    //Message对象不能new,只能获得
                    // 两种方法获得:
                   // 方式1:Message.obtain();
		//方式2:handler.obtainMessage()
                   Thread.sleep(100);
                }
                final byte[] image=byteArrayOutputStream.toByteArray();
                //将字节数组缓存区中的内容构建为字节数组
               handler.post(new Runnable() {
                   @Override
                   public void run() {
                       pd.dismiss();
                  Bitmap bitmap=BitmapFactory.decodeByteArray(image,0,image.length);
                   img_img.setImageBitmap(bitmap);
                   }
               });

                inputStream.close();
                byteArrayOutputStream.close();
            }catch (Exception ex){
                Log.i("tag",ex.getMessage());
            }
        }
    }
}

ANR对话框 :Application Not Response 规定如果5秒没有响应,会出现ANR对话框,会强制要求退出APP
1、耗时操作不能放在线程里(网络下载,数据库操作,文件读写)
2、非ui线程不能操作UI控件(进度条,进度对话框,图片加载)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值