3 Handler的用法

3-1 Handler用法(一)

API文档描述:

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the toplevel application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.

翻译:

一个处理程序允许你发送和线程消息队列中的消息和Runnable对象关联的进程。每个处理程序实例都与一个单独的线程关联,该线程的消息队列。当你创建一个新的处理程序,它是绑定到创建它的线程的线程/消息队列,从这一点上,它将传递消息和runnable对象,消息队列和执行他们出来的消息队列。

Handler有两个主要用途:(1)调度消息和runnable对象作为将来的执行;及(2)将被执行在一个不同的线程自己的行动。

当为应用程序创建一个进程时,它的主线程是专门负责运行一个消息队列,它负责管理顶级应用程序对象(活动、广播接收器等),以及它们所创建的任何窗口。您可以创建自己的线程,并通过一个处理程序与主应用程序线程进行通信。这是通过调用同一岗位或SendMessage方法之前做的,但是从你的新思路。给定的运行或消息将被安排在处理程序的消息队列,并在适当的时候进行处理。

Handler的两大用途:

  1. 在未来某个时间点执行message和runnable对象;
  2. 将要执行的action放到message queue中去,然后使得另外的不同的线程可以执行这个action。

我们可以自己在UI线程之上再创建线程,然后我们需要通过Handler来使得我们的线程和UI线程通信。这样我们才能在我们的子线程中更新UI。因为Android中UI的更新只能在UI线程中进行。我们只能通过Handler的通信来使得我们从子线程中更新UI。

MainActivity.java

package com.example.yzx;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv=(TextView) findViewById(R.id.tv);
        new Thread(){
            public void run() {
                try {
                    Thread.sleep(1000);
                tv.setText("update thread");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }
        @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示。但是,在主线线程之外的线程中直接更新页面显示的问题是

 报异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

【只有原始创建这个视图层次(view hierachy)的线程才能修改它的视图(view)】

 


这个异常的描述是仅能在原线程中更新UI,产生的原因是我们在非UI线程中执行UI

 

 

解决方法:

package com.example.yzx;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    private Handler handler = new Handler();

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

        new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            tv.setText("update thread");
                        }
                    });

                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

 

从上面的方法中我们可以知道,如果想直接更新ui,我们需要在Thread的run方法中通过handler.post()的方法来实现,
而post方法中的参数是一个new Runnable(){public void run(){},然后我们在这个run方法中去更新ui,这才是正确的方法

实例1:淘宝中图片的自动替换。

MainActivity.java


package com.example.yzx;

import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore.Images;

import com.example.yzx.R.id;

import android.app.Activity;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    private Handler handler = new Handler();

    private ImageView imageview;
    // 建立图片的数组
    private int Images[] = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
    // 建立索引,指定图片的位置
    private int index;

    MyRunnable myRunnable = new MyRunnable();

    // 创建一个runnable
    class MyRunnable implements Runnable {
        public void run() {
            index++;
            index = index % 3;// 三张图片不断循环
            imageview.setImageResource(Images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }

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

        imageview = (ImageView) findViewById(R.id.imageView1);
        handler.postDelayed(myRunnable, 1000);
        
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

两个postDelayed()方法 :要循环发送消息 。

第一个 把runnable发送到thread(main)的messagequeue 里,等待时机到了延迟1秒后去执行run方法;

而run方法里的postDelayed()再次把runnable发送到thread(main)的messagequeue 里,等待时机到了延迟1秒后去执行run方法;如此循环下去。

3-2 Handler用法(二)

传送数据:

MainActivity.java

 

package com.example.yzx;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore.Images;

import com.example.yzx.R.id;

import android.app.Activity;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    private Handler handler = new Handler() {
        // a。重写一个handlermassage的方法,是接受我们发送来的消息
        public void handleMessage(android.os.Message msg) {
            tv.setText("" + msg.arg1);
        };
    };

    private ImageView imageview;
    // 1. 建立图片的数组
    private int Images[] = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
    // 2. 建立索引,指定图片的位置
    private int index;

    MyRunnable myRunnable = new MyRunnable();

    // 3.创建一个runnable
    class MyRunnable implements Runnable {
        public void run() {
            index++;
            index = index % 3;// 三张图片不断循环
            imageview.setImageResource(Images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }

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

        imageview = (ImageView) findViewById(R.id.imageView1);
        // 4.
        handler.postDelayed(myRunnable, 1000);
        // b.发送消息
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    // c创建一个message
                    Message message = new Message();
                    // d.给messa指定参数
                    message.arg1 = 88;
                    // e.把message发送出去
                    handler.sendMessage(message);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }

    // new Thread() {
    // public void run() {
    // try {
    // Thread.sleep(1000);
    // handler.post(new Runnable() {
    // @Override
    // public void run() {
    // // TODO Auto-generated method stub
    // tv.setText("update thread");
    // }
    // });
    //
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // };
    // }.start();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

 

传送多个数据:

 
package com.example.yzx;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore.Images;

import com.example.yzx.R.id;

import android.app.Activity;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    private Handler handler = new Handler() {
        // a。重写一个handlermassage的方法,是接受我们发送来的消息
        public void handleMessage(android.os.Message msg) {
            tv.setText("" + msg.obj);
            // tv.setText("" + msg.arg1+"-"+msg.arg2);
        };
    };

    class Person {
        public String name;
        public int age;
        public String sex;

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "name=" + name + "  age=" + age + "  sex=" + sex;
        }
    }

    private ImageView imageview;
    // 1. 建立图片的数组
    private int Images[] = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
    // 2. 建立索引,指定图片的位置
    private int index;

    MyRunnable myRunnable = new MyRunnable();

    // 3.创建一个runnable
    class MyRunnable implements Runnable {
        public void run() {
            index++;
            index = index % 3;// 三张图片不断循环
            imageview.setImageResource(Images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }

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

        imageview = (ImageView) findViewById(R.id.imageView1);
        // 4.
        handler.postDelayed(myRunnable, 1000);
        // b.发送消息
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    // c创建一个message
                    Message message = new Message();
                    // d.给messa指定参数
                    message.arg1 = 88;
                    message.arg2 = 188888;
                    Person person = new Person();
                    person.age = 18;
                    person.name = "张三";
                    person.sex = "男";
                    message.obj = person;
                    // e.把message发送出去
                    handler.sendMessage(message);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }

    // new Thread() {
    // public void run() {
    // try {
    // Thread.sleep(1000);
    // handler.post(new Runnable() {
    // @Override
    // public void run() {
    // // TODO Auto-generated method stub
    // tv.setText("update thread");
    // }
    // });
    //
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // };
    // }.start();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}


一样的效果:

1.
new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
//                    // c创建一个message
//                    Message message = new Message();
//                    // d.给messa指定参数
//                    message.arg1 = 88;
//                    message.arg2 = 188888;
                    Message message=handler.obtainMessage();
                    Person person = new Person();
                    person.age = 18;
                    person.name = "张三";
                    person.sex = "男";
                    message.obj = person;
                    // e.把message发送出去
                    handler.sendMessage(message);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();

2.

new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
//                    // c创建一个message
//                    Message message = new Message();
//                    // d.给messa指定参数
//                    message.arg1 = 88;
//                    message.arg2 = 188888;
                    Message message=handler.obtainMessage();
                    Person person = new Person();
                    person.age = 18;
                    person.name = "张三";
                    person.sex = "男";
                    message.obj = person;
                    // e.把message发送出去
//                    handler.sendMessage(message);
                    message.sendToTarget();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();

 

 

移出消息:

点击button中止图片的循环

 

package com.example.yzx;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore.Images;

import com.example.yzx.R.id;

import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

//C
public class MainActivity extends Activity implements OnClickListener {
    // A
    private Button button;

    private TextView tv;
    private Handler handler = new Handler() {
        // a。重写一个handlermassage的方法,是接受我们发送来的消息
        public void handleMessage(android.os.Message msg) {
            tv.setText("" + msg.obj);
            // tv.setText("" + msg.arg1+"-"+msg.arg2);
        };
    };

    class Person {
        public String name;
        public int age;
        public String sex;

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "name=" + name + "  age=" + age + "  sex=" + sex;
        }
    }

    private ImageView imageview;
    // 1. 建立图片的数组
    private int Images[] = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
    // 2. 建立索引,指定图片的位置
    private int index;

    MyRunnable myRunnable = new MyRunnable();

    // 3.创建一个runnable
    class MyRunnable implements Runnable {
        public void run() {
            index++;
            index = index % 3;// 三张图片不断循环
            imageview.setImageResource(Images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        // B
        button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(this);
        imageview = (ImageView) findViewById(R.id.imageView1);
        // 4.
        handler.postDelayed(myRunnable, 1000);
        // b.发送消息
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    // // c创建一个message
                    // Message message = new Message();
                    // // d.给messa指定参数
                    // message.arg1 = 88;
                    // message.arg2 = 188888;
                    Message message = handler.obtainMessage();
                    Person person = new Person();
                    person.age = 18;
                    person.name = "张三";
                    person.sex = "男";
                    message.obj = person;
                    // e.把message发送出去
                    // handler.sendMessage(message);
                    message.sendToTarget();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }

    // new Thread() {
    // public void run() {
    // try {
    // Thread.sleep(1000);
    // handler.post(new Runnable() {
    // @Override
    // public void run() {
    // // TODO Auto-generated method stub
    // tv.setText("update thread");
    // }
    // });
    //
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // };
    // }.start();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    // D
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        handler.removeCallbacks(myRunnable);
    }

}

 

点击button按钮,图片不再循环

 

拦截消息:

  handler.removeCallBack(runnable)
    可以移除一个已经挂接执行的方法
  Handler handler=new Handler(new Callback(){里面也有个boolean handleMessage 返回true时可以截获发送到handler的message}){@override void handlMessage()}

package com.example.yzx;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.*;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

//C
public class MainActivity extends Activity implements OnClickListener {
    // A
    private Button button;

    private TextView tv;
    private Handler handler = new Handler(new Callback() {
        @Override
        public boolean handleMessage(Message paramMessage) {
            Toast.makeText(getApplicationContext(), "" + 1, 1).show();
            return false;// 当为true的时候就拦截消息,后面的toast就不执行。
        }
    }) {
        public void handleMessage(Message msg) {
            Toast.makeText(getApplicationContext(), "" + 2, 1).show();
        }// handler处理消息
    };

    class Person {
        public String name;
        public int age;
        public String sex;

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "name=" + name + "  age=" + age + "  sex=" + sex;
        }
    }

    private ImageView imageview;
    // 1. 建立图片的数组
    private int Images[] = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
    // 2. 建立索引,指定图片的位置
    private int index;

    MyRunnable myRunnable = new MyRunnable();

    // 3.创建一个runnable
    class MyRunnable implements Runnable {
        public void run() {
            index++;
            index = index % 3;// 三张图片不断循环
            imageview.setImageResource(Images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        // B
        button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(this);
        imageview = (ImageView) findViewById(R.id.imageView1);
        // 4.
        handler.postDelayed(myRunnable, 1000);
        // b.发送消息
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    // // c创建一个message
                    // Message message = new Message();
                    // // d.给messa指定参数
                    // message.arg1 = 88;
                    // message.arg2 = 188888;
                    Message message = handler.obtainMessage();
                    Person person = new Person();
                    person.age = 18;
                    person.name = "张三";
                    person.sex = "男";
                    message.obj = person;
                    // e.把message发送出去
                    // handler.sendMessage(message);
                    message.sendToTarget();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }

    // new Thread() {
    // public void run() {
    // try {
    // Thread.sleep(1000);
    // handler.post(new Runnable() {
    // @Override
    // public void run() {
    // // TODO Auto-generated method stub
    // tv.setText("update thread");
    // }
    // });
    //
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // };
    // }.start();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    // D
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        // handler.removeCallbacks(myRunnable);
        handler.sendEmptyMessage(1);
    }

}

带Callback参数的Handler可以截获消息,true则拦截,false则不拦截

 

 

posted @ 2016-03-28 17:33  沉默的羊癫疯  阅读(182)  评论(0编辑  收藏  举报