Android Handler多线程技术 个人心得

来源:互联网 发布:淘宝日本直邮可信吗 编辑:程序博客网 时间:2024/06/06 21:47

这里有一篇详细介绍的文章:http://www.111cn.net/sj/android/95458.htm
在进行解析URL往app中加载图片时,我首先引发了android.os.NetworkOnMainException的异常,原因在于在主线程中进行了网络请求的操作(真的是太菜了~),一般来说这种操作会导致UI线程堵塞,从而引起极差的用户体验,所以一般都是在子线程中异步加载。然而还有一个坑是,若要加载图片,必定会引发修改UI的操作(ImageView),但我们又知道更新UI的操作必须在UI线程或者说主线程中进行,所以综合下来我们考虑Handler通信的方式(其实AsyncTask也一样)来完成这个功能。

那么这里我们需要利用Handler同时完成主线程子线程的信息互换:主线程要把从EditText输入的URL的String发送给子线程去网络请求,子线程处理之后要把相应的bitmap传回给主线程来更新UI。主线程给子线程传递信息很简单,因为自身有默认的MessageQueue,无需调用Looper.prepare()以及Looper.loop()方法来维护MessageQueue,自动轮询。所以,在主线程中初始化的Handler就直接通过子线程发送过来的Message的what,通过switch-case判断来完成对应的功能。那么在子线程中,需要相应的操作来完成消息队列的轮询,并且在自己的线程中初始化自己的handler,同时Looper.prepare()才能把这个Handler同自己绑定,以实现传输信息的作用。

那么由于是个人心得,Handler内部机制就不多说啦,直接上代码配合注释希望能让你看懂!

public class MainActivity extends AppCompatActivity {    private EditText editText;    private Button preview_btn;    private Button post_btn;    private ImageView image;    private Bitmap bitmap;    private String path;    private PreviewThread previewThread;    private PostThread postThread;    /**     * 主线程的Handler对象,更新UI     */    private Handler myHandler = new Handler(){        @Override        public void handleMessage(Message msg) {            switch(msg.what){                case 1:                    image.setImageBitmap((Bitmap) msg.obj);                    break;                case 2:                    image.setImageBitmap((Bitmap) msg.obj);                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        editText = (EditText) findViewById(R.id.edit);        preview_btn = (Button) findViewById(R.id.preview);        post_btn = (Button) findViewById(R.id.post);        image = (ImageView) findViewById(R.id.image);        /*        千万不要忘记打开线程!!         */        previewThread = new PreviewThread();        previewThread.start();        postThread = new PostThread();        postThread.start();        /**         * 在对应的按钮事件中,我们发送给子线程path,也就是主线程与子线程通信         */        preview_btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                path = editText.getText().toString();                if (path.equals("")) {                    setDialog("preview-operation denied.");                } else {                    Message msg = new Message();                    msg.obj = path;                    previewThread.myHandler1.sendMessage(msg);                }            }        });        /**         * 在对应的按钮事件中,我们发送给子线程path,也就是主线程与子线程通信         */        post_btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                path = editText.getText().toString();                if (path.equals("")) {                    setDialog("Post-operation denied.");                } else {                    Message msg = new Message();            //也可以选用obtainMessage()那个方法                    msg.obj = path;                         //直接装载path                    postThread.myHandler2.sendMessage(msg); //发送给子线程                }            }        });//        post_btn.setEnabled(false);    }    /**     *弹窗提醒     */    public void setDialog(String msg) {        new AlertDialog.Builder(MainActivity.this)                .setTitle("Warning")                .setMessage(msg)                .setNegativeButton("Okay",                        new DialogInterface.OnClickListener() {                            @Override                            public void onClick(DialogInterface dialogInterface, int i) {                            }                        }).show();    }    /**     * 预览,加载图片网络请求的子线程,拥有自己独立的handler以收发信息     * 在哪个线程中初始化Handler,这个Handler就是谁的,不过还需要跟Looper绑定才能完成收发信息     */    class PreviewThread extends Thread{        private Handler myHandler1;        @Override        public void run() {            Looper.prepare();            myHandler1 = new Handler(){                @Override                public void handleMessage(Message msg) {                            String path = (String) msg.obj;                            URL httpUrl = null;                            try {                                httpUrl = new URL(path);                                HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();                                connection.connect();                                bitmap = BitmapFactory.decodeStream(connection.getInputStream());//                                post_btn.setEnabled(true);                                Message toMain = new Message();                                toMain.obj = bitmap; //直接把bitmap向上转型,赋给obj以完成信息装载                                toMain.what = 1;     //设置what以便于主线程Handler的switch-case                                myHandler.sendMessage(toMain); //发送给谁就引用谁的sendMessage()                            } catch (MalformedURLException e) {                                e.printStackTrace();                            } catch (IOException e) {                                e.printStackTrace();                            }                    }            };            Looper.loop(); //启动消息循环        }    }    /**     * 设置背景的子线程,与上面的子线程类似不再赘述     */    class PostThread extends Thread{        private Handler myHandler2;        @Override        public void run() {            Looper.prepare();            myHandler2 = new Handler() {                @Override                public void handleMessage(Message msg) {                    String path2 = (String) msg.obj;                    URL httpUrl = null;                    try {                        httpUrl = new URL(path2);                        HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();                        connection.connect();                        MainActivity.this.setWallpaper(connection.getInputStream());                        bitmap = null;                        post_btn.setEnabled(true);                        Message toMain = new Message();                        toMain.obj = bitmap;                        toMain.what = 2;                        myHandler.sendMessage(toMain);                    } catch (MalformedURLException e) {                        e.printStackTrace();                    } catch (IOException e) {                        e.printStackTrace();                    }                }            };        }    }}



0 0
原创粉丝点击