zoukankan      html  css  js  c++  java
  • 学习通过Thread+Handler实现非UI线程更新UI组件

    Android线程机制】

       出于性能考虑,AndroidUI操作并不是线程安全的,这就意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的规则只允许UI线程修改Activity里的UI组件

       当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程

    Handler类简介】

      Handler类主要作用有两个:

      -->在新启动的线程发送消息

       -->在主线程中获取、处理消息

    【原理】

        为了让线程能“适时”地处理新启动的线程所发送的消息,显然只能通过回调的方法来实现---开发者只需要重写Handler类中的处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,Handler会不断地从MessageQueue中获取并处理消息-这将导致Handler类中的处理消息的方法被回调

    Handler类中用于发送和处理消息的方法 】

    . void handleMessage(Message msg):                                处理消息的方法。该方法通常用于被重写
    . final boolean hasMessages(int what):                                检查消息队列中是否包含what属性为指定值的消息
    . final boolean hasMessages(int what,Object object) :     检查消息队列中是否包含what属性为指定值 
                                                                                              的消息且object属性为指定对象的消息
    . 多个重载的Message obtainMessage():                            获取消息
    . sendEmptyMessage(int what):                                         发送空消息
    . final boolean sendEmptyMessageDelayed(int what,long delayMills):           指定多少秒后发送空消息
    . final boolean sendMessage(Message msg):                                               立即发送消息
    . final boolean sendMessageDelayed(Message msg,long delayMills):           指定多少秒后发送消息

     

    -----------------------------------------------------------------------------------------------------------------

    下面通过一个例子实现Android线程操作机制

    eg:通过点击按钮,来实现异步加载csdn的logo

    效果图:

    【代码】

    package cn.edu.bzu.asynchronous_processomg;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    /**
     * 学习通过Thread+Handler实现非UI线程更新UI组件
     * 学习异步加载的使用
     * @author monster
     *  date:2015-05-28
     *  introduce : Android只允许UI线程修改Activity里的UI组件
     *  Aim:点击按钮读取CSDN网站的LOGO
     */  
    public class MainActivity extends Activity {
       private Button mButton;
       private ImageView mImageView; 
       
       private final static int MSG_SUCCESS = 0; //获取图片成功的标识
       private final static int MSG_FAILURE = 1; //获取图片失败的标识
       
       private Thread mThread;
       
       private Handler mHandler=new Handler(){
           public void handleMessage(Message msg){  //此方法在UI线程中运行
               switch(msg.what){
                   case MSG_SUCCESS:
                       mImageView.setImageBitmap((Bitmap)msg.obj); //得到obj,并且强制类型转换成Bitmap类型--->>>obj含有图片的信息
                       Toast.makeText(getApplication(), "success", Toast.LENGTH_LONG).show();
                       break;    
                   case MSG_FAILURE:
                       Toast.makeText(getApplication(), "error", Toast.LENGTH_LONG).show();
                       break;
               }
           }
           
       };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //实例化控件的时候,如果为当前上下文的时候,则不需要写上下文
            mButton=(Button)findViewById(R.id.mButton);
            mImageView=(ImageView)findViewById(R.id.mImageView);
            
            mButton.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    if(mThread==null){
                        mThread=new Thread(runnable);
                        mThread.start();
                    }
                }
            });
        }
                Runnable runnable=new Runnable() {
                    
                    @Override
                    public void run() {
                         //run()在新的线程中运行 
                        HttpClient hc=new DefaultHttpClient();
                        HttpGet hg=new HttpGet("http://csdnimg.cn/www/images/csdnindex_logo.gif"); //csdn 的logo
                        final Bitmap bm;
                        try {
                            HttpResponse hr=hc.execute(hg); // 响应做出的请求
                            bm=BitmapFactory.decodeStream(hr.getEntity().getContent());
                        } catch (Exception e) {
                            mHandler.obtainMessage(MSG_FAILURE).sendToTarget();//获取图片失败
                            return ;
                        }
                        mHandler.obtainMessage(MSG_SUCCESS,bm).sendToTarget();//获取图片成功
                    }
                };
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
        
    }
    

    【总结】

       Handle在代码中为一个主线程,Runnable为一个新线程,新线程中通过请求响应的方法得到网站的logo,然后通过Handle消息传递机制进行传递从网站中读取的图片,这个图片为一个bitmap,是通过把文件流转换成bitmap,然后进行消息传递

    【链接分享】

       http://blog.csdn.net/mylzc/article/details/6736988

    【源代码下载地址】

      https://github.com/monsterLin/Asy_Processing

  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/boy1025/p/4537856.html
Copyright © 2011-2022 走看看