Android – Tasks.await blocks UI and ANR

huangapple go评论79阅读模式
英文:

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&lt;AppUpdateInfo&gt; appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
                .addOnSuccessListener(new OnSuccessListener&lt;AppUpdateInfo&gt;() {
                    @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&lt;AppUpdateInfo&gt; appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()
                    .addOnSuccessListener(new OnSuccessListener&lt;AppUpdateInfo&gt;() {
                        @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
            }
        });

huangapple
  • 本文由 发表于 2020年9月15日 23:31:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63905160.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定