04_消息机制的写法
handle直接翻译叫处理。Handler叫做处理者/助手。
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.
Handler允许你去发送并且处理消息或者说是一个Runnable对象。Handler是跟一个Thread线程对应起来。线程有一个MessageQueue(消息队列)。每一个Handler的实例都和一个单独的线程是一一对应的。在哪一个线程创建的Handler,这个Handler就和这个线程是对应起来的。如果Handler是在主线程里面创建的,那么它实际上就对应着这个主线程。当你创建一个Handler对象,它就跟这个线程绑定在一起了。反复提到了有一个消息队列。可以通过Handler来发一条消息,实际上是想在子线程里面获取数据。然后得在主线程拿到这个数据之后,更新界面。这就涉及到它们俩之间得进行沟通。子线程拿到数据之后得想办法通知一下主线程,在通知的过程当中可以把数据给它携带过去。这就涉及到子线程要发一个消息发给主线程。
在哪个线程创建的Handler,这个Handler就跟当前的线程建立的一一对应的关系。所以可以在主线程创建这么一个Handler。Handler可以发送一个消息并且还可以处理消息。
handler既可以去发送消息/数据还可以处理消息,那就可以通过Handler在子线程发消息,在主线程处理消息。
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.
有两个最主要的用处:在未来的某一时刻来运行这么一个消息或者说是一个runnable对象。这一个用法咱们以后再说。最主要的对于咱们的就是这个东西:可以在你所拥用的不同线程之间来进行消息的传递。基本的思路:在子线程里面通过handler发消息,在主线程中创建一个Handler对象。
安卓源码路径是:
H:\heimaandroidadt\adt-bundle-windows-x86_64_20140101\adt-bundle-windows-x86_64_20140101\sdk\sources\android-18
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
实际上它是啥也没有,等着你去实现。你想去接收到消息的话必须得实现这个方法。
整个handler的用法套路还是挺简单的,一共就分三步:①在主线程创建一个handler②子线程发消息③主线程处理消息 一共就这么几步,但是这里面这个原理稍微有一点复杂。
package com.itheima.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class HelloServlet */ //@WebServlet("/HelloServlet") public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * Default constructor. */ public HelloServlet() { // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //response.getWriter().append("Served at: ").append(request.getContextPath()); try { Thread.sleep(10000);//接收请求之后设置服务端睡眠10秒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } response.getWriter().append("Served at: ").append(request.getContextPath());//让服务端睡眠10秒之后才产生响应 } //http://localhost:8080/day07_01_servlethello/hello /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
package com.itheima.htmlcodeviewer; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_url; private Button btn_show; private TextView tv_code; //①在主线程创建一个handler 这个handler的消息就会发送到主线程的消息队列中 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) {//这就是套路,创建一个handler对象并且重写它的handleMessage()方法. // TODO Auto-generated method stub //super.handleMessage(msg); //可以通过handler在主线程中处理消息 在handleMessage方法中处理消息 String temp = (String) msg.obj;//obj携带了相关的数据,实际上它是一个text,是一个String类型的文本 //刚才咱们丢进来的就是String类型的 tv_code.setText(temp);//由于这个Handler是在主线程创建的,所以直接在这儿去修改这个数据.我现在是在主线程操作. //实现了把消息丢给主线程来处理. }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_url = (EditText) findViewById(R.id.et_url); btn_show = (Button) findViewById(R.id.btn_show); tv_code = (TextView) findViewById(R.id.tv_code); //et_url.setText("http://10.0.2.2:8080"); //et_url.setText("http://10.0.2.2:8080/day07_01_servlethello/hello"); et_url.setText("http://localhost:8080/day07_01_servlethello/hello"); btn_show.setOnClickListener(new MyOnClickListenr()); String name = Thread.currentThread().getName(); Toast.makeText(this, name, Toast.LENGTH_SHORT).show(); } private class MyOnClickListenr implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub new Thread(){ public void run() { //获取url String path = et_url.getText().toString().trim(); try { URL url = new URL(path); //拿着url联网 //URLConnection openConnection = url.openConnection(); HttpURLConnection openConnection = (HttpURLConnection) url.openConnection(); //} catch (MalformedURLException e) { //设置请求的方法 方法要大写 默认采用的是GET方式请求 openConnection.setRequestMethod("GET"); //如果联网之后网络信号不是太好,那就涉及到一直在等,一直在等 //有的时候可能会等的时间很长,等的时间很长的话那就有问题了,我究竟等到什么时候算是个结束 //设置超时的时间,一旦超过这个时间默认就是连接失败,让它停止下来 openConnection.setConnectTimeout(10000);//设置一个连接超时的时间 //获取响应码 int responseCode = openConnection.getResponseCode(); //判断响应码 如果是200 获取流 if(responseCode==200){ //联网后获得响应内容 响应是通过流的方式去返回回来的 //通过textview 展示对应的内容 InputStream inputStream = openConnection.getInputStream();//InputStream其实放的就是跟咱们HTML代码相关的内容 String stringFromStream = Utils.getStringFromStream(inputStream); //不能直接修改界面 而是要通知主线程 获取到了数据 并且把数据丢给主线程 在主线程中显示 //②通过handler发送消息Message,把要更新界面用到的数据 通过Message 携带数据 //不能直接修改界面 而是要通知主线程 获取到了数据 并且把数据丢给主线程 在主线程中显示 所以现在就用到了一个API:Handler //通过handler发送消息Message 把要更新界面用到的数据 通过Message进行携带 Message是一个对象 一个对象里面可以搞一些属性 通过这些属性 //就把这些内容给它携带过去 携带数据 Message msg = new Message(); msg.obj = stringFromStream;//通过obj就可以携带数据 因为它是Object类型 什么对象都可以丢给它 handler.sendMessage(msg); //修改textview内容展示数据 //tv_code.setText(stringFromStream); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }.start(); } } }
package com.itheima.htmlcodeviewer; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; public class Utils { //从这个流里面把它内容读出来,读出来之后把它转化成一个String类型的数据 public static String getStringFromStream(InputStream inputStream) { // TODO Auto-generated method stub //把流转化为字符串 ByteArrayOutputStream baso = new ByteArrayOutputStream(); int len = -1; byte[] buffer = new byte[1024]; try { while((len=inputStream.read(buffer))!=-1){ baso.write(buffer, 0, len); } inputStream.close(); byte[] byteArray = baso.toByteArray(); return new String(byteArray); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } }