使用android studio导入so 怎么没有办法导入android.os.handler这个包

Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等 - 山岭巨人 - 博客园
方法一:(java习惯,在android不推荐使用)
刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题
new Thread( new Runnable() {
public void run() {
myView.invalidate();
}).start();
可以实现功能,刷新UI界面。但是这样是不行的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
方法二:(Thread+Handler)
查阅了文档和apidemo后,发觉常用的方法是利用Handler来实现UI线程的更新的。
Handler来根据接收的消息,处理UI更新。Thread线程发出Handler消息,通知更新UI。
Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case TestHandler.GUIUPDATEIDENTIFIER:
myBounceView.invalidate();
super.handleMessage(msg);
class myThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
以上方法demo看:
方法三:(java习惯,不推荐)
在Android平台中需要反复按周期执行方法可以使用Java上自带的TimerTask类,TimerTask相对于Thread来说对于资源消耗的更低,除了使用Android自带的AlarmManager使用Timer定时器是一种更好的解决方法。 我们需要引入import java.util.T 和 import java.util.TimerT
public class JavaTimer extends Activity {
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run() {
setTitle("hear me?");
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timer.schedule(task, 10000);
方法四:(TimerTask + Handler)
实际上这样做是不行的,这跟Android的线程安全有关!应该通过配合Handler来实现timer功能的!
public class TestTimer extends Activity {
Timer timer = new Timer();
Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
setTitle("hear me?");
super.handleMessage(msg);
TimerTask task = new TimerTask(){
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timer.schedule(task, 10000);
方法五:( Runnable + Handler.postDelayed(runnable,time)&)
在Android里定时更新 UI,通常使用的是&java.util.Timer,&java.util.TimerTask, android.os.Handler组合。实际上Handler 自身已经提供了定时的功能。&
private Handler handler = new Handler();
private Runnable myRunnable= new Runnable() {
public void run() {
if (run) {
handler.postDelayed(this, 1000);
tvCounter.setText("Count: " + count);
然后在其他地方调用
handler.post(myRunnable);
handler.post(myRunnable,time);
====================================================================
知识点总结补充:
& &很多初入Android或Java开发的新手对Thread、Looper、Handler和Message仍然比较迷惑,衍生的有HandlerThread、java.util.concurrent、Task、AsyncTask由于目前市面上的书籍等资料都没有谈到这些问题,今天就这一问题做更系统性的总结。我们创建的Service、Activity以及Broadcast均是一个主线程处理,这里我们可以理解为UI线程。但是在操作一些耗时操作时,比如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑使用Thread线程来解决。
& &对于从事过J2ME开发的程序员来说Thread比较简单,直接匿名创建重写run方法,调用start方法执行即可。或者从Runnable接口继承,但对于Android平台来说UI控件都没有设计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,这点Google在设计Android时倒是参考了下Win32的消息处理机制。
&1. 对于线程中的刷新一个View为基类的界面,可以使用postInvalidate()方法在线程中来处理,其中还提供了一些重写方法比如postInvalidate(int left,int top,int right,int bottom) 来刷新一个矩形区域,以及延时执行,比如postInvalidateDelayed(long delayMilliseconds)或postInvalidateDelayed(long delayMilliseconds,int left,int top,int right,int bottom) 方法,其中第一个参数为毫秒
&2. 当然推荐的方法是通过一个Handler来处理这些,可以在一个线程的run方法中调用handler对象的 postMessage或sendMessage方法来实现,Android程序内部维护着一个消息队列,会轮训处理这些,如果你是Win32程序员可以很好理解这些消息处理,不过相对于Android来说没有提供 PreTranslateMessage这些干涉内部的方法。
3. Looper又是什么呢? ,其实Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列,但是Looper和Handler没有什么关系,我们从开源的代码可以看到Android还提供了一个Thread继承类HanderThread可以帮助我们处理,在HandlerThread对象中可以通过getLooper方法获取一个Looper对象控制句柄,我们可以将其这个Looper对象映射到一个Handler中去来实现一个线程同步机制,Looper对象的执行需要初始化Looper.prepare方法就是昨天我们看到的问题,同时推出时还要释放资源,使用Looper.release方法。
4.Message 在Android是什么呢? 对于Android中Handler可以传递一些内容,通过Bundle对象可以封装String、Integer以及Blob二进制对象,我们通过在线程中使用Handler对象的sendEmptyMessage或sendMessage方法来传递一个Bundle对象到Handler处理器。对于Handler类提供了重写方法handleMessage(Message msg)&来判断,通过msg.what来区分每条信息。将Bundle解包来实现Handler类更新UI线程中的内容实现控件的刷新操作。相关的Handler对象有关消息发送sendXXXX相关方法如下,同时还有postXXXX相关方法,这些和Win32中的道理基本一致,一个为发送后直接返回,一个为处理后才返回 .
5. java.util.concurrent对象分析,对于过去从事Java开发的程序员不会对Concurrent对象感到陌生吧,他是JDK 1.5以后新增的重要特性作为掌上设备,我们不提倡使用该类,考虑到Android为我们已经设计好的Task机制,这里不做过多的赘述,相关原因参考下面的介绍:
6. 在Android中还提供了一种有别于线程的处理方式,就是Task以及AsyncTask,从开源代码中可以看到是针对Concurrent的封装,开发人员可以方便的处理这些异步任务。java android使用自定义UncaughtExceptionHandler 处理程序崩溃 - 为程序员服务
为程序员服务
android使用自定义UncaughtExceptionHandler 处理程序崩溃
[Java]代码
import java.io.F
import java.io.FileOutputS
import java.io.FilenameF
import java.io.PrintW
import java.io.StringW
import java.io.W
import java.lang.Thread.UncaughtExceptionH
import java.lang.reflect.F
import java.util.A
import java.util.P
import java.util.TreeS
import android.content.C
import android.content.pm.PackageI
import android.content.pm.PackageM
import android.content.pm.PackageManager.NameNotFoundE
import android.os.B
import android.os.L
import android.util.L
import android.widget.T
* UncaughtException处理类,当程序发生Uncaught异常的时候,有该类 来接管程序,并记录 发送错误报告.. 註冊方式
* CrashHandler crashHandler = CrashHandler.getInstance(); //注册crashHandler
* crashHandler.init(getApplicationContext()); //发送以前没发送的报告(可选)
* crashHandler.sendPreviousReportsToServer();
public class CrashHandler implements UncaughtExceptionHandler {
/** Debug Log tag */
public static final String TAG = &CrashHandler&;
* 是否开启日志输出,在Debug状态下开启, 在Release状态下关闭以提示程序性能
public static final boolean DEBUG =
/** 系统默认的UncaughtException处理类 */
private Thread.UncaughtExceptionHandler mDefaultH
/** CrashHandler实例 */
private static CrashHandler INSTANCE;
/** 程序的Context对象 */
private Context mC
/** 使用Properties来保存设备的信息和错误堆栈信息 */
private Properties mDeviceCrashInfo = new Properties();
private static final String VERSION_NAME = &versionName&;
private static final String VERSION_CODE = &versionCode&;
private static final String STACK_TRACE = &STACK_TRACE&;
/** 错误报告文件的扩展名 */
private static final String CRASH_REPORTER_EXTENSION = &.cr&;
/** 保证只有一个CrashHandler实例 */
private CrashHandler() {
/** 获取CrashHandler实例 ,单例模式 */
public static CrashHandler getInstance() {
if (INSTANCE == null) {
INSTANCE = new CrashHandler();
return INSTANCE;
* 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器
* @param ctx
public void init(Context ctx) {
mContext =
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
* 当UncaughtException发生时会转入该函数来处理
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
// Sleep一会后结束程序
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, &Error : &, e);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
* @param ex
* @return true:如果处理了该异常信息;否则返回false
private boolean handleException(Throwable ex) {
if (ex == null) {
final String msg = ex.getLocalizedMessage();
// 使用Toast来显示异常信息
new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(mContext, &程序出错啦:& + msg, Toast.LENGTH_LONG)
Looper.loop();
}.start();
// 收集设备信息
collectCrashDeviceInfo(mContext);
// 保存错误报告文件
String crashFileName = saveCrashInfoToFile(ex);
// 发送错误报告到服务器
sendCrashReportsToServer(mContext);
* 在程序启动时候, 可以调用该函数来发送以前没有发送的报告
public void sendPreviousReportsToServer() {
sendCrashReportsToServer(mContext);
* 把错误报告发送给服务器,包含新产生的和以前没发送的.
* @param ctx
private void sendCrashReportsToServer(Context ctx) {
String[] crFiles = getCrashReportFiles(ctx);
if (crFiles != null && crFiles.length & 0) {
TreeSet&String& sortedFiles = new TreeSet&String&();
sortedFiles.addAll(Arrays.asList(crFiles));
for (String fileName : sortedFiles) {
File cr = new File(ctx.getFilesDir(), fileName);
postReport(cr);
cr.delete();// 删除已发送的报告
private void postReport(File file) {
// TODO 使用HTTP Post 发送错误报告到服务器
// 这里不再详述,开发者可以根据OPhoneSDN上的其他网络操作
// 教程来提交错误报告
* 获取错误报告文件名
* @param ctx
private String[] getCrashReportFiles(Context ctx) {
File filesDir = ctx.getFilesDir();
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(CRASH_REPORTER_EXTENSION);
return filesDir.list(filter);
* 保存错误信息到文件中
* @param ex
private String saveCrashInfoToFile(Throwable ex) {
Writer info = new StringWriter();
PrintWriter printWriter = new PrintWriter(info);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
String result = info.toString();
printWriter.close();
mDeviceCrashInfo.put(STACK_TRACE, result);
String fileName = &&;
long timestamp = System.currentTimeMillis();
fileName = &crash-& + timestamp + CRASH_REPORTER_EXTENSION;
FileOutputStream trace = mContext.openFileOutput(fileName,
Context.MODE_PRIVATE);
mDeviceCrashInfo.store(trace, &&);
trace.flush();
trace.close();
return fileN
} catch (Exception e) {
Log.e(TAG, &an error occured while writing report file...&
+ fileName, e);
* 收集程序崩溃的设备信息
* @param ctx
public void collectCrashDeviceInfo(Context ctx) {
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
mDeviceCrashInfo.put(VERSION_NAME,
pi.versionName == null ? &not set& : pi.versionName);
mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
} catch (NameNotFoundException e) {
Log.e(TAG, &Error while collect package info&, e);
// 使用反射来收集设备信息.在Build类中包含各种设备信息,
// 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
// 具体信息请参考后面的截图
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
mDeviceCrashInfo.put(field.getName(), field.get(null));
if (DEBUG) {
Log.d(TAG, field.getName() + & : & + field.get(null));
} catch (Exception e) {
Log.e(TAG, &Error while collect crash info&, e);
您可能的代码
相关聚客文章
相关专栏文章android Handler的使用(一) - 低级写手 我自由了 - ITeye技术网站
博客分类:
Handler的使用(一)
Handler基本概念:
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发送消息和接收消息不是同步的处理。
这种机制通常用来处理相对耗时比较长的操作。
使用一个例子简单的来介绍一下Handler。
示例1:一个应用程序中有2个按钮(start、end),当点击start按钮时,执行一个线程,这个线程在控制台输出一串字符串,并且每隔3秒再执行一次线程,直到点击end按钮为止,线程停止。
下图为这个应用程序的界面:
下图为执行程序时控制台的输出:
开发步骤:
1、 新建一个Android应用程序
2、 在布局文件中添加2个Button控件标签,并为其设置属性和值
3、 在Activity中,声明控件变量并根据id获得控件对象
4、 在Activity中,创建一个Handler对象
5、 在Activity中,创建一个Runnable对象
a) 以匿名内部类的方式
b) 将要执行的操作写在Runnable对象中的run()方法中
i. 打印出一句话
ii. 调用Runnable对象的postDelayed()方法
6、 在Activity中,编写start按钮需要的监听器,并绑定
a) 在这个监听器的Onclick()方法中,调用Handler的post()方法,将要执行的线程对象放到队列当中。
7、 在Activity中,编写end按钮需要的监听器,并帮定
a) 在这个监听器的Onclick()方法中,调用Handler的removeCallbacks ()方法,删除队列当中未执行的线程对象。
b)
下面是Activity的代码:
package android.
import android.app.A
import android.os.B
import android.os.H
import android.view.V
import android.view.View.OnClickL
import android.widget.B
public class HandlerTest extends Activity {
/** Called when the activity is first created. */
private Button startB
private Button endB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//根据id获得控件对象
startButton = (Button)findViewById(R.id.startButton);
endButton = (Button)findViewById(R.id.endButton);
//为控件设置监听器
startButton.setOnClickListener(new StartButtonListener());
endButton.setOnClickListener(new EndButtonListener());
class StartButtonListener implements OnClickListener{
public void onClick(View v) {
//调用Handler的post()方法,将要执行的线程对象放到队列当中
handler.post(updateThread);
class EndButtonListener implements OnClickListener{
public void onClick(View v) {
//调用Handler的removeCallbacks()方法,删除队列当中未执行的线程对象
handler.removeCallbacks(updateThread);
//创建Handler对象
Handler handler = new Handler();
//新建一个线程对象
Runnable updateThread = new Runnable(){
//将要执行的操作写在线程对象的run方法当中
public void run(){
System.out.println("updateThread");
//调用Handler的postDelayed()方法
//这个方法的作用是:将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象
//第一个参数是Runnable类型:将要执行的线程对象
//第二个参数是long类型:延迟的时间,以毫秒为单位
handler.postDelayed(updateThread, 3000);
上面是一个最简单的例子,下面再看另外一个例子。
示例2:一个应用程序中有一个进度条和一个按钮,当点击按钮后,每隔一秒钟进度条前进一部分。
下图为应用程序的运行效果图:
开发步骤:
1、 新建一个Android应用程序
2、 在布局文件中添加一个progressBar和一个Button,并为其设置属性和值
3、 在Activity中,声明控件变量并根据id获得控件对象
4、 创建线程对象
a) 通过匿名内部类的方式
b) 在编写完了5、6步之后再来继续编写这个线程对象里的操作
i. 声明一个变量用来设置进度条的进度
ii. 重写线程类的run方法(),里面编写要执行的操作
1. 打印一个字符串
2. 进度条的值增加
3. 得到一个消息对象
4. 设置消息对象arg1的值
5. 让线程休眠一秒钟
6. 将消息对象放入到消息队列中
7. 判断,如果进度条的值等于100,则将线程对象从队列中移除。
5、 创建Handler对象
a) 与示例1不同的地方是,这里是通过匿名内部类的方式来声明的,而示例1是直接new出来的对象
b) 重写Handler对象的handlerMessage(Message msg)方法
i. 这个方法传入了一个Message对象,即消息对象,首先设置进度条的进度(这个值是Messag对象里面的一个成员变量arg1)。
ii. 将要执行的线程对象放入到队列当中
6、 编写Button需要的监听器,并绑定
a) 设置进度条为显示状态
b) 将要执行的线程对象放入到队列当中
下面是Activity的代码:
package android.
import android.app.A
import android.os.B
import android.os.H
import android.os.M
import android.view.V
import android.view.View.OnClickL
import android.widget.B
import android.widget.ProgressB
public class ProgressBarHandlerTest extends Activity {
/** Called when the activity is first created. */
private ProgressBar progressB
private Button startB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar = (ProgressBar)findViewById(R.id.progressbar);
startButton = (Button)findViewById(R.id.startButton);
startButton.setOnClickListener(new ProgressBarOnClickListener());
class ProgressBarOnClickListener implements OnClickListener{
public void onClick(View v) {
//设置进度条为可见状态
progressBar.setVisibility(View.VISIBLE);
updateBarHandler.post(updateThread);
//使用匿名内部类来复写Handler当中的handlerMessage()方法
Handler updateBarHandler = new Handler(){
public void handleMessage(Message msg) {
progressBar.setProgress(msg.arg1);
updateBarHandler.post(updateThread); //将要执行的线程放入到队列当中
//线程类,该类使用匿名内部类的方式进行声明
Runnable updateThread = new Runnable(){
int i = 0;
public void run() {
// TODO Auto-generated method stub
System.out.println("Begin Thread");
//得到一个消息对象,Message类是android系统提供的
Message msg = updateBarHandler.obtainMessage();
//将Message对象的arg1参数的值设置为i
msg.arg1 = //用arg1、arg2这两个成员变量传递消息,优点是系统性能消耗较少
Thread.sleep(1000); //让当前线程休眠1000毫秒
}catch(InterruptedException ex){
ex.printStackTrace();
//将Message对象加入到消息队列当中
updateBarHandler.sendMessage(msg);
//如果i的值等于100
if (i == 100){
//将线程对象从队列中移除
updateBarHandler.removeCallbacks(updateThread);
项目源码已经上传到附件了,有需要的可下载。
不知道大家有没有弄明白哈,我自己都写得晕晕乎乎的了,没办法啊语文写作能力不咋地,汗~
这里其实有一点我没有弄明白,就是当进度条的值等于100的时候,就将线程对象从队列中移除,从而停止线程的运行;这个在示例1中是没有问题的,当点击end按钮,线程停止;但是在示例2例子中,当进度条的值等于100了,可是却没有停止,还是在继续的运行,每隔一秒就执行一个线程,不知道这是为什么,研究了好一会儿都没弄明白,希望各位知道的可以跟我说说哈,咱们有机会多探讨探讨、多交流交流!
下载次数: 819
浏览 102618
回答三楼& 不行,因为不能在子线程里更新UI
updateThread里面的run方法是可以更新进度条的,因为这里的操作相当于在UI线程,只要稍微调整一下代码,就可以做到三楼的要求。
//使用匿名内部类来复写Handler当中的handlerMessage()方法
Handler updateBarHandler = new Handler(){
public void handleMessage(Message msg) {
progressBar.setProgress(msg.arg1);
if(msg.arg1&=progressBar.getMax()) {
updateBarHandler.removeCallbacks(updateThread);
updateBarHandler.post(updateThread);
//将要执行的线程放入到队列当中
我试了下,这个是好使的。
1楼的判断条件是不是正好写反了?
浏览: 1096305 次
来自: 北京
写的很好,支持
很好啊,写的很好,可以把你的当模板了106881人阅读
&&& 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知
&&& handler基本使用:
&&&&&&& 在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中
提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握handler的基本使用,我这里主要深入描述handler的内部机制
&& .现在我们首先就有一个问题,我们使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:
从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。
&&&& 现在我们再来看一下使用Handler的基本实现代码:
&&&&&&&&&&&&&& // 主线程中新建一个handler
&&&&&&&&&&&&&&& normalHandler = new Handler() {
&&&&&&&&&&&&&&&&&&&&&&& public void handleMessage(android.os.Message msg) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& btnSendMsg2NormalHandler.setText(&normalHandler&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]--normalHandler handleMessage run...&, Thread.currentThread()
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .getName()));
&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& };
//发送消息到hanlder
myThreadHandler.sendEmptyMessage(0);&
你现在已经很清楚了sendEmptyMessage到handleMessage的过程,途中经过Looper.MessageQueue队列,转由Looper所在的线程去处理了,这是一个异步的过程,当然Looper所在的线程也可以是sendEmptyMessage所在的线程。&
&&&& 看了上面你也许还是迷惑不解,那么什么要Looper了,跟我们要用的Handler又有啥鸟关系呢?
&&&& 我在前面一直强调在主线程中使用handler,为什么要这么说呢,因为你在自己new一个新线程中去像我前面那样简单建立一个Handler,程序执行是会报错的:
&&& java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
&&&& at android.os.Handler.&init&(Handler.java:121)
&&&& at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.&init&(HandleTestActivity.java:86)
&&&& at com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)
为什么在主线程中不会报错,而在自己新见的线程中就会报这个错误呢?很简单,因为主线程它已经建立了Looper,你可以打开ActivityThread的源码看一下:
&&& public static final void main(String[] args) {
&&&&&&& SamplingProfilerIntegration.start();
&&&&&&& Process.setArgV0(&&pre-initialized&&);
&&&&&&& Looper.prepareMainLooper();
&&&&&&& ActivityThread thread = new ActivityThread();
&&&&&&& thread.attach(false);
Looper.loop();
&&&&&&& if (Process.supportsProcesses()) {
&&&&&&&&&&& throw new RuntimeException(&Main thread loop unexpectedly exited&);
&&&&&&& thread.detach();
&&&&&&& String name = (thread.mInitialApplication != null)
&&&&&&&&&&& ? thread.mInitialApplication.getPackageName()
&&&&&&&&&&& : &&unknown&&;
&&&&&&& Slog.i(TAG, &Main thread of & + name + & is now exiting&);
&&& 在main函数中它已经做了这个事情了,为什么要调用 Looper.prepareMainLooper(); Looper.loop();我们可以进去看一下,在prepareMainLooper方法中新建了一个looper对象,并与当前进程进行了绑定,而在Looper.loop方法中,线程建立消息循环机制,循环从MessageQueue获取Message对象,调用&
msg.target.dispatchMessage(msg);进行处理msg.target在myThreadHandler.sendEmptyMessage(0)设置进去的,因为一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理,那么Handler又是怎样与Looper建立联系的呢,在Handler构造函数中有这样一段代码:
&&&&&& mLooper = Looper.myLooper();
&&&&&&& if (mLooper == null) {
&&&&&&&&&&& throw new RuntimeException(
&&&&&&&&&&&&&&& &Can't create handler inside thread that has not called Looper.prepare()&);
&&&&&&& mQueue = mLooper.mQ
在新建Handler时需要设置mLooper成员,Looper.myLooper是从当前线程中获取绑定的Looper对象:
public static final Looper myLooper() {
&&&&&&& return (Looper)sThreadLocal.get();
&&& 若Looper对象没有创建,就会抛异常&Can't create handler inside thread that has not called Looper.prepare()&
这跟我前面讲的是一致的。所以我们在一个新线程中要创建一个Handler就需要这样写:
&&&&&&& class MyThread extends Thread {
&&&&&&&&&&&&&&& public void run() {&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&& Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]-- run...&, Thread
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .currentThread().getName()));
&&&&&&&&&&&&&&&&&&&&&&& // 其它线程中新建一个handler
&&&&&&&&&&&&&&&&&&&&&&& Looper.prepare();//
创建该线程的Looper对象,用于接收消息,在非主线程中是没有looper的所以在创建handler前一定要使用prepare()创建一个Looper
&&&&&&&&&&&&&&&&&&&&&&& myThreadHandler = new Handler() {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& public void handleMessage(android.os.Message msg) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]--myThreadHandler handleMessage run...&, Thread
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .currentThread().getName()));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&&&&&&&&&& Looper.myLooper().loop();//建立一个消息循环,该线程不会退出
&&&&&&&&&&&&&&& }
&& 现在,你应该对Handler的机制有所了解了吧,若有什么疑问,欢迎在评论中提出
& 在其它线程中Handler使用主线程的Looper
&& 前面我说了在新线程中要新建一个Handler需要调用Looper.prepare();也有另一种方法就是使用主线程中的Looper,那就不必新建Looper对象了:
&&&&&&&&&&&&&&&&&&&&&&& threadMainLoopHandler =new Handler(Looper.getMainLooper()){
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& public void handleMessage(android.os.Message msg) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]--threadMainLoopHandler handleMessage run...&, Thread
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .currentThread().getName()));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //该handleMessage方法将在mainthread中执行
&&&&&&&&&&&&&&&&&&&&&&& };
& 这时候注意不要在handleMessage做太多的操作,因为它在主线程中执行,会影响主线程执行ui更新操作。
&&& 使用Message.callback回调
&& public void dispatchMessage(Message msg) {
&&&&&&& if (msg.callback != null) {
&&&&&&&&&&& handleCallback(msg);
&&&&&&& } else {
&&&&&&&&&&& if (mCallback != null) {
&&&&&&&&&&&&&&& if (mCallback.handleMessage(msg)) {
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& handleMessage(msg);
从dispatchMessage定义可以看出,如果Message对象自带callback对象,handler不会执行handleMessage方法而是执行message.callback中定义的run方法,当然callback还是在handler关联的looper所绑定的线程中执行的。实际上Handler.post(Runnable r)方法就是把r添加到一个msg.callback的,也就是说,下面两种写法,没有什么区别:
1.使用Message.callback
Message msg = Message.obtain(myThreadHandler,new Runnable() {
public void run() {
Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]--myThreadHandler.Message.callback.run&,
Thread.currentThread().getName()));
myThreadHandler.sendMessage(msg);
2.使用Handler.post
myThreadHandler.post(new Runnable() {
public void run() {
Log.d(Constant.TAG, MessageFormat.format(&Thread[{0}]--myThreadHandler.Message.callback.run&,
Thread.currentThread().getName()));
注:对于Handler机制相关测试,我写了一个测试类:
3.Handler对Activity finish影响。
在开发的过程中碰到一个棘手的问题,调用Activity.finish函数Acitivity没有执行生命周期的ondestory函数,后面查找半天是因为有一个handler成员,因为它有一个delay消息没有处理,调用Activity.finish,Activity不会马上destory,所以记得在Ativity finish前清理一下handle中的未处理的消息,这样Activity才会顺利的destory
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:622455次
积分:4003
积分:4003
排名:第3743名
原创:34篇
评论:402条
(1)(3)(2)(1)(2)(5)(8)(5)(1)(4)(2)(1)

我要回帖

更多关于 android studio导入库 的文章

 

随机推荐