zoukankan      html  css  js  c++  java
  • Android--Handler

    一、Handler的定义:

    主要接受子线程发送的数据, 并用此数据配合主线程更新UI。

    解释:当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。  如果此时需要一个耗时的操作,例如: 联网读取数据,    或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示  "强制关闭"。  这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。 这个时候,Handler就出现了。,来解决这个复杂的问题 ,由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。

    二、Handler一些特点

    handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:

    (1)安排消息或Runnable 在某个主线程中某个地方执行;

    (2)安排一个动作在不同的线程中执行。

    Handler中分发消息的一些方法

    post(Runnable)

    postAtTime(Runnable,long)

    postDelayed(Runnable long)

    sendEmptyMessage(int)

    sendMessage(Message)

    sendMessageAtTime(Message,long)

    sendMessageDelayed(Message,long)

    以上post类方法允许你排列一个Runnable对象到主线程队列中,

    sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新。

    三、Handler实例

    listview显示数据,布局和上一篇一样,MainActivity类代码

    package com.example.multithreadind01;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    
    public class MainActivity extends Activity {
    
        private String fromDb_str1 = "";
        private Button btn;
        private TextView tv;
        private ListView lv;
        private BaseAdapter adapter;
        private List<User> userList = new ArrayList<User>();
        private Runnable doInBackground1;
        private Runnable doInBackground2;
        
        //1.跟着主线程走,可以碰UI
        //2.能够接受子线程发送的消息(Message)
        //        子线程类本身不可以发信息
        private Handler handler;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            Log.i("UI_MainThread","id:"+Thread.currentThread().getId());
            
            for (int i = 0; i < 5; i++) {
                User u = new User();
                u.setUsername("小明"+i);
                u.setSex("女"+i);
                userList.add(u);
            }
            
            tv =(TextView)findViewById(R.id.textView1);
            btn =(Button)findViewById(R.id.button1);
            btn.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    //1.访问数据库或者互联网(但会卡的)
                    //2.更新界面
                    Thread t1 = new Thread(doInBackground1);
                    t1.start();
                    
                    Thread t2 = new Thread(doInBackground2);
                    t2.start();
                    
                }
            });
            adapter = new BaseAdapter(){
    
                @Override
                public int getCount() {
                    // TODO Auto-generated method stub
                    return userList.size();
                }
    
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                    LayoutInflater inflater = MainActivity.this.getLayoutInflater();
                    View view;
                    if (convertView==null){
                        view = inflater.inflate(R.layout.item, null);
                    }
                    else{
                        view = convertView;
                    }
                    
                    TextView tv_username = (TextView)view.findViewById(R.id.username);
                    TextView tv_sex = (TextView)view.findViewById(R.id.sex);
                    tv_username.setText(userList.get(position).getUsername());
                    tv_sex.setText(userList.get(position).getSex());
                    return view;
                }
                
                @Override
                public Object getItem(int position) {
                    // TODO Auto-generated method stub
                    return null;
                }
    
                @Override
                public long getItemId(int position) {
                    // TODO Auto-generated method stub
                    return 0;
                }
            };
            lv = (ListView)findViewById(R.id.listView1);
            lv.setAdapter(adapter);
            
            handler = new Handler(){
                
                //1.消息msg来自于子线程
                //2.消息可以多个,采用msg.what识别
                //3.处理消息,一般就会更新UI
                //4.此方法可以参考onPostExecute
                @Override
                public void handleMessage(Message msg) {
                    
                    super.handleMessage(msg);
                    int msgwhat = msg.what;
                    Log.i("handler","已经收到消息,消息what:"+msgwhat+",id:"+Thread.currentThread().getId());
                    
                    if (msgwhat==1){
                        //更新helloworld
                        tv.setText("子线程让我更新"+msgwhat);
                    }
                    if (msgwhat==2){
                        //更新ListView
                        adapter.notifyDataSetChanged();
                    }
    
                }
                
            };
            
            //子线程代码1
            doInBackground1 = new Runnable() {
                
                @Override
                public void run() {
                    Log.i("sub_Thread","子线程1启动,id:"+Thread.currentThread().getId());
                    
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    
                    //1.访问数据库或者互联网,不在UI进程,所以不卡
                    Message msg = new Message();
                    //对消息一个识别号,便于handler能够识别
                    msg.what = 1;
                    handler.sendMessage(msg);
                    Log.i("sub_Thread","子线程1已经发送消息给handler");
                }
            };
            
            
            
            //子线程代码1
            doInBackground2 = new Runnable() {
                
                @Override
                public void run() {
                    Log.i("sub_Thread","子线程2启动,id:"+Thread.currentThread().getId());
                    
                    try {
                        Thread.sleep(6000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }               
                    Message msg = new Message();
                    //对消息一个识别号,便于handler能够识别
                    msg.what = 2;
                    //handler.sendMessage(msg);
                    handler.sendMessageDelayed(msg, 500);                
                    //访问互联网,下载最新的,更新data,但不碰界面
                    for (User user : userList) {
                        user.setSex("女");
                    }
                    
                    Log.i("sub_Thread","子线程2已经发送消息给handler");
                }
            };
            
        }
    }

    效果图:

                 

             

    四、总结:

    1)android系统是单线程系统,为了实现多线程的效果,采用了message queue。

    2)为实现多线程,可采用runOnUiThread,post,handle,AsyncTask技术实现。

  • 相关阅读:
    从零开始学android开发-setBackgroundDrawable与setBackgroundResource的区别
    从零开始学android开发-用Intent启动Activity的方法
    从零开始学android开发-View的setOnClickListener的添加方法
    从零开始学android开发- 应用程序窗体显示状态操作requestWindowFeature
    从零开始学android开发- layout属性介绍
    android常见错误--Unable to resolve target ‘android
    Html+jquery mobile
    用jQuery Mobile做HTML5移动应用的三个优缺点
    Chrome Apps将可以打包成iOS或Android应用
    [转]0.python:scikit-learn基本用法
  • 原文地址:https://www.cnblogs.com/yuluo123/p/6138876.html
Copyright © 2011-2022 走看看