Java 无法在未调用 Looper.prepare() 的线程内创建处理程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10403858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Can't create handler inside thread that has not called Looper.prepare()
提问by 19greg96
I saw most of the related questions, but I couldn't find any that fixed my problem.
我看到了大部分相关问题,但我找不到任何可以解决我的问题的问题。
This is my code, and I have no idea what I'm doing wrong.
这是我的代码,我不知道我做错了什么。
static class NamedFile {
public File f;
public String name;
public String ext;
public String path;
public BitmapDrawable icon;
public NamedFile (File file) {
f = file;
name = f.getName();
if (f.isFile()) {
if (name.indexOf('.') != -1) {
ext = name.substring(name.lastIndexOf('.') + 1).trim().toLowerCase();
} else {
ext = "unknown";
}
}
path = f.getAbsolutePath();
if (ext == null) {
icon = mFolderIcon;
} else {
BitmapDrawable i = icons.get(ext);
if (i == null) {
try {
int rid = R.drawable.class.getField(ext).getInt(R.drawable.class);
icons.put(ext, new BitmapDrawable(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(res, rid, mOpts), iconSize, iconSize, false)));
icon = icons.get(ext);
} catch (Exception e1) {}
} else {
icon = i;
}
}/* else if (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png")) {
Bitmap b = BitmapFactory.decodeFile(path, mOpts);
if (b != null) {
icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false));
}
}*/
if (ext != null && (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png"))) {
/*
Bitmap b = BitmapFactory.decodeFile(path, mOpts);
if (b != null) {
icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false));
}
*/
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
HashMap<String, Object> m = ((HashMap<String, Object>)message.obj);
sendThumbnail ((String)m.get("path"), (byte[])m.get("data"));
}
};
Thread thread = new Thread() {
public void writeInt (byte[] buff, int pos, int value) {
buff[pos] = (byte)(value >>> 24);
buff[pos + 1] = (byte)(value >>> 16);
buff[pos + 2] = (byte)(value >>> 8);
buff[pos + 3] = (byte)value;
}
@Override
public void run() {
try {
Bitmap b = BitmapFactory.decodeFile(path, mOpts);
if (b.getHeight() > 256 || b.getWidth() > 256) {
float r;
if (b.getHeight() > b.getWidth()) {
r = 128f / b.getHeight();
} else {
r = 128f / b.getWidth();
}
b = Bitmap.createScaledBitmap(b, (int)(r * b.getWidth()), (int)(r * b.getHeight()), false);
byte[] buffer = new byte[b.getWidth() * b.getHeight() * 4 + 8];
writeInt (buffer, 0, b.getWidth());
writeInt (buffer, 4, b.getHeight());
int i = 8;
for (int y = 0; y < b.getHeight(); y ++) {
for (int x = 0; x < b.getWidth(); x ++) {
writeInt (buffer, i, b.getPixel(x, y));
i += 4;
}
}
HashMap<String, Object> msg = new HashMap<String, Object>();
msg.put("path", path);
msg.put("data", buffer);
Message message = handler.obtainMessage(1, msg);
handler.sendMessage(message);
}
} catch (Exception e) {
sendLog (e.toString());
}
}
};
thread.start();
}
if (icon == null) {
icon = mFileIcon;
}
}
public NamedFile () {
}
public NamedFile simpleClone () {
final NamedFile nf = new NamedFile();
nf.name = name;
nf.ext = ext;
nf.path = path;
return nf;
}
}
This is nested inside an if statement that is in a static class' constructor function and the static class is in a public class that extends ListActivity. I'm new to Java.
这嵌套在静态类的构造函数中的 if 语句中,而静态类位于扩展 ListActivity 的公共类中。我是 Java 的新手。
Error:
错误:
05-01 20:21:58.810: E/AndroidRuntime(584): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception
05-01 20:21:58.830: E/AndroidRuntime(584): java.lang.RuntimeException: An error occured while executing doInBackground()
05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.AsyncTask.done(AsyncTask.java:200)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.lang.Thread.run(Thread.java:1096)
05-01 20:21:58.830: E/AndroidRuntime(584): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.Handler.<init>(Handler.java:121)
05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$NamedFile.<init>(FileTransferActivity.java:588)
05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$NamedFile.<init>(FileTransferActivity.java:588)
05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:489)
05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:1)
05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.AsyncTask.call(AsyncTask.java:185)
05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-01 20:21:58.830: E/AndroidRuntime(584): ... 4 more
(FileTransferActivity.java:588 is final Handler handler = new Handler() {
)
(FileTransferActivity.java:588 是final Handler handler = new Handler() {
)
回答by DeeV
A Handler
is basically a callback class that Android uses to asynchronously run code when you send it messages of some form. In order for a Handler
to receive and handle messages in a separate thread from the UI thread, it must keep the thread open. That is where the Looperclass comes in. Like in the example of the page, call Looper.prepare()
at the top of the run()
method, then call Looper.loop()
at the bottom. The thread will stay open until you explicitly destroy it. In order to destroy a Looper
thread, you must have a method in your Thread
class that calls Looper.getMyLooper().quit()
.
AHandler
基本上是一个回调类,当你向它发送某种形式的消息时,Android 使用它来异步运行代码。为了Handler
在与 UI 线程不同的线程中接收和处理消息,它必须保持线程处于打开状态。这就是Looper类的用武之地。就像在页面示例中一样Looper.prepare()
,在run()
方法的顶部调用,然后Looper.loop()
在底部调用。该线程将保持打开状态,直到您明确销毁它。为了销毁Looper
线程,您的类中必须有一个Thread
调用Looper.getMyLooper().quit()
.
An example thread class would be something like this:
一个示例线程类将是这样的:
class LooperThread extends Thread {
public Handler mHandler;
private volatile Looper mMyLooper;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
mMyLooper = Looper.getMyLooper();
Looper.loop();
}
public void killMe(){
mMyLooper.quit();
}
}
Run the thread normally by creating a new object of it.
通过创建它的新对象来正常运行线程。
LooperThread myLooperThread = new LooperThread();
Hold a reference to it. Then call:
保留对它的引用。然后调用:
myLooperThread.killMe();
Whenever you want the thread to die. This is usually in the onPause()
, onStop()
, or onDestroy()
methods of the Activity.
每当您希望线程死亡时。这通常是在onPause()
,onStop()
或onDestroy()
活性的方法。
Please note that a thread of this nature will stay open when the activity is closed so you must kill it before the user quits.
请注意,当活动关闭时,这种性质的线程将保持打开状态,因此您必须在用户退出之前终止它。
回答by SurenSaluka
Runs the specified action on the UI thread
在 UI 线程上运行指定的操作
ActivityName.runOnUiThread(new Runnable() {
public void run()
{
//put your logic here
}
});
回答by dagalpin
I recommend using HandlerThread as it prepares the looper for you.
我建议使用 HandlerThread,因为它会为您准备 Looper。
http://developer.android.com/reference/android/os/HandlerThread.html
http://developer.android.com/reference/android/os/HandlerThread.html