英文:
Android - Tasks.await blocks UI and ANR
问题
我正试图在视图中展示应用程序在Play商店中是否有新的更新,使用AppUpdateManager。
我正在使用下面的方法等待appUpdateInfoTask完成,然后继续进行UI操作。
private static AppUpdateInfo checkIfUpdateAvailable(Context context) {
try {
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);
final Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
.addOnSuccessListener(new OnSuccessListener<AppUpdateInfo>() {
@Override
public void onSuccess(AppUpdateInfo appUpdateInfo) {
}
});
try {
return Tasks.await(appUpdateInfoTask);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
当准备好时,此方法应返回AppUpdateInfo对象。然而,await似乎阻塞了整个UI。
我无法理解的是为什么应用程序会在Tasks.await(appUpdateInfoTask)处停止响应,我在其他地方也使用了相同的方法,而且一直正常运行。我是否遗漏了什么?
英文:
I am trying to show in a view if there is a new update of the app in the playstore using AppUpdateManager.
I am using the below method that waits for the appUpdateInfoTask to finish and then continue with the UI.
private static AppUpdateInfo checkIfUpdateAvailable (Context context){
try {
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);
final Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
.addOnSuccessListener(new OnSuccessListener<AppUpdateInfo>() {
@Override
public void onSuccess(AppUpdateInfo appUpdateInfo) {
}
});
try {
return Tasks.await(appUpdateInfoTask);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
This should return the AppUpdateInfo object when it is ready.
However the await seems to block the whole UI.
What I cannot understand is why the app stuck on Tasks.await(appUpdateInfoTask), I have used the same method in other places as well and always run.
Am I missing something here?
答案1
得分: 2
按照文档说明:
https://developers.google.com/android/guides/tasks
此方法将同步调用(如果从 UI 线程调用,则会阻塞 UI)
因此有两个选项:
使用您的代码:
您还可以在阻塞任务时指定超时,以避免应用程序挂起:
AuthResult authResult = Tasks.await(task, 500, TimeUnit.MILLISECONDS);
使用以下代码(经过修改的您的代码):
public interface UpdateAvailabilityInterface {
void updateAvailable();
void getAppUpdateInfo(AppUpdateInfo appUpdateInfo);
void updateNotAvailable();
}
private static void checkIfUpdateAvailable(Context context, UpdateAvailabilityInterface updateAvailabilityInterface) {
try {
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);
final Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
.addOnSuccessListener(new OnSuccessListener<AppUpdateInfo>() {
@Override
public void onSuccess(AppUpdateInfo appUpdateInfo) {
// 异步获取信息
if (updateAvailabilityInterface != null) {
updateAvailabilityInterface.getAppUpdateInfo(appUpdateInfo);
boolean updateIsAvailable = true; // 添加检查是否可用的方法
if (updateIsAvailable) {
updateAvailabilityInterface.updateAvailable();
} else {
updateAvailabilityInterface.updateNotAvailable();
}
}
}
});
// 尝试等待任务
// try {
// return Tasks.await(appUpdateInfoTask);
// } catch (ExecutionException | InterruptedException e) {
// e.printStackTrace();
// return null;
// }
} catch (Exception e) {
e.printStackTrace();
// return null;
}
}
注意:我没有尝试过上面的代码,所以如果您发现无法正常工作,请告诉我,我会自己尝试。
调用者将如下所示:
checkIfUpdateAvailable(context, new UpdateAvailabilityInterface() {
@Override
public void updateAvailable() {
// 当有更新可用时的代码
}
@Override
public void getAppUpdateInfo(AppUpdateInfo appUpdateInfo) {
// 获取 AppUpdateInfo 时执行的代码
// 在获得 appUpdateInfo 后编写您的代码
}
@Override
public void updateNotAvailable() {
// 当没有更新可用时的代码
}
});
英文:
As the doc says :
https://developers.google.com/android/guides/tasks
This method will be called synchronously (if it is called from UI Thread, then will block the UI)
So there are 2 options :
With your code :
You can also specify a timeout when blocking a task so that your application does not hang:
AuthResult authResult = Tasks.await(task, 500, TimeUnit.MILLISECONDS);
With following code (your code with modifications) :
public interface UpdateAvailabilityInterface {
void updateAvailable();
void getAppUpdateInfo(AppUpdateInfo appUpdateInfo);
void updateNotAvailable();
}
private static void checkIfUpdateAvailable(Context context, UpdateAvailabilityInterface updateAvailabilityInterface) {
try {
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);
final Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
.addOnSuccessListener(new OnSuccessListener<AppUpdateInfo>() {
@Override
public void onSuccess(AppUpdateInfo appUpdateInfo) {
//You will get the info here asynchronously..
if (updateAvailabilityInterface != null) {
updateAvailabilityInterface.getAppUpdateInfo(appUpdateInfo);
boolean updateIsAvailable = true; // add method to check if update is available or not
if (updateIsAvailable) {
updateAvailabilityInterface.updateAvailable();
} else {
updateAvailabilityInterface.updateNotAvailable();
}
}
}
});
// try {
// return Tasks.await(appUpdateInfoTask);
// } catch (ExecutionException | InterruptedException e) {
// e.printStackTrace();
// return null;
// }
} catch (Exception e) {
e.printStackTrace();
// return null;
}
}
Note : I didn't try the above code, so please let me know if this doesn't work for you, I will try it by my self.
Caller will look like this :
checkIfUpdateAvailable(context, new UpdateAvailabilityInterface() {
@Override
public void updateAvailable() {
// Code when update is available
}
@Override
public void getAppUpdateInfo(AppUpdateInfo appUpdateInfo) {
// Get the AppUpdateInfo whenever it is available
//Write your code which will be executed after you get appUpdateInfo
}
@Override
public void updateNotAvailable() {
// Code when update is not available
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论