Android &引用;“导致僵局”;多次执行某项活动时出错

Android &引用;“导致僵局”;多次执行某项活动时出错,android,performance,android-account,Android,Performance,Android Account,我正在设备上测试我的应用程序,在执行某个活动5或6次后,该应用程序崩溃并出现错误:java.lang.IllegalStateException:从主线程调用该应用程序可能导致死锁 活动很简单:用户输入一个任务并单击保存。此时,我获取他们的用户名和authtoken,并向我的服务器发出POST请求。我想知道我的应用程序是否会崩溃,因为每次我都会得到用户名和authtoken 崩溃发生在下面代码的newcreatetask行 public boolean onOptionsItemSelected

我正在设备上测试我的应用程序,在执行某个活动5或6次后,该应用程序崩溃并出现错误:
java.lang.IllegalStateException:从主线程调用该应用程序可能导致死锁

活动很简单:用户输入一个任务并单击保存。此时,我获取他们的用户名和authtoken,并向我的服务器发出POST请求。我想知道我的应用程序是否会崩溃,因为每次我都会得到用户名和authtoken

崩溃发生在下面代码的
newcreatetask

public boolean onOptionsItemSelected(MenuItem menuItem) {
    if (menuItem.getTitle().toString().equalsIgnoreCase("save")) {
        new CreateTask(this,taskName.getText().toString(), getMyAccount().getUsername(), getMyAccount().getAuthToken()).execute();
        return true;
    }
return true
}
getMyAccount()
的代码如下所示:

private MyAccount getMyAccount() {
    MyAccount myAccount = new MyAccount(getApplicationContext());
    return myAccount;
}
最后,类
MyAccount
如下所示:

public class MyAccount {
    private static final String TAG = "MyAccount";
    private final Account account;
    private final AccountManager manager;
    private final Context context;
    public MyAccount(final Context context) {
        this.context = context;
        final Account[] accounts = AccountManager.get(context).getAccountsByType("com.myapp");
        account = accounts.length > 0 ? accounts[0] : null;
        manager = AccountManager.get(context);
    }

    public String getPassword() {
        return account!=null? manager.getPassword(account): null;
    }

    public String getUsername() {
        return account!=null? account.name: null;
    }

    public String getAuthToken() {
        if (account != null) {
            AccountManagerFuture<Bundle> future = manager.getAuthToken(account,"com.myapp", false, null, null);
            try {
                Bundle result = future.getResult();
                return result != null ? result.getString(KEY_AUTHTOKEN) : null;
            } catch (AccountsException e) {
                Log.e(TAG, "Auth token lookup failed", e);
                return null;
            } catch (IOException e) {
                Log.e(TAG, "Auth token lookup failed", e);
                return null;
            }
        }
        else
            return null;
    }
}
公共类MyAccount{
私有静态最终字符串TAG=“MyAccount”;
私人最终账户;
私人最终会计经理;
私人最终语境;
公共MyAccount(最终上下文){
this.context=上下文;
最终账户[]账户=AccountManager.get(上下文).getAccountsByType(“com.myapp”);
account=accounts.length>0?accounts[0]:空;
manager=AccountManager.get(上下文);
}
公共字符串getPassword(){
返回帐户!=null?管理器。getPassword(帐户):null;
}
公共字符串getUsername(){
退货账户!=null?账户名称:null;
}
公共字符串getAuthToken(){
如果(帐户!=null){
AccountManagerFuture=manager.getAuthToken(帐户,“com.myapp”,false,null,null);
试一试{
Bundle result=future.getResult();
返回结果!=null?result.getString(KEY\u AUTHTOKEN):null;
}捕获(AccountSexException e){
Log.e(标记“身份验证令牌查找失败”,e);
返回null;
}捕获(IOE异常){
Log.e(标记“身份验证令牌查找失败”,e);
返回null;
}
}
其他的
返回null;
}
}
问题


这不是最好的做法吗?我的应用程序崩溃是因为我不断重复获取
帐户
authtoken
?避免这种情况的方法是什么?

请在您使用的方法的说明中注意这一点:

可以从任何线程调用此方法,但是 不得在主线程上使用AccountManagerFuture

您显然违反了这一点,因为您的
MyAccount#getAuthToken()
正在访问主线程上的
Future
Bundle result=Future.getResult()

我想这就是为什么你会得到这个例外


希望能有所帮助。

是的,您应该致电manager.getAuthToken(…);在一个单独的线程中,AsyncTask是可以的。实际上,根据它的说法,
getAuthToken
可能不需要单独的线程。让我检查一下,我将尝试将
MyAccount
功能包装到一个单独的asynctask中,该任务从
createTask
调用,并将发布我的进度。感谢问题不在于在UI线程上调用
manager.getAuthToken
,而是在主线程上操作返回的
Future
对象。请看我重新编写的答案。在代码中添加一些解释将使您的答案对未来的搜索者更有用。
        Thread CrearEventoHilo = new Thread(){
            public void run(){
                //do something that retrun "Calling this from your main thread can lead to deadlock"
            }
        };
        CrearEventoHilo.start();
        CrearEventoHilo.interrupt();