Android Handler多线程技术 个人心得

这里有一篇详细介绍的文章: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值