博客《Android客户端和服务器端数据交互的第三种方法》中Android手机客户端代码1曾经提到“第41行和第61行不可缺少,否则会出现java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()异常”,呵呵呵,难道将"第41行和第61行"代码注销掉以后真的会出现这个异常?嗯嗯嗯,这是一个事实,可是如果把"第41行和第61行"代码注销掉并且把“第50行”代码改为“System.out.println(EntityUtils.toString(httpResponse.getEntity()));”,这时再次运行Android客户端就会发现程序没有任何问题,为什么会这样?很简单,一句话Android中不能在子线程中刷新UI线程。那么问题来了,如果需要在子线程中刷新UI线程怎么办?有如下两种方法:

第一种方法:像博客《Android客户端和服务器端数据交互的第三种方法》中说的那样添加"第41行和第61行"代码;

第二种方法提到了Looper类,那么怎么理解这个类呢?

Looper类用来为一个子线程开启一个消息循环。默认情况下Android中新诞生的非主线程没有开启消息循环(主线程诞生时系统会自动为其创建开启消息循环的Looper对象),所以在非主线程中直接new Handler()会报“java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()”异常,需要先调用Looper.prepare()启用Looper,然后通过调用Looper.loop()让Looper开始工作,如下代码:

代码1:名为“AndroidActivity.java”的文件

package com.example.androidclient;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;public class AndroidActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.android);Button sendButton = (Button) findViewById(R.id.button);sendButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {new Thread(new Runnable(){@Overridepublic void run() {Looper.prepare();Message message = new Message();  Bundle bundle = new Bundle();Handler handler = new Handler(){  @Override  public void handleMessage(Message message) {  super.handleMessage(message);  Bundle bundle = message.getData();  String msg = bundle.getString("msg");  Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();  }  };bundle.putString("msg", "你好!!!");message.setData(bundle);  handler.sendMessage(message);Looper.loop();}}).start();}});}
}

代码2:名为“android.xml”的文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_centerVertical="true"android:text="@string/hello" /></RelativeLayout>

第二种方法:像博客《Android客户端和服务器端数据交互的第二种方法》中做的那样在子线程中添加Handler来发送消息更新UI线程。

第二种方法提到了HandlerHandler,可是怎样理解它呢?

Handler主要用于接收子线程发送的数据并用此数据配合主线程更新UI线程. 
        解释: 当Android应用程序启动时,它首先会开启一个主线程 (也就是UI线程), 主线程为管理界面中的UI控件,进行事件分发, 比如说, 点击一个Button, Android会将事件分发到该Button上来响应操作。如果点击按钮后需要一个耗时的操作(比如联网读取数据或者读取本地较大的一个文件),你不能把这些操作放在主线程中,放在主线程界面会出现假死现象, 如果5秒钟还没有完成,则会收到Android系统的一个错误提示"强制关闭",这个时候我们需要把这些耗时的操作放在一个子线程中,又因为子线程涉及到UI更新,而Android主线程不安全的,所以只能在主线程中更新UI线程,子线程中操作是危险的。这种情况下,Handler的出现解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接收子线程传过来的(子线程用sedMessage()方法传弟)Message对象(该对象携带者子线程传入的数据)并把这些数据放入主线程队列中以配合主线程更新UI线程。

Android中的Can't create handler inside thread that has not called Looper.prepare()异常相关推荐

  1. Can't create handler inside thread that has not called Looper.prepare()

    问题: Can't create handler inside thread that has not called Looper.prepare() 1,在报错的方法前加Looper.prepare ...

  2. java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() ...

  3. Can't create handler inside thread that has not called Looper.prepare() 解决办法

    在开发的过程当中,遇到了想在一个线程中弹出一个提示窗 new AlertDialog.Builder(            context),但是就出现了一个问题. java.lang.Runtim ...

  4. Android --- java.lang.RuntimeException: Can‘t create handler inside thread that has not called Loop

    报错信息如下: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.pr ...

  5. java.lang.RuntimeException: Can't create handler inside thread that has not

    在子线程中 调用了这句: Toast.makeText(UiUtils.getContext(), "正在下载"+name, Toast.LENGTH_SHORT).show(); ...

  6. Can't create handler inside thread Thread that has not called Looper.prepare()

    今天在子线程里面写了一个Toast 运行程序直接崩溃了 看了下log 如下 最后忽然想到了子线程里面不能直接使用Toast 然后 就添加了 Looper.prepare(); 和 Looper.loo ...

  7. Android在子线程里使用Toast报错Can't toast on a thread that has not called Looper.prepare()

    在接android SDK的时候有时候为了方便debug调试查看,通过Toast输出相关信息, 实际上这个是在子线程中输出的,在logcat里查看有如下报错java.lang.RuntimeExcep ...

  8. Android中的消息机制:Handler消息传递机制

    参考<疯狂android讲义>第2版3.5 P214 一.背景 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为 ...

  9. Android中ProgressBar的使用-通过Handler与Message实现进度条显示

    场景 进度条效果 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改为 ...

  10. 浅谈Android中的Handler机制

    Handler是Android中提供的一种异步回调机制,也可以理解为线程间的消息机制.为了避免ANR,我们通常会把一些耗时操作(比如:网络请求.I/O操作.复杂计算等)放到子线程中去执行,而当子线程需 ...

最新文章

  1. 关于MSSQL导入导出时主键与约束丢失的问题解决
  2. DOM中window的navigate()重新导航到制定网址
  3. Lync Server 2010 语音质量
  4. Apache负载均衡设置方法: mod_proxy
  5. ai人工智能的本质和未来_人工智能的未来在于模型压缩
  6. springboot 订单重复提交_瞬间几千次的重复提交,我用Spring Boot+Redis扛住了
  7. 如何用手机打开dcm格式图片_实现原始Dicom自动转换BIDS格式 ——Heudiconv
  8. 吴恩达机器学习ex8:推荐系统
  9. request.getInputStream中文乱码解决方案
  10. BLE - LINK LAYER SPECIFICATION
  11. 深度学习自学(四):NCNN配置openmp-CMAKELIST
  12. Windows XP启用telnet服务图文教程
  13. 农村三资管理平台app_农村三资管理系统功能
  14. 银联刷卡POS机冲正
  15. 技术解密之百度搜索中台低代码的探索与实践
  16. Base64系列第一篇 Base64介绍
  17. angular7中使用ckplayer插件实现各大浏览器视频播放功能
  18. DS1302 中文资料+代码 单片机制作时钟
  19. 大数据分析案例:应用系统负载分析与磁盘容量预测
  20. mysql网页设计资源_分享25个很棒的网页设计教程和资源网站

热门文章

  1. pycharm 中Python 模板的自动生成
  2. 自动手动安装CDH5
  3. Bzoj1070 [SCOI2007]修车
  4. QLineEdit使用正则表达式小剖析
  5. 今天看C++Primer发现的问题
  6. JSP 内置对象request常见用法
  7. 6.性能之巅 洞悉系统、企业与云计算 --- CPU
  8. 15.企业应用架构模式 --- 分布模式
  9. 27.Yii App应用
  10. 8. 大型网站架构演化