我查了官方的Android文档/指南Looper,Handler和MessageQueue.但我无法得到它.我是android新手,对这些概念非常困惑.
我不明白为什么我会收到这个错误.我正在使用AsyncTask在后台运行一些进程.
我有:
protected void onPreExecute()
{
connectionProgressDialog = new ProgressDialog(SetPreference.this);
connectionProgressDialog.setCancelable(true);
connectionProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
connectionProgressDialog.setMessage("Connecting to site...");
connectionProgressDialog.show();
downloadSpinnerProgressDialog = new ProgressDialog(SetPreference.this);
downloadSpinnerProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
downloadSpinnerProgressDialog.setMessage("Downloading wallpaper...");
}
Run Code Online (Sandbox Code Playgroud)
当我doInBackground()根据条件进入时我:
[...]
connectionProgressDialog.dismiss();
downloadSpinnerProgressDialog.show();
[...]
Run Code Online (Sandbox Code Playgroud)
每当我尝试downloadSpinnerProgressDialog.show()我收到错误.
有什么想法吗?
我有一个工作线程,它位于后台,处理消息.像这样的东西:
class Worker extends Thread {
public volatile Handler handler; // actually private, of course
public void run() {
Looper.prepare();
mHandler = new Handler() { // the Handler hooks up to the current Thread
public boolean handleMessage(Message msg) {
// ...
}
};
Looper.loop();
}
}
Run Code Online (Sandbox Code Playgroud)
从主线程(UI线程,不重要)我想做这样的事情:
Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);
Run Code Online (Sandbox Code Playgroud)
麻烦的是,这为我设定了一个漂亮的竞争条件:在worker.handler阅读时,没有办法确定工作线程已经分配给了这个领域!
我不能简单地Handler从Worker构造函数创建,因为构造函数在主线程上运行,因此Handler它将自己与错误的线程相关联.
这似乎不太常见.我可以提出几个解决方法,所有这些都是丑陋的:
像这样的东西:
class Worker extends Thread {
public volatile Handler handler; // actually private, of course …Run Code Online (Sandbox Code Playgroud)我有以下代码
class OverlayTask extends AsyncTask<Void, Void, Void> {
@Override
public void onPreExecute() {
if (sites != null) {
myMapView.getOverlays().remove(sites);
myMapView.invalidate();
sites = null;
}
}
@Override
public Void doInBackground(Void... unused) {
grabShipsWithLocation();
return (null);
}
@Override
public void onPostExecute(Void unused) {
myMapView.getOverlays().add(sites);
myMapView.invalidate();
isLoading = false;
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎在一些测试设备上工作正常,但我发现在开发控制台上出现了很多错误.我似乎无法弄清楚为什么以及在哪里放置这个Looper.prepare().需要它吗?
java.lang.ExceptionInInitializerError
at com.test.appname.FinderMain$1.gotLocation(FinderMain.java:286)
at com.test.appname.MyLocation$GetLastLocation.run(MyLocation.java:89)
at java.util.Timer$TimerImpl.run(Timer.java:289)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
Run Code Online (Sandbox Code Playgroud)
按要求MyLocation.java
class GetLastLocation …Run Code Online (Sandbox Code Playgroud) 我在后台完成了AsyncTask完成的任务.在某些时候,我需要发出一个完成某事的Toast.
我试过,但我失败了,因为
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
我怎样才能做到这一点?
我使用android.os.Handler类在后台执行任务.当单元测试这些时,我调用Looper.loop()让测试线程等待后台任务线程做它的事情.后来,我调用Looper.myLooper().quit()(也在测试线程中),允许测试线程退出loop并恢复测试逻辑.
在我想要编写多种测试方法之前,这一切都很好.
问题是Looper似乎不是为允许在同一个线程上退出和重新启动而设计的,所以我被迫在一个测试方法中完成所有测试.
我查看了Looper的源代码,但找不到解决方法.
有没有其他方法来测试我的Hander/Looper代码?或者可能还有一些测试友好的方式来编写我的后台任务类?
请考虑以下代码段:
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
getLooper().quitSafely();
}
};
for(int i = 0; i < urls.size(); i++) {
useCaseProvider.get().execute(callback, handler, urls.get(i), threadPool);
}
Looper.loop();
//Continue processing the results of all the use cases after the
//loop has been asked to terminated via the handler
Run Code Online (Sandbox Code Playgroud)
一点背景:我正在对UI线程进行一些处理,我需要ping一大堆设备并对结果做一些事情.我需要并行执行请求才能高效.
问题:如果其中一个用例以某种方式执行得足够快并在我能够命中Looper.loop()之前进行了回调; 消息会排队还是丢失?处理程序将runnable发布到原始线程,回调函数将被回发到此线程.
任何人都可以解释为什么有人应该使用Android Looper功能来创建一个"管道线程",而不是制作一个从BlockingQueue中提取任务的普通线程?从表面上看,似乎有两种方法可以做同样的事情.
我创建了一个扩展Thread的类,通过LocationManager在非ui线程中检索用户位置.我将它作为一个线程实现,因为它必须在请求时启动并在有限的时间内完成它的工作.顺便说一句,我必须在线程中添加一个Looper对象,以便能够为LocationManager(onLocationChanged)创建处理程序.
这是代码:
public class UserLocationThread extends Thread implements LocationListener {
//...
public void run() {
try {
Looper.prepare();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
Looper.loop();
Looper.myLooper().quit();
} catch (Exception e) {
//...
}
}
@Override
public void onLocationChanged(Location location) {
locationManager.removeUpdates(this);
//...
handler.sendMessage(msg); //this is the handler for communication with father thread
}
//...}
Run Code Online (Sandbox Code Playgroud)
我希望线程启动,接收用户位置数据(在这种情况下只是一次),通过消息将数据发送到主线程给处理程序,然后死掉.问题是,在我的情况下,一旦run方法结束,线程就不会再死了(应该没问题,因为否则onLocationChanged将不会收到新的位置).
但是通过这种方式,假设线程的停止和挂起方法已被弃用,那么至少在这种情况下,使用looper die创建一个线程会是一个好方法吗?
提前致谢 ;)
我们正在构建一个应用程序,可以执行大量动画并下载大量图像.在一定数量的事务(可预测的数字)之后,应用程序崩溃并出现错误:
A/Looper: Could not create wake pipe. errno=24
Run Code Online (Sandbox Code Playgroud)
我们在代码中不使用Looper,但我们使用的一些库确实使用了Looper:
有没有任何机构经历过任何这些库的Looper错误,并知道如何解决?