• Android使用Thread+Handler实现非UI线程更新界面 .


    每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,则会报错:

    CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views

    Android为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。对于运算量较大的操作和IO操作,我们需要新开线程来处理这些繁重的工作,以免阻塞ui线程。

     

    ThreadHandlerActivity.activity

    public class ThreadHandlerActivity extends Activity {
        /** Called when the activity is first created. */
        
        private static final int MSG_SUCCESS = 0;//获取图片成功的标识
        private static final int MSG_FAILURE = 1;//获取图片失败的标识
        
        private ImageView mImageView;
        private Button mButton;
        
        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);//imageview显示从网络获取到的logo
                    Toast.makeText(getApplication(), "成功!", Toast.LENGTH_LONG).show();
                    break;
    
                case MSG_FAILURE:
                    Toast.makeText(getApplication(), "失败!", Toast.LENGTH_LONG).show();
                    break;
                }
            }
        };
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.threadhandler);
            mImageView= (ImageView) findViewById(R.id.threadhandler_imageView);//显示图片的ImageView
            mButton = (Button) findViewById(R.id.threadhandler_download_btn);
            mButton.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    if(mThread == null) {
                        mThread = new Thread(runnable);
                        mThread.start();//线程启动
                    }
                    else {
                        Toast.makeText(ThreadHandlerActivity.this, "线程已启动!", Toast.LENGTH_LONG).show();
                    }
                }
            });
        }
        
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {//run()在新的线程中运行
                HttpClient hc = new DefaultHttpClient();
                HttpGet hg = new HttpGet("http://pic7.nipic.com/20100517/4945412_113951650422_2.jpg");//获取指南针图片
                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();//获取图片成功,向ui线程发送MSG_SUCCESS标识和bitmap对象
            }
        };
        
    }

     

    threadhandler.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="fill_parent"
     4     android:layout_height="fill_parent"
     5     android:orientation="vertical" >
     6 
     7     <Button
     8         android:id="@+id/threadhandler_download_btn"
     9         android:layout_width="wrap_content"
    10         android:layout_height="wrap_content"
    11         android:text="ThreadHandler下载" >
    12     </Button>
    13 
    14     <ImageView
    15         android:id="@+id/threadhandler_imageView"
    16         android:layout_width="wrap_content"
    17         android:layout_height="wrap_content" />
    18 
    19 </LinearLayout>

    运行结果:


     

     

     

    非UI线程发送消息到UI线程分为两个步骤

     

    一、发送消息到UI线程的消息队列

    通过使用Handler的

    Message obtainMessage(int what,Object object)

    构造一个Message对象,这个对象存储了是否成功获取图片的标识what和bitmap对象,然后通过message.sendToTarget()方法把这条message放到消息队列中去。
    二、处理发送到UI线程的消息
    在ui线程中,我们覆盖了handler的 
    public void handleMessage (Message msg) 
    这个方法是处理分发给ui线程的消息,判断msg.what的值可以知道mThread是否成功获取图片,如果图片成功获取,那么可以通过msg.obj获取到这个对象。
    最后,我们通过
    mImageView.setImageBitmap((Bitmap) msg.obj);
    设置ImageView的bitmap对象,完成UI的更新。

     

  • 相关阅读:
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Python位运算符
  • 原文地址:https://www.cnblogs.com/ggzjj/p/2856196.html
Copyright © 2020-2023  润新知