zoukankan      html  css  js  c++  java
  • Handler简述和实例

    Handler

    1、简介:

    Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI的。所以就有了handler,它的作用就是实现线程之间的通信。 handler整个流程中,主要有四个对象,handler,Message,MessageQueue,Looper。当应用创建的时候,就会在主线程中创建handler对象, 我们通过要传送的消息保存到Message中,handler。post,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop()方法 不断的从MessageQueue中取出Message交给handler进行处理。从而实现线程之间的通信。

    2、Looper、MessageQueue、Message、Handler的关系

    Looper:

    每一个线程只有一个Looper,每个线程在初始化Looper之后,然后Looper会维护好该线程的消息队列,用来存放Handler发送的Message,并处理消息队列出队的Message。它的特点是它跟它的线程是绑定的,处理消息也是在Looper所在的线程去处理,所以当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。

    在主线程中,ActivityThread默认会把Looper初始化好,prepare以后,当前线程就会变成一个Looper线程。

    MessageQueue:

    MessageQueue是一个消息队列,用来存放Handler发送的消息。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。

    Message:

    消息对象,就是MessageQueue里面存放的对象,一个MessageQueu可以包括多个Message。当我们需要发送一个Message时,我们一般不建议使用new Message()的形式来创建,更推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。

    Handler的主要用途

    1. 推送未来某个时间点将要执行的Message或者Runnable到消息队列。

    2. 在子线程把需要在另一个线程执行的操作加入到消息队列中去。

    实例一:通过Handler配合Message或者Runnable实现倒计时

    public class MainActivity extends AppCompatActivity {
       private static final int UPDATE = 0x1;
       private TextView mTv;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           mTv = findViewById(R.id.tv);
           begin();
      }

       private Handler mHandler = new Handler(){
           @Override
           public void handleMessage(@NonNull Message msg) {
               switch (msg.what){
                   case UPDATE:
                       mTv.setText(String.valueOf(msg.arg1));
                       break;
              }
          }
      };

       public void begin(){
           new Thread(new Runnable() {
               @Override
               public void run() {
                   for (int i=5;i>0;i--){
                       Message msg = new Message();
                       msg.what = UPDATE;
                       msg.arg1 = i;
                       mHandler.sendMessage(msg);
                       try {
                           Thread.sleep(1000);
                      }catch (InterruptedException e){
                           e.printStackTrace();
                      }
                       Log.d("xxxxx", "run: ");
                  }
                   startActivity(new Intent(MainActivity.this,Main2Activity.class));
                   finish();
              }
          }).start();
      }

       @Override
       protected void onDestroy() {
           super.onDestroy();
           Log.d("xxxxx", "onDestroy: ");
      }
      }

    实列二:在子线程把需要在另一个线程执行的操作加入到消息队列中去

    import androidx.appcompat.app.AppCompatActivity;

    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.Toast;

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.ProtocolException;
    import java.net.URL;

    public class Main2Activity extends AppCompatActivity implements View.OnClickListener {
       private Button mLoad;
       private Button mReset;
       private ImageView mImageView;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main2);

           mLoad = findViewById(R.id.load);
           mLoad.setOnClickListener(this);
           mReset = findViewById(R.id.reset);
           mReset.setOnClickListener(this);
           mImageView = findViewById(R.id.img_show);
      }

       public Bitmap loadPic(){
           Bitmap bitmap = null;
           int respondCode = 0;
           InputStream inputStream = null;
           try {
               URL url = new URL("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1421494343,3838991329&fm=23&gp=0.jpg");
               HttpURLConnection connection = (HttpURLConnection) url.openConnection();
               connection.setRequestMethod("GET");
               connection.setConnectTimeout(10*1000);
               connection.setReadTimeout(5*1000);
               connection.connect();
               respondCode = connection.getResponseCode();
               if (respondCode == 200){
                   inputStream = connection.getInputStream();
                   bitmap = BitmapFactory.decodeStream(inputStream);
              }
          }catch (MalformedURLException e){
               e.printStackTrace();
               Toast.makeText(this,"访问失败",Toast.LENGTH_SHORT).show();
          } catch (ProtocolException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          } finally {
               if (inputStream != null){
                   try {
                       inputStream.close();
                  }catch (IOException e){
                       e.printStackTrace();
                  }
              }
          }
           return bitmap;
      }

       @Override
       public void onClick(View v) {
           int i = v.getId();
           switch (i){
               case R.id.load:
                   new Thread(new Runnable() {
                       @Override
                       public void run() {
                           final Bitmap bitmap = loadPic();
                           Handler handler = new Handler(Looper.getMainLooper());
                           handler.post(new Runnable() {
                               @Override
                               public void run() {
                                   mImageView.setImageBitmap(bitmap);
                              }
                          });
                      }
                  }).start();
                   break;
               case R.id.reset:
                   mImageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_foreground));
                   break;
          }
      }
    }

    注意:记得添加网络权限!

  • 相关阅读:
    前端学习之路,前端开发人员如何在团队中规范git commit提交记录
    基于AntV图表库的Ant DeSign Charts图表展示的简单应用
    基于React-Amap组件库的高德地图简单应用
    高效的Coding,前端开发人员值得一看的前端开发工具
    解决git pull拉取更新代码失败,unable to resolve reference ‘refs/remotes/origin/xxx分支名’: reference broken问题
    position: sticky实现导航栏下滑吸顶效果
    javaScript保留三位有效数字
    封装属于自己的axios请求
    微博立场检测 60分Baseline
    Sequence to Sequence Learning with Neural Networks论文阅读
  • 原文地址:https://www.cnblogs.com/littleboy123/p/13036264.html
Copyright © 2011-2022 走看看