Handler的使用

1、Handler的作用:

1)在Android中UI操作一般情况下不能放在子线程中进行操作,如果在子线程中操作会出现Only the original thread that created a view hierarchy can touch its views.错误,但是有的时候UI布局需要得到子线程的数据,这个时候就需要使用Handler来进行UI的操作。

2)如果UI布局还没有完成,这个时候是可以在子线程中进行UI的操作;代码如下:

public class MainActivity01 extends AppCompatActivity {
    TextView textview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textview = (TextView) findViewById(R.id.textview);
        AThread aThread = new AThread(textview);
        aThread.start();
    }

    class AThread extends Thread {
        TextView textView;

        public AThread(TextView textView) {
            this.textView = textView;
        }
        @Override
        public void run() {
            String temp = "hahaha";
            temp += "AAA";
            textView.setText(temp);
        }
    }
}


 

原因是:android在编译的时候回先判断activity是否存在,如果存在了才会去判断后面的UI操作是否是在UI线程中进行的,如果不是就会出现错误,但是如果把子线程进行的UI操作写在前面,就会在activity还没有布局完成的时候就进行了UI操作,因为activity== null所以不会去判断该UI操作是否是在UI线程中进行的。但是这种操作没有什么意义,通常情况下都是activity已经存在,只是想得到子线程中的属性来给UI里面的控件进行更改,因此要使用Handler。

2、Handler的用法:

a.1:在UI线程中进行Handler的初始化,在把初始化后的结果传递到子线程中,把UI控件需要的值通过sendMessage()方法传递出来然后在UI线程中更改。这也是Handler最常用的方法;代码如下:

public class MainActivity02 extends Activity implements View.OnClickListener {
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        textView.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        MyHandler myHanler = new MyHandler();
        BThread bThread = new BThread(myHanler);
        bThread.start();
    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            textView.setText(msg.obj.toString());
        }
    }
    class BThread extends Thread {
        Handler handler;

        public BThread(Handler handler) {
            this.handler = handler;
        }

        @Override
        public void run() {
            String temp = "哈哈哈";
            temp += "BBB";
            Message message = handler.obtainMessage();
            message.obj = temp;
            handler.sendMessage(message);
        }
    }
}

a.2 除此之外,其实我们还可以在子线程中定义Handler,通过把UI线程的Looper传递到子线程中来进行UI控件的操作设置;

代码如下:

UI线程代码:

public class MainActivity04 extends Activity implements View.OnClickListener{
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        textView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        DThread cThread = new DThread(textView, Looper.myLooper());
        cThread.start();
    }
}


子线程代码:

public class DThread extends Thread {
    TextView textView;
Looper looper;
    public DThread(TextView textView, Looper looper) {
        this.textView = textView;
        this.looper = looper;
    }

    @Override
    public void run() {
        Looper.prepare();
        MyHandler myHandler = new MyHandler(looper);
        Message message = myHandler.obtainMessage();
        String temp = "DDD";
        message.obj = temp;
        message.setTarget(myHandler);
        myHandler.sendMessage(message);
//        looper.loop();
    }
    class MyHandler extends Handler{
        public  MyHandler(Looper looper){
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            textView.setText(msg.obj.toString());
        }
    }
}

3、总结:

通过以上2中Handler的使用方法,我们可以发现不管在哪个线程进行Handler的定义,我们都可以完成UI控件的操作。是否能够进行UI控件的操作其实主要是看我们通过Handler把UI控件需要的子线程的哪个属性通过sendMessage()方法发送到了哪里,Handler发送的消息会被添加到被关联的MessageQueue中。我们就可以通过looper.loop()来遍历MessageQueue里面的信息只要MessageQueue是主线程的,那么这个信息就可以在主线程中得到就能够用得到的属性在UI线程中完成对控件的操作。

通过Handler的工作原理,我们可以直接写一个简单的自定义的Handler来完成对UI的操作;

代码如下:

自定义的Handler:

public class MyHand {
    ArrayList<IMessage> arrayList;

    public MyHand(ArrayList<IMessage> arrayList) {

        this.arrayList = arrayList;
    }

    public  void handleIMessage(IMessage iMessage){

    }
    public  void sendIMessage(IMessage iMessage){
        arrayList.add(iMessage);
    }
}

信息:

public class IMessage {
    Object object;
    MyHand target;
}


子线程:

public class GThread extends Thread {
    MyHand myHand;

    public GThread(MyHand myHand) {
        this.myHand = myHand;
    }

    @Override
    public void run() {
        String temp = "哈哈哈";
        temp += "GGG";
        IMessage iMessage = new IMessage();
        iMessage.target = myHand;
        iMessage.object = temp;
        myHand.sendIMessage(iMessage);
    }
}


主线程:

public class MainActivity07 extends Activity implements View.OnClickListener{
    TextView textView;
    Button button_check;

    IMessage iMessage;
   ArrayList<IMessage> arrayList;
    MyHand myHand ;
    boolean isFlag = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        button_check = (Button) findViewById(R.id.button_check);
        textView.setOnClickListener(this);
        button_check.setOnClickListener(this);
        arrayList = new ArrayList();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.textview:
               if (arrayList.size() > 0){
                   myHand = iMessage.target;
                   myHand.handleIMessage(iMessage);
               }
                break;
            case R.id.button_check:
                GThread gThread = new GThread(new Ghand(arrayList));
                gThread.start();
                while (isFlag){
                    if (arrayList.size() > 0){
                        iMessage = arrayList.get(0);
                        if (iMessage == null){
                            return;
                        }
                        isFlag = false;
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        }
    }
    class Ghand extends MyHand{

        public Ghand(ArrayList<IMessage> arrayList) {
            super(arrayList);
        }

        @Override
        public void handleIMessage(IMessage iMessage) {
            textView.setText(iMessage.object.toString());
        }
    }
}



 



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值