区块链技术博客
www.b2bchain.cn

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))的讲解

这篇文章主要介绍了Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))的讲解,通过具体代码讲解7468并且分析了Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))的讲解的详细步骤与相关技巧,需要的朋友可以参考下

本文实例讲述了Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))的讲解。分享给大家供大家参考文章查询地址https://www.b2bchain.cn/7468.html。具体如下:

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

  • 1.本讲必备操作
    • 1.准备所需代码
    • 2.学会Debug模式断点调试
      • 1.点击Debug模式 运行调试
      • 2.调试方法
        • 1.Step Over(程序执行下一行)
        • 2.Run to Cursor(跳到下一个断点)
      • 3.排查错误
  • 2.Handler机制
    • 1.线程问题分析
    • 2.解决方法-切到主线程
    • 3.Handler的使用方法
      • 1.通过sendEmptyMessage实现主线程方法回调(不带参数)
      • 2.通过sendMessage实现主线程方法回调(带参数)
    • 4.Handler的原理(重要)
      • 1.Handler原理 大概思路
      • 2.Handler原理 详细讲解
      • 3.Handler原理 图文解说
      • 4.Handler原理 视频讲解
    • 案例实战-倒计时 发送消息
    • 5.关于Handler总结

1.本讲必备操作

1.准备所需代码

导入前一讲已经分析过,且本讲需要用到的代码
添加权限

  	 <uses-permission android:name="android.permission.INTERNET"/>      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 

application节点下添加

	android:usesCleartextTraffic="true" 

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

activity.java代码

public class MainActivity extends AppCompatActivity {     TextView textView1;     TextView textView2;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         textView1 = findViewById(R.id.textView);         textView2 = findViewById(R.id.textView2); //怎么创建线程         Thread thread = new Thread() {//方法1             @Override             public void run() {                 super.run();                 try { // 子线程                     Log.i("MainActivity", "start"); //服务器的地址                     URL url = new URL("http://148.70.46.9/object3"); //和服务器建立连接                     HttpURLConnection httpURLConnection = (HttpURLConnection)                             url.openConnection(); //发送请求到服务器                     httpURLConnection.setRequestMethod("GET"); // 服务器返回的数据 字节流 byte 字符流 char 文本 // 输入流 从磁盘(网络)到内存 输出内存到磁盘                     InputStream inputStream = httpURLConnection.getInputStream(); //字节流                     Reader reader = new InputStreamReader(inputStream);// 字符流                     BufferedReader bufferedReader = new BufferedReader(reader); //缓存流                     String result = "";                     String temp;                     while ((temp = bufferedReader.readLine()) != null) {                         result += temp;                     }                     Log.i("MainActivity", "result:" + result); // { "grade":"18级","classname":"中医学","students":["张三","李四","王五"] }                     JSONObject jsonObject = new JSONObject(result);                     final String grade = jsonObject.getString("grade");                     final String classname = jsonObject.getString("classname");                     Log.i("MainActivity", "grade:" + grade + " classname :" + classname);                     JSONArray jsonArray = jsonObject.getJSONArray("students");                     for (int i = 0; i < jsonArray.length(); i++) {                         JSONObject jsonObject1 = jsonArray.getJSONObject(i);                         String id = jsonObject1.getString("id");                         int age = jsonObject1.getInt("age");                         String name = jsonObject1.getString("name");                         Log.i("MainActivity", "id:" + id + " age:" + age + " name :" + name);                     } // ViewRootImpl$CalledFromWrongThreadException 在一个错误的线程中 // 子线程 -网络访问只能在子线程 // ui操作 文本设置值 点击事件 有时候会问题 有时候不会有问题 -不能子线程 // 切到主线程                     runOnUiThread(new Runnable() {                          @Override                         public void run() { // 主线程                             textView1.setText("年级:" + grade);                             textView2.setText("班级:" + classname);                         }                     });                 } catch (Exception e) {                     e.printStackTrace();                 }             }         };         thread.start();     } } 

xml代码

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity">     <TextView         android:id="@+id/textView"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginTop="88dp"         app:layout_constraintStart_toStartOf="parent"         app:layout_constraintTop_toTopOf="parent"         android:layout_marginLeft="110dp" />     <TextView         android:id="@+id/textView2"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginTop="27dp"         app:layout_constraintStart_toStartOf="@+id/textView"         app:layout_constraintTop_toBottomOf="@+id/textView" /> </androidx.constraintlayout.widget.ConstraintLayout> 

运行结果
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

2.学会Debug模式断点调试

断点调试详细介绍推荐博客

1.点击Debug模式 运行调试

第一步,加断点(在开始和排查过程中都可以添加断点)
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

第二步,点击按钮运行调试(Debug模式)
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
模拟器会出现这样一个弹框(我们不用管)
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
来,一起操作吧
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

2.调试方法

视图介绍

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
这里主要介绍两个按钮功能

  1. Step Over
  2. Run to Cursor

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

1.Step Over(程序执行下一行)

功能:单步跳过,点击该按钮表示程序将执行下一行,如果该行是一句代码直接执行到下一行, 如果该行是一个方法,不会进入该方法,直接执行到下一行。

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

2.Run to Cursor(跳到下一个断点)

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

3.排查错误

我们在这行代码key中加3个问号,使key与服务器的不对应,模拟错误

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
我们点击Step Over按钮,会发现程序执行到这一行,就跳到异常处理了
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
并且报错,我们找到刚才跳到异常的那一行代码,并且结合报错原因,便可得知错误所在
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

最后讲下为什么我们要学习断点调试,因为当我们找不到错误所在时,通过断点调试可以帮助我们查看程序运行期间每一步各变量的值,断点调试的方法可以帮助我们加快排查错误的速度,提高我们的工作效率,是一名合格程序员必备的技能

2.Handler机制

1.线程问题分析

问题分析:在子线程中UI操作出现问题
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
再次运行,有时候会抛出这样一个异常(有时候会有问题 有时候不会有问题 带有一定的随机性)
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
// ViewRootImpl$CalledFromWrongThreadException 表示在一个错误的线程中
// 网络访问只能在子线程
// ui操作 (对于控件的操作-例如文本设置值 点击事件)-不能放在子线程
// 解决方法就是把ui操作放到主线程

耗时操作要放到子线程里面(例如网络访问),UI操作要放到主线程(例如文本设置)

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

那么问题来了,UI操作要放到主线程,不能放到子线程,按道理来说,UI操作放到子线程一定有问题,为什么结果却是有时候会有问题,有时候不会呢?
首先,我们来看一个方法,按住shift+ctrl+r 搜索这个文件
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
找到这个方法
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
这个方法实际实际上就是帮我们检查线程的,但是这个方法是在OnResume()方法中调用的,所以当这个checkThread()检查线程的方法没有执行的时候,ui操作放到子线程就不会有问题,相反,就会出问题

就比方:
有时候网络请求耗时很长,调用ui操作的代码还没有执行,而检查线程的方法执行了,然后再执行调用ui操作的代码,ui操作放到子线程就会检查出有问题,
有时候网络请求花的时间很短,调用ui操作的代码已经执行了,但是检查线程的方法还没有执行,所以也就ui操作放到子线程就没有检查出有问题

所以我们不要抱着侥幸的心态,养成一个好习惯,把UI操作放到主线程,把耗时操作放到子线程

2.解决方法-切到主线程

方法一.我们之前讲到的直接写一个runOnUiThread方法来创建主线程,

 runOnUiThread(new Runnable() {                         @Override                         public void run() {                          //对ui的操作 只能放到主线程                             try {                                                              }catch (Exception e){                                                              }                         }                     });`  

实际上这个runOnUiThread方法也是Handler的机制
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

方法二-用Handler来切到主线程

3.Handler的使用方法

第一步.创建Handler类
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

  Handler mHandler=new Handler(){         @Override         public void handleMessage(@NonNull Message msg) {//重写handleMessage方法             super.handleMessage(msg);         }     }; 

1.通过sendEmptyMessage实现主线程方法回调(不带参数)

把之前的创建的主线程代码注释,把对文本赋值的操作粘贴到handleMessage方法中,
并在子线程加一句代码

                    mHandler.sendEmptyMessage(1);  

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
我们这里不带参数运行
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
代码

  Handler mHandler=new Handler(){         @Override         public void handleMessage(@NonNull Message msg) {//重写handleMessage方法             super.handleMessage(msg);             textView1.setText("年级:" );             textView2.setText("班级:" );         }     }; 

运行
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
如果去掉 mHandler.sendEmptyMessage(1); 不发消息通知的话
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

所以,也就是说
mHandler.sendEmptyMessage(1);在子线程中执行,主线程的handleMessage就会回调,我们也就可以肯定handleMessage方法中的代码一定会在主线程中执行,

所以这个mHandler.sendEmptyMessage(1);的目的是,在子线程中发送消息去通知主线程来进行UI操作

2.通过sendMessage实现主线程方法回调(带参数)

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
代码

                     Message message=new Message();                     message.what=1;                      Bundle bundle=new Bundle();                     bundle.putString("grade",grade);//把所需要传的值放入这个 Bundle 当中                     bundle.putString("classname",classname);                     message.setData(bundle);//再把 bundle 放到message当中                      mHandler.sendMessage(message); 

再回到handleMessage方法接收消息,结果运行成功
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
代码

 Handler mHandler=new Handler(){         @Override         public void handleMessage(@NonNull Message msg) {//重写handleMessage方法             super.handleMessage(msg);            String grade= msg.getData().getString("grade");             String classname= msg.getData().getString("classname");             textView1.setText("年级:"+ grade);             textView2.setText("班级:" +classname);         }     }; 

4.Handler的原理(重要)

1.Handler原理 大概思路

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

2.Handler原理 详细讲解

  1. 首先,我们要搞清楚一个概念,在线程里面,有一个这样的结论,就是在不同线程之间,变量是可以相互共享的,不同的线程可以拿到同一个变量的引用
    Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

2.小伙伴都知道,我们刚才分析的 Handler 是在主线程里面创建的,小伙伴注意,activity里面所有的成员变量,包括OnCreate方法里面的定义的变量都是在主线程,所以也就是说我们创建的 Handler 是在主线程的,在主线程里面可以用 Handler 进行各种操作,但是我们在子线程里面也用到了 Handler,再次证明了线程间 变量的引用是可以相互共享的结论
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
.因为我们创建了一个 Handler ,那么实际上 主线程和子线程是都可以拿到这个Handler 的引用,因为他就是在主线程里面创建的,那么子线程也可以对它进行操作

3.那我们在子线程对Handler 进行了一个什么操作呢?我们可以看到,我们实际上调用了一个方法-sendMessage方法,我们还创建了一个Message对象,这个Message对象里面有很多数据,比如说我们创建的这个Bundle类,可以帮助我们传递消息,还有一个what整型变量,也就是说这个 Message我们可以把他看成一个实体类,里面可以传递很多数据
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

5.当子线程调用sendMessage方法后,这个Message对象就被加到主线程里面去,加到一个叫MessageQueue里面去,MessageQueue是一个Message队列,MessageQueue里面会保存很多的Message ,所以每次发送一个Message到MessageQueue,就会把这个Message放到队列的队尾
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

6.我们知道队列知识一种数据结构,它里面的代码不会去执行,那么这个队列的代码是怎么样去执行的呢?实际上在主线程里面还有一个角色-Looper,
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
这里有一个loop()方法,然后在通过死循环先把队列中队首取出来,遵循先进先出的原则,
然后再一个一个取出Message,如果Message取完了,这个死循环就会在这里一直等着,来一个取一个
,为什么需要一个队列来存Message呢,因为如果某个时候有很多个UI操作同时进行,如果不是一个队列的话,那我们的应用程序就会卡死,因为执行不过来,如果是一个队列的话,就算有很多UI操作,我们的队列可以一个一个执行,就不会导致我们的应用程序界面被卡死
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

7.我们将这个Message取出来还进行了什么操作呢,再往下看Looper代码
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
也就是说,Message取出来以后,会去调用Handler的dispatchMessage方法,我们可以看到,Handler是有这个方法的
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
我们来看一下这个方法执行了什么操作
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
我们可以发现这里的dispatchMessage方法调用了handleMessage方法,所以也就相当于回调了handleMessage方法
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

3.Handler原理 图文解说

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

4.Handler原理 视频讲解

博主原声讲解-Handler原理(多多关照哈哈)

Handler不仅可以实现主线程和子线程的切换,也可以实现子线程与子线程之间的切换

案例实战-倒计时 发送消息

常见应用:例如 点击验证码发送以后需要间隔60秒才能再次发送

第一步,在xml文件当中添加一个按钮控件
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
第二步,把Button定义为全局变量 ,并且实例化Button,并且添加点击事件,然后再定义一个变量

Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
第三步,子线程发送消息,然后主线通过判断time,再每延时1秒发送一次消息
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

第四步,记得注释原来子线程 发送的消息
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
运行
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))

5.关于Handler总结

1. Handler主要用来实现线程和线程之间的数据交互
2. CalledOnWrongThreadException异常都用Handler 来解决

小伙伴们,今天的内容就讲到这里啦,已经凌晨两点了,再动用了超级多的工具以后,终于把这篇博客写完了,还给你们录了个视频,讲的不好,多多指教,我会继续努力,谢谢您的阅读,晚安,玛卡巴卡。
Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))
Andrioid 入门第六讲04-网络请求第三方框架-xUtils(原生HTTP网络访问的缺点,xUtils简介,使用方法(网络请求访问,注解(布局文件+控件+点击事件)加载网络图片))

本文地址https://www.b2bchain.cn/7468.html

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Android 入门第六讲03-Handler(学会Debug模式断点调试,Handler机制(线程问题分析,Handler的使用方法),Handler的原理(超详细))的讲解
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们