【问题标题】:How to update the UI smoothly?如何顺利更新UI?
【发布时间】:2016-10-10 21:57:08
【问题描述】:

据我所知,Android 的AsyncTask 是一种从互联网异步加载信息的好方法。但是,我不想阻塞 UI 并阻止用户与之交互。

我的问题的基本描述。

目前,我正在使用 websockets 来发送/接收来自 web 服务器的数据。在诸如用户进入房间、从播放列表中添加或删除一首歌曲、一首歌曲被赞成或反对,或者一首歌曲结束而另一首歌曲开始等事件中,必须更新 UI 以指示更改。但理想情况下,这些更改会非常频繁地发生,这意味着不断阻止 UI 以刷新它会很麻烦和烦人。

如何在不中断用户活动的情况下更新我的 UI? AsyncTask 就够了吗?

【问题讨论】:

  • AsyncTask 不是唯一的方法。还有 Handlers 和 Loopers,您可以在 Communicating with the UI Thread 中阅读相关内容,然后是 Keeping your App Responsive。

标签: android multithreading user-interface android-asynctask websocket


【解决方案1】:

asyncTask 不会阻止用户界面。它在单独的线程上运行以发送/接收来自网络的数据,然后返回结果。当您收到返回的结果时,您可以根据自己的选择更新 UI。

asyncTask 正在执行其后台工作时,您的 UI 不会停止。您可以通过在您的活动中构建一个并在doInBackground 方法中简单地休眠一段时间(比如说五秒钟)来尝试它。您将看到您的 UI 在这五秒钟内仍然正常工作。

编辑:您可以对返回的结果执行任何操作,并且也不会中断您的 UI。如果不是这种情况,您可能需要考虑优化您对内存对象所做的工作。任何未存储在内存中的内容都应该使用AsyncTask 检索或写入磁盘、数据库或互联网端点。正如评论者在上面指出的那样,这不是使用其他线程的唯一方法,但如果您发出合理的网络请求并期望用户有良好的连接,它很容易并且可能会起作用。您只需要确保涵盖了超时和异常,以便您的应用在任务花费的时间超过预期时不会崩溃。

public class LoadCommentList extends AsyncTask<Integer, Integer, List<Comment>> {
    private String commentSubject;

    public LoadCommentList(commentSubject){
        this.commentSubject = commentSubject;
    }

    // Do the long-running work in here
    protected List<Comment> doInBackground(Integer... params) {
        // the data producer is a class I have to handle web calls
        DataProducer dp = DataProducer.getInstance();

        // here, the getComments method makes the http call to get comments
        List<Comment> comments = dp.getComments(commentSubject);

        return comments;
    }

    // This is called each time you call publishProgress()
    protected void onProgressUpdate(Integer... progress) {
      // setProgressPercent(progress[0]);
    }

    // This is called when doInBackground() is finished
    protected void onPostExecute(List<Comment> comments) {
        // calls a method in the activity to update the ui
        updateUI(comments);
    }
}

实际上使用 Integer... 参数有更简洁的示例,但这只是我方便的示例。

【讨论】:

  • 那么,如果我使用的是 socket.io,我应该在哪里设置套接字连接,在 Activity 或 AsyncTask 中?
  • 使用您的 AsyncTask 来完成长期运行的工作。我已经更新了答案以显示一个例子。在 AsyncTask 中设置您的套接字连接,但您可以使用其他类或方法来实际执行此操作,以保持您的代码干净和可读。
  • 那么 AsyncTask 只运行一次吗?如果它只运行一次,是否有办法让 AsyncTask 不断运行?
  • AsyncTask 会按照您的要求运行。如果您希望它重复运行,例如在某个时间间隔内,您将需要设置其他内容,例如服务和处理程序...有关更多信息,请参阅stackoverflow.com/questions/13954611/…,该主题可能超出您原来的范围问题...
【解决方案2】:

我不知道你在哪里读到的,但异步任务是当今最糟糕的网络服务调用方式。您应该使用 Retrofit 进行服务调用,它的速度提高了 8 倍,并且可以流畅地处理 UI 更新。 在此处阅读有关此内容的更多信息:-

http://googleweblight.com/?lite_url=http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit&ei=qR4bQU5c&lc=en-IN&s=1&m=260&host=www.google.co.in&ts=1465531978&sig=APY536z0v15lfX3G6KY4nls4wf1kzttJdA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多