我得到这个异常,"无法在未调用Looper.prepare()的线程中创建处理程序",当我调用get或getFriends时抛出。这是我用于getFriends的代码。它是从主线程调用的。
public void returnFriendIDs(final int pointer){
Properties properties = new Properties.Builder()
.add(Profile.Properties.ID)
.add(Profile.Properties.FIRST_NAME)
.add(Profile.Properties.LAST_NAME)
.add(Profile.Properties.INSTALLED)
.build();
try{
mSimpleFacebook.getFriends(properties, new OnFriendsListener() {
@Override
public void onComplete(List<Profile> friends) {
String resultStr = "";
Log.d(LOGPREFIX, "Number of friends = " + friends.size());
for(Profile p : friends){
resultStr += p.getId()+',';
}
if(friends.size() > 0) returnFriends(pointer, resultStr.substring(0,resultStr.length()-1));
else returnFriends(pointer, "");
}
@Override
public void onFail(String reason){
returnFriends(pointer, "");
}
@Override
public void onException(Throwable throwable){
Log.w(LOGPREFIX, throwable.getMessage());
returnFriends(pointer, "");
}
});
}
catch(Throwable throwable){
Log.w(LOGPREFIX, "In getFriends"+throwable.getMessage());
}
}
在调用getFriends之前,我尝试过调用Looper.prepare(),但这只会导致没有调用任何回调。
我的活动结果函数是
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
//Log.w(LOGPREFIX, "onActivityResult() called.");
mSimpleFacebook.onActivityResult(this, requestCode, resultCode, data);
// Handle InApp Purchase call results
if(REQUEST_INAPP_PURCHASE == requestCode)
{
if (!mBillingHelper.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
堆栈跟踪为:
Pending exception java.lang.RuntimeException thrown by 'unknown throw location'
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at void android.os.Handler.<init>(android.os.Handler$Callback, boolean) (Handler.java:200)
at void android.os.Handler.<init>() (Handler.java:114)
at void com.facebook.RequestAsyncTask.onPreExecute() (RequestAsyncTask.java:146)
at android.os.AsyncTask android.os.AsyncTask.executeOnExecutor(java.util.concurrent.Executor, java.lang.Object[]) (AsyncTask.java:587)
at android.os.AsyncTask android.os.AsyncTask.execute(java.lang.Object[]) (AsyncTask.java:535)
at void com.sromku.simple.fb.actions.GetAction.runRequest(com.facebook.Request) (GetAction.java:143)
at void com.sromku.simple.fb.actions.GetAction.executeImpl() (GetAction.java:81)
at void com.sromku.simple.fb.actions.AbstractAction.execute() (AbstractAction.java:17)
at void com.sromku.simple.fb.SimpleFacebook.getFriends(com.sromku.simple.fb.entities.Profile$Properties, com.sromku.simple.fb.listeners.OnFriendsListener) (SimpleFacebook.java:594)
at void com.fillmyblank.app.FillMyBlank.returnFriendIDs(int) (FillMyBlank.java:325)
at void org.libsdl.app.SDLActivity.nativeInit() (SDLActivity.java:-2)
at void org.libsdl.app.SDLMain.run() (SDLActivity.java:509)
at void java.lang.Thread.run() (Thread.java:818)
它是用我的主函数(我相信是 UI 线程)的这段代码调用的。我使用 ndk,所以主函数是指实际的函数主函数。
aEnv = (JNIEnv *)SDL_AndroidGetJNIEnv();
aActivityClass = aEnv->FindClass(mClassPath.c_str());
aStaticMid = aEnv->GetStaticMethodID(aActivityClass, "GetActivity", "()Lcom/fillmyblank/app/FillMyBlank;");
aActivity = aEnv->CallStaticObjectMethod(aActivityClass, aStaticMid);
friends* fp = new friends;
fp->waiting = SDL_CreateCond();
aJavaMethodID = aEnv->GetMethodID(aActivityClass, "returnFriendIDs", "(I)V");
aEnv->CallVoidMethod(aActivity, aJavaMethodID, fp);
编辑:添加了堆栈跟踪
编辑:添加了调用函数。
解释
异常被抛出在AsyncTask
的onPreExecute
部分,该部分是Facebook库(com.facebook.RequestAsyncTask
)的一部分。
onPreExecute
在与 AsyncTask 的调用方相同的线程中执行。如果调用方是 ui 线程,没问题,它会工作。如果调用方不是 ui 线程,它可能会失败(很有可能)。如果使用 UI 的任何组件或与 UI 相关的任何组件,它将失败。
在您的情况下,它不是在 ui 线程中执行,而是在没有消息循环的常规线程中执行,因此抛出这个著名的异常: Can't create handler inside thread that has not called Looper.prepare()
解决方案
您必须使用 runOnUiThread 方法,该方法将确保您的代码在 ui 线程中执行。 runOnUiThread
将Runnable
作为参数。
public void returnFriendIDs(final int pointer)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Properties properties = new Properties.Builder()
.add(Profile.Properties.ID)
.add(Profile.Properties.FIRST_NAME)
.add(Profile.Properties.LAST_NAME)
.add(Profile.Properties.INSTALLED)
.build();
try{
mSimpleFacebook.getFriends(properties, new OnFriendsListener() {
@Override
public void onComplete(List<Profile> friends) {
String resultStr = "";
Log.d(LOGPREFIX, "Number of friends = " + friends.size());
for(Profile p : friends){
resultStr += p.getId()+',';
}
if(friends.size() > 0) returnFriends(pointer, resultStr.substring(0,resultStr.length()-1));
else returnFriends(pointer, "");
}
@Override
public void onFail(String reason){
returnFriends(pointer, "");
}
@Override
public void onException(Throwable throwable){
Log.w(LOGPREFIX, throwable.getMessage());
returnFriends(pointer, "");
}
});
}
catch(Throwable throwable){
Log.w(LOGPREFIX, "In getFriends"+throwable.getMessage());
}
}
});
}