今天 碰到一个需求 需要应用的服务在后台运行时也能获取某个状态弹出toast
还可以做成一个服务 可以通过发送广播来调用这个服务 全局弹出Toast
简单来将实现如下
开机广播接收器——启动后台服务——死循环线程判断状态——显示toast
问题卡在了从线程弹出toast这一操作,
由于需求的特殊性, 可能没有activity , 所以UI线程的handler获取不到
网上的攻略有两种
第一种
在线程run 用Looper.prepare();包含所有的代码 Looper.loop()public void run(){ Looper.prepare(); ... //code ... Looper.loop() }
这种方法 在调用Looper.loop()方法后 会进入一个死循环的队列 ,只有在handler.getLooper().quit() 才能退出针对我的情况,里面有个死循环 Looper.loop()方法放在循环外面 永远调用不到, 放在里面调用后死循环第一个循环都完成不了此法无效
第二种
从Ui线程传入handler 并覆写handlermessage
使用handler.sendMessage() 将Toast放到Ui线程里去调用 由于可能没有UI界面 所以handler不适用 (这里有个问题, 是不是非要在Ui线程调用Toast, 或者说只要主线程就能调用 比如service)
要研究下handler Looper 队列极致了
后来忽然想到AsynTask 想了下它的参数 没有context上下文限制, 但是确可以实现到主线程的操作,(好像里面一个获取主线程的方法)。
于是 这篇文章 结束了
贴代码:
BootBroadcastReceiver.java
public class BootBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Constant.ACTION_BOOT_COMPLETED))
{
Intent accountStatusIntent=new Intent(context,AccountStatusService.class);
context.startService(accountStatusIntent);
}
}
}
public class AccountStatusService extends Service{
public void onCreate() {
new GetCardStatusTask(this).execute();
}
class GetCardStatusTask extends AsyncTask<Object, String, Object>{
protected Object doInBackground(Object... arg0) {
while(true){
publishProgress(tempStatus);
//休眠3秒
}
}
protected void onProgressUpdate(String... values) {
Toast.makeText(context,"aaa",Toast.LENGTH_LONG).show();
}
}
}
还可以做成一个服务 可以通过发送广播来调用这个服务 全局弹出Toast
另外 自定义Toast的方法 传送门:
关于线程弹Toast的帖子
Android -- Looper.prepare()和Looper.loop() —深入版 :
http://blog.csdn.net/heng615975867/article/details/9194219
(
不在ui主线程,而是起一个线程去显示toast,你会怎么做,大部分人可能会调用Looper.prepare(), Looper.loop(),确实这样会达到想要的效果,可是这样做存在一个弊端。大部分人可能没想过将Looper的循环停掉(Looper.loop() 会进入一个无限while循环,只有调用quit方法才能跳出来),这在一定程度上会耗用内存,作为保质保量的程序员不应该让此类事情发生。所以尽量避免在新的线程去操作ui主线程的东西,要不就调用类似runOnUiThread的方法去更新。)