Android中的Can't create handler inside thread that has not called Looper.prepare()异常
博客《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(){ @Override public 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”的文件
第二种方法:像博客《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线程。
更多相关文章
- mybatisplus的坑 insert标签insert into select无参数问题的解决
- python起点网月票榜字体反爬案例
- 《Android开发从零开始》——25.数据存储(4)
- Android系统配置数据库注释(settings.db)
- Android中不同应用间实现SharedPreferences数据共享
- 浅析Android中的消息机制-解决:Only the original thread that cr
- Android异步消息机制之Handler
- Android的Handler机制详解3_Looper.looper()不会卡死主线程
- android图表ichartjs