【发布时间】:2014-08-04 00:11:41
【问题描述】:
我在 Android 应用程序的 Service 中使用 Looper。通常它可以正常工作。但在某些情况下(例如,当我经常尝试调试我的应用程序时)它显示应用程序内部存在竞争。 Looper 正在启动,Thread 和 Handler 正在方法 startMessageThread() 中创建,该方法在 Service.onCreate() 方法结束时被调用。
比赛是因为在Looper.loop();之前初始化的还有其他方法和类使用这个类。在某些情况下,这些方法在Looper 结束之前运行。结果为NullPointerException。
public class MyService extends Service {
private Thread thread;
private Handler handler;
@Override
public void onCreate() {
super.onCreate();
//some code
startMessageThread();
}
private void startMessageThread() {
thread = new Thread() {
@Override
public void run() {
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
}
}
}
}
如果我是对的,这个问题How to create a Looper thread, then send it a message immediately? 非常相似,但我不想在创建“HandlerThread”后立即发送任何消息。只是为了强制主线程在onCreate方法结束时等待Looper结束。
我已经尝试在 Service.onCreate 方法的末尾添加这个:
synchronized (thread) {
try {
if (looperRun) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
looperRun 当然是boolean。我在Looper.loor(); 方法调用之前添加了looperRun = true;。而这段代码在startMessageThread()方法的末尾。
if (looperRun) {
notify();
looperRun = false;
}
在某些情况下我遇到了这个异常:
java.lang.RuntimeException: Unable to create service com.myapplication.service.MyService:
java.lang.IllegalMonitorStateException: object not locked by thread before wait()
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2582)
at android.app.ActivityThread.access$1800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalMonitorStateException: object not locked by thread before wait()
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:364)
at com.myapplication.service.MyService.onCreate(MyService.java:162)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2572)
at android.app.ActivityThread.access$1800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
编辑
protected void startMessageThread() {
MessageThread messageThread = new MessageThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
}
private class MessageThread extends HandlerThread {
public MessageThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
}
}
编辑 2
我尝试过类似的解决方案:How to create a Looper thread, then send it a message immediately? 我的代码如下。但是我的应用在启动后似乎被冻结了。
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
case MSG_INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
//message handling
}
}
};
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
我像以前一样在这个方法中启动这个HandlerThread:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
backgroundHandler.sendEmptyMessage(MSG_INIT);
}
正如我上面提到的 - 应用程序似乎在启动后被冻结。什么都没有发生。
【问题讨论】:
-
你想做什么?
-
@OfekRon 我想在
onCreate里面等一会儿,因为Looper将完成
标签: java android multithreading