• android——handler机制原理


      在android版本4.0及之后的版本中多线程有明确的分工,子线程可以写所有耗时的代码(数据库、蓝牙、网络服务),但是绝对不能碰UI,想碰UI跟着主线程走,那么我们如何才能让主线程知道我们要对 UI进行操作呢?这时我们就可以利用用消息机制——handler去通知主线程(因为子线程本身不可以发消息)

      下面是handler简单的工作原理图(此图为转载)

       handler用来发消息和处理消息

    下面用个案例来说明:

      activity_main.xml:

          

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     >
    10  
    11     <TextView
    12         android:id="@+id/textView1"
    13         android:layout_width="wrap_content"
    14         android:layout_height="wrap_content"
    15         android:text="@string/hello_world" />
    16 
    17     <Button
    18         android:id="@+id/button1"
    19         android:layout_width="wrap_content"
    20         android:layout_height="wrap_content"
    21         android:layout_alignParentRight="true"
    22         android:layout_alignTop="@+id/textView1"
    23         android:layout_marginRight="53dp"
    24         android:text="Button" />
    25 
    26     <ListView
    27         android:id="@+id/listView1"
    28         android:layout_width="match_parent"
    29         android:layout_height="wrap_content"
    30         android:layout_below="@+id/button1"
    31         android:layout_marginTop="84dp" >
    32     </ListView>
    33 
    34    <!--  <ProgressBar
    35         android:id="@+id/progressBar1"
    36         style="?android:attr/progressBarStyleHorizontal"
    37         android:layout_width="wrap_content"
    38         android:layout_height="wrap_content"
    39         android:layout_alignLeft="@+id/listView1"
    40         android:layout_alignRight="@+id/button1"
    41         android:layout_below="@+id/button1"
    42         android:layout_marginTop="28dp" /> -->
    43 
    44 </RelativeLayout>

    listview中的布局item.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="horizontal" >
     6     <TextView 
     7         android:id="@+id/username"
     8         android:layout_weight="1"
     9         android:layout_width="match_parent"
    10         android:layout_height="60dp"
    11         android:textSize="45dp"
    12         />
    13 
    14     <TextView
    15         android:id="@+id/sex"
    16         android:layout_width="match_parent"
    17         android:layout_height="60dp"
    18         android:layout_weight="1"
    19         android:textSize="45dp" />
    20 
    21 </LinearLayout>

    User.java(用于模拟数据)

     1 public class User {
     2     private String username;
     3     private String sex;
     4     public String getUsername() {
     5         return username;
     6     }
     7     public void setUsername(String username) {
     8         this.username = username;
     9     }
    10     public String getSex() {
    11         return sex;
    12     }
    13     public void setSex(String sex) {
    14         this.sex = sex;
    15     }
    16 
    17 }

    mainActivity.java

     

      1  2 
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 
      6 import android.app.Activity;
      7 import android.os.Bundle;
      8 import android.os.Handler;
      9 import android.os.Message;
     10 import android.util.Log;
     11 import android.view.LayoutInflater;
     12 import android.view.Menu;
     13 import android.view.MenuItem;
     14 import android.view.View;
     15 import android.view.View.OnClickListener;
     16 import android.view.ViewGroup;
     17 import android.widget.BaseAdapter;
     18 import android.widget.Button;
     19 import android.widget.ListView;
     20 import android.widget.TextView;
     21 import android.widget.Toast;
     22 
     23 
     24 public class MainActivity extends Activity {
     25 
     26     private String fromDb_str1 = "";
     27     private Button btn;
     28     private TextView tv;
     29     private ListView lv;
     30     private BaseAdapter adapter;
     31     private List<User> userList = new ArrayList<User>();
     32     private Runnable doInBackground1;
     33     private Runnable doInBackground2;
     34     
     35     //1.跟着主线程走,可以碰UI
     36     //2.能够接受子线程发送的消息(Message)
     37     //        子线程类本身不可以发信息
     38     private Handler handler;
     39     
     40     @Override
     41     protected void onCreate(Bundle savedInstanceState) {
     42         super.onCreate(savedInstanceState);
     43         setContentView(R.layout.activity_main);
     44         
     45         Log.i("UI_MainThread","id:"+Thread.currentThread().getId());
     46         
     47         
     48         //模拟数据访问产生数据
     49         for (int i = 0; i < 5; i++) {
     50             User u = new User();
     51             u.setUsername("小明"+i);
     52             u.setSex("女"+i);
     53             userList.add(u);
     54         }
     55         
     56         tv =(TextView)findViewById(R.id.textView1);
     57         btn =(Button)findViewById(R.id.button1);
     58         btn.setOnClickListener(new OnClickListener() {
     59             
     60             @Override
     61             public void onClick(View v) {
     62                 //1.访问数据库或者互联网(但会卡的)
     63                 //2.更新界面
     64                 Thread t1 = new Thread(doInBackground1);
     65                 t1.start();
     66                 
     67                 Thread t2 = new Thread(doInBackground2);
     68                 t2.start();
     69                 
     70             }
     71         });
     72         adapter = new BaseAdapter(){
     73 
     74             @Override
     75             public int getCount() {
     76                 // TODO Auto-generated method stub
     77                 return userList.size();
     78             }
     79 
     80             @Override
     81             public View getView(int position, View convertView, ViewGroup parent) {
     82                 LayoutInflater inflater = MainActivity.this.getLayoutInflater();
     83                 View view;
     84                 if (convertView==null){
     85                     view = inflater.inflate(R.layout.item, null);
     86                 }
     87                 else{
     88                     view = convertView;
     89                 }
     90                 
     91                 TextView tv_username = (TextView)view.findViewById(R.id.username);
     92                 TextView tv_sex = (TextView)view.findViewById(R.id.sex);
     93                 tv_username.setText(userList.get(position).getUsername());
     94                 tv_sex.setText(userList.get(position).getSex());
     95                 return view;
     96             }
     97             
     98             @Override
     99             public Object getItem(int position) {
    100                 // TODO Auto-generated method stub
    101                 return null;
    102             }
    103 
    104             @Override
    105             public long getItemId(int position) {
    106                 // TODO Auto-generated method stub
    107                 return 0;
    108             }
    109         };
    110         lv = (ListView)findViewById(R.id.listView1);
    111         lv.setAdapter(adapter);
    112         
    113         handler = new Handler(){
    114             
    115             //1.消息msg来自于子线程
    116             //2.消息可以多个,采用msg.what识别
    117             //3.处理消息,一般就会更新UI
    118             //4.此方法可以参考onPostExecute
    119             @Override
    120             public void handleMessage(Message msg) {
    121                 
    122                 super.handleMessage(msg);
    123                 int msgwhat = msg.what;
    124                 Log.i("handler","已经收到消息,消息what:"+msgwhat+",id:"+Thread.currentThread().getId());
    125                 
    126                 if (msgwhat==1){
    127                     //更新helloworld
    128                     tv.setText("子线程让我更新"+msgwhat);
    129                 }
    130                 if (msgwhat==2){
    131                     //更新ListView
    132                     adapter.notifyDataSetChanged();
    133                 }
    134 
    135             }
    136             
    137         };
    138         
    139         //子线程代码1
    140         doInBackground1 = new Runnable() {
    141             
    142             @Override
    143             public void run() {
    144                 Log.i("sub_Thread","子线程1启动,id:"+Thread.currentThread().getId());
    145                 
    146                 try {
    147                     Thread.sleep(3000);
    148                 } catch (InterruptedException e) {
    149                     // TODO Auto-generated catch block
    150                     e.printStackTrace();
    151                 }
    152                 
    153                 //1.访问数据库或者互联网,不在UI进程,所以不卡
    154                 Message msg = new Message();
    155                 //对消息一个识别号,便于handler能够识别
    156                 msg.what = 1;
    157                 handler.sendMessage(msg);
    158                 Log.i("sub_Thread","子线程1已经发送消息给handler");
    159             }
    160         };
    161         
    162         
    163         
    164         //子线程代码1
    165         doInBackground2 = new Runnable() {
    166             
    167             @Override
    168             public void run() {
    169                 Log.i("sub_Thread","子线程2启动,id:"+Thread.currentThread().getId());
    170                 
    171                 try {
    172                     Thread.sleep(6000);
    173                 } catch (InterruptedException e) {
    174                     // TODO Auto-generated catch block
    175                     e.printStackTrace();
    176                 }
    177                 
    178                 Message msg = new Message();
    179                 //对消息一个识别号,便于handler能够识别
    180                 msg.what = 2;
    181                 //handler.sendMessage(msg);
    182                 handler.sendMessageDelayed(msg, 500);
    183 
    184                 
    185                 //访问互联网,下载最新的,更新data,但不碰界面
    186                 for (User user : userList) {
    187                     user.setSex("不男不女");
    188                 }
    189                 
    190                 Log.i("sub_Thread","子线程2已经发送消息给handler");
    191             }
    192         };
    193         
    194     }
    195 }
    196 
    197     

    效果图:

      点击button的时候如下图

    上面就是一个小例子;但是上面的代码写的还有很多需要改进的地方,详情请参考(此链接为转载):

    Android中使用Handler造成内存泄露的分析和解决http://www.linuxidc.com/Linux/2013-12/94065.htm

        

      

  • 相关阅读:
    SQL Server 2005 Integration Services (SSIS)数据源之MySQL
    SQL Server 2005 Integration Services (SSIS)数据源之Sybase
    oracle10g 监听服务无法启动
    创建一个People类型,有年龄、工资、性别三个属性。 定义一个方法叫做找对象,找对象方法传过来一个人;
    基于组件的C#农历算法
    ASP.NET中实现中文简/繁体自动转换的类
    最牛的QQ资料
    单一登陆(Single Signon)问题
    Smart Client Case Study Source Code Download from MSDN China
    简历制作 | 论文资源 | 考试认证 | 招聘求职 | 文学艺术 | 外语学习
  • 原文地址:https://www.cnblogs.com/mark0812/p/6136858.html
Copyright © 2020-2023  润新知