• android之Handler机制


    简单例子开头: 网络http请求网站源码数据并显示

      注意点:访问网络需要加Internet权限:
          android.permission.INTERNET


    简单的步骤:

    使用UrlConnection请求一个url地址获取内容:

    //1.创建一个Url对象
      URL url = new URL(url_str);

    //2.获取一个UrlConnection对象
      HttpURLConnection connection = (HttpURLConnection)url.openConnection();

    //3.为UrlConnection对象设置一些请求的参数,请求方式,连接的超时时间
      connection.setRequestMethod("GET");//设置请求方式
      connection.setConnectTimeout(1000*10);//设置超时时间

    //4.在获取url请求的数据前需要判断响应码,200 :成功,206:访问部分数据成功 300:跳转或重定向 400:错误 500:服务器异常
      int code = connection.getResponseCode();
      if(code == 200){


    //5.获取有效数据,并将获取的流数据解析成String
      InputStream inputStream = connection.getInputStream();
      String result = StreamUtils.streamToString(inputStream);
      }

    注意:

    (1)主线程不能够做耗时的操作,网络请求就是耗时的操作需要放到子线程做。
    (2)子线程不能更新控件的内容(更新Ui)。所以产生了矛盾,解决办法就是使用Handler(处理消息机制).

    (3)子线程一定不能更新UI?是错的, SurfaceView :多媒体视频播放 ,可以在子线程中更新UI;Progress(进度)相关的控件:也是可以在子线程中更新Ui;

    审计机制:activity完全显示的时候审计机制才会去检测子线程有没有更新Ui. 当activity没有完全显示的时候子线程可以更新UI

    ******消息机制原理*****

     Handler、Looper、MessageQuene之间的关系。

    每一个线程最多有一个Looper、一个Looper里边含有一个MessageQuene。

    Handler每次将消息发送到MessageQuene中,Looper用过一个死循环不断的从MessageQuene中获取消息,获取后,根据Message的target分发给对应的Handler进行处理。

    Handler:消息机制的写法(重要) 

    使用Handler的步骤:

    1.主线程中创建一个Handler

    private Handler handler = new Handler(){
        //重写handler的handlermessage方法
    public void handleMessage(android.os.Message msg) { }; };

    2.重写handler的handlermessage方法

    3.子线程中创建一个Message对象,将获取的数据绑定给msg

    Message msg = new Message();
    //另一种方式:Message msg = Messge.obtain;
    msg.obj = result;

    4.handler对象在子线程中将message发送给主线程

    handler.sendMessage(msg);

    5. 主线程中handlermessage重写的方法中 接受子线程发来的数据,就可以做更新UI的操作。

     String result= (String) msg.obj;

     下面是一个例子:

    布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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:orientation="vertical"
        tools:context="com.example.yb.myapplication.HttpUrlActivity">
    
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/ed_url"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/bt_httpRequest"
            android:text="请求网页数据"/>
        <ScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_httpResponse"/>
        </ScrollView>
    </LinearLayout>

    在Activity里面

    public class HttpUrlActivity extends AppCompatActivity implements View.OnClickListener {
       private Context mcontext;
        private TextView tv_httpResponse1;
        private EditText ed_url;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_http_url);
    
            mcontext=this;
            Button bt_httpRequest = (Button)findViewById(R.id.bt_httpRequest);
            ed_url = (EditText) findViewById(R.id.ed_url);
            tv_httpResponse1 = (TextView) findViewById(R.id.tv_httpResponse);
            bt_httpRequest.setOnClickListener(this);
        }
    
    //H.1在主线程中创建一个handler对象 ,这里是匿名内部类
        Handler handler=new Handler(){
        //H.2重新handleMessage方法
            @Override
            public void handleMessage(Message msg) {
                //H.5 接受子线程发来的 数据,处理数据
                String result= (String) msg.obj;
                //H.6当前线程是主线程,可以做UI的更新
                //5显示到TextView
                tv_httpResponse1.setText(result);
            }
        };
    
        @Override
        public void onClick(View v) {
    
                    final String url_str = ed_url.getText().toString().trim();
                    if (TextUtils.isEmpty(url_str)) {
                        Toast.makeText(mcontext, "url不能为空", Toast.LENGTH_SHORT).show();
                        return;
                    }
    //匿名内部类可以用于接口上,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。
    // 最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口。
                    //创建一个子线程做网络请求
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                //四.请求url地址
                                //1创建一个url对象
                                URL url = new URL(url_str);
    
                                //2获取一个urlConnection对象
                                HttpURLConnection con = (HttpURLConnection) url.openConnection();
    
                                //3设置urlConnection的参数:请求时间,请求方式
                                con.setRequestMethod("GET");
                                con.setConnectTimeout(1000 * 10); //超时时间
    
                                //4根据请求的结果的响应码来判断,200成功,206部分数据访问成功。400错误,500服务器异常
                                int code = con.getResponseCode();
                                if (code == 200) {
                                    //获取数据,并返回的流数据解析为String
                                    InputStream inputStream = con.getInputStream();
    
                                    //将获取的读取流解析为String字符串
                                    String result=StreamUtil.stremToString(inputStream);
    
                                    //H.3 子线程创建一个Message对象,为了携带子线程获取的数据给主线程
                                    Message msg=new Message();
                                    msg.obj=result;
                                    //H.4使用handler对象将消息发送给主线程
                                    handler.sendMessage(msg);
    
                                }
    
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
    
    
        }
    
    }

     创建一个工具类StreamUtil ,里面写入把读取流转为String返回

    public class StreamUtil {
        /**
         * 获取的读取流转为String返回
         *
         * @param inputStream
         */
        public static String stremToString(InputStream in) {
            String result="";
            try {
                //创建一个字节数组写入流
                ByteArrayOutputStream out=new ByteArrayOutputStream();
    
                byte[] buffer=new byte[1024];
                int length=0;
                while((length=in.read(buffer))!=-1){  //如果返回-1 则表示数据读取完成了。
                    out.write(buffer,0,length);//写入数据
                    out.flush();
                }
                result=out.toString();//写入流转为字符串
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    其他的消息处理:

    使用handler直接post到主线程,handler需要在主线程创建

    //延迟多少毫米执行runnable。
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            tv_simple.setText("我被更新了");
            }
    }, 1000*5);

    应用场景:广告展示后,做页面跳转。

  • 相关阅读:
    HDU 5316——Magician——————【线段树区间合并区间最值】
    HDU 5318——The Goddess Of The Moon——————【矩阵快速幂】
    BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
    BNU 20860——Forwarding Emails——————【强连通图缩点+记忆化搜索】
    日期
    HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】
    HDU 5288——OO’s Sequence——————【技巧题】
    c++ 中. 和 ->,波浪号 ~ 符号怎么用 ————很重要
    c++缓冲区std::wstringbuf
    Arduino读取写入电压值
  • 原文地址:https://www.cnblogs.com/DonAndy/p/6175700.html
Copyright © 2020-2023  润新知