ASynchTask 在 doinbackground 中休眠锁定 UI 线程

发布于 2025-01-05 19:46:34 字数 2672 浏览 2 评论 0原文

编辑:已解决。抱歉,我突然想到,虽然我的数据加载是在后台线程中发生的,但解析数据的回调却不是。数据的解析花费了很长时间,这就是锁定我的线程的原因。

编辑:我注意到我的首要问题(ProgressDialog 不再旋转)可能是由于我使用 ProgressDialog 而不是 UI 线程被阻止的问题引起的。如果是这种情况,我该如何解决?

编辑:澄清一下,这不会永远锁定整个程序。加载所有内容后,进度对话框将消失,并启动新活动。我的问题是,在加载时,整个 UI 锁定(即进度对话框停止旋转)

TL;DR: doInBackground() 中的 Thread.sleep() 正在锁定 UI 线程

我有一个应用程序,当特定活动打开时,开始从我的后端在后台加载大量数据,例如与日程表相关的大量数据。该信息不会立即使用,但如果用户尝试访问它(即通过单击计划按钮并启动计划活动),则可以使用该信息。

如果用户在单击计划按钮之前稍等一下,所有数据都会加载,计划活动将打开,并显示所有精彩内容。我的问题是他们是否在数据加载之前单击按钮。

我的解决方案是创建一个 ASyncTask,它显示 ProgressDialog,同时定期检查数据是否已完成加载,否则休眠。它知道数据已通过一些应用程序范围的布尔变量完成加载。我的问题是,即使 Thread.sleep() 在 doinbackground() 中运行,它仍然锁定 UI 线程。

我正在使用自定义 ASyncTask,定义如下:

public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{
    private ProgressDialog pd; //the progress dialog
    private String title; //the title of the progress dialog
    private String  message; //the body of the progress dialog
    private Runnable task; //contains the code we want to run in the background
    private Runnable postTask; //execute when the task ends
    private Context c;


    public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){
        super();
        c = context;
        task = r;
        postTask = postR;
        title = t;
        message = m;
    }

    @Override
    protected void onPreExecute(){
        pd = ProgressDialog.show(c,title, message, false, false);
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        task.run();
        return true;
    }


    @Override
    protected void onPostExecute(Boolean result) {
        pd.dismiss();
        if(postTask != null)
            postTask.run();
    }

并通过(例如)调用它:(

if(loadingSchedule){

            LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() {
                public void run(){
                    while(loadingSchedule){
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                    }
                }
            },new Runnable() {
                public void run(){

                    Intent i= new Intent(thisClass, Schedule.class);
                    i.putExtra("numberIneed",index);
                    startActivity(i); 
                }
            });
            lwpd.execute();

我将对全局变量的访问缩短为“loadingSchedule”以使其更易于阅读)

如何使其不锁定 UI 线程?

EDIT: SOLVED. Sorry guys, it occurred to me that while my loading of my data was occurring in a background thread, the callback that parsed the data was not. The parsing of the data took a very long time, and that was what was locking my thread.

EDIT: It has come to my attention that my overarching problem (the ProgressDialog no longer spinning) may be caused by a problem with my use of a ProgressDialog rather than the UI thread being blocked. If that is the case, how do I fix that?

EDIT: to clarify, this does not lock the entire program up forever. Once everything is loaded, the progress dialog IS dismissed, and the new activity is brought up. My problem is that while it is loading, the entire UI locks up (i.e. the progressdialog stops spinning)

TL;DR: Thread.sleep() in doInBackground() is locking the UI thread

I have an app that, when a specific activity opens, begins to load a lot of data in the background from my back-end, for example, a large amount of data related to a schedule. This information will not be used right away, but may be used if the user attempts to access it (i.e. by clicking the schedule button, and launching the schedule activity).

If the user waits a bit before clicking the schedule button, all of the data loads, the schedule activity opens, and displays everything great. My problem is if they click the button before the data loads.

My solution here was to create an ASyncTask that shows a ProgressDialog while periodically checking if the data has finished loading, and sleeping otherwise. It knows that the data is finished loading via some application-wide boolean variables. My problem is that, even though the Thread.sleep() is run within doinbackground(), it is still locking the UI Thread.

I am using a custom ASyncTask, defined below:

public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{
    private ProgressDialog pd; //the progress dialog
    private String title; //the title of the progress dialog
    private String  message; //the body of the progress dialog
    private Runnable task; //contains the code we want to run in the background
    private Runnable postTask; //execute when the task ends
    private Context c;


    public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){
        super();
        c = context;
        task = r;
        postTask = postR;
        title = t;
        message = m;
    }

    @Override
    protected void onPreExecute(){
        pd = ProgressDialog.show(c,title, message, false, false);
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        task.run();
        return true;
    }


    @Override
    protected void onPostExecute(Boolean result) {
        pd.dismiss();
        if(postTask != null)
            postTask.run();
    }

and calling it via (for example):

if(loadingSchedule){

            LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() {
                public void run(){
                    while(loadingSchedule){
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                    }
                }
            },new Runnable() {
                public void run(){

                    Intent i= new Intent(thisClass, Schedule.class);
                    i.putExtra("numberIneed",index);
                    startActivity(i); 
                }
            });
            lwpd.execute();

(I shortened access to the global variable to "loadingSchedule" to make it easier to read)

How do I make this not lock the UI thread?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一张白纸 2025-01-12 19:46:34

doInBackground() 中的 Thread.sleep() 正在锁定 UI 线程

doInBackground() 中的 Thread.sleep() 不会锁定 UI 线程,正如其名称所示,任务在后台异步执行。

您的 UI 线程不会被锁定。它实际上是在 AsyncTask 启动之前弹出的 ProgressDialog(在 onPreExecute() 方法中),并在 AsyncTask 执行期间(在 doInBackground() 方法中)持续显示在前面并阻止用户与底层活动的交互。最后在 AsyncTask 完成后被解雇。 (在 onPostExecute() 方法中)

我有一个应用程序,当特定活动打开时,它开始从后端在后台加载大量数据

这是一个常见的用例,创建一个在后台加载数据的 AsyncTask 实现会更有效,而不是创建一个显示 ProgressDialog 的 ASyncTask,同时定期检查数据是否已完成加载,否则休眠。

查看 API 此处,它包含如何使用它的很好的示例适当地。

Thread.sleep() in doInBackground() is locking the UI thread

Thread.sleep() in doInBackground() does not lock UI thread, as its name stated, task do in background asynchronously.

You UI thread doesn't get locked. It is actually the ProgressDialog pop up before AsyncTask started (in onPreExecute() method) and keep showing in front and block user interaction with the underlying activity during AsyncTask execution (in doInBackground() method). and finally dismissed after AsyncTask finish. (in onPostExecute() method)

I have an app that, when a specific activity opens, begins to load a lot of data in the background from my back-end

This is a common use case, it will be more efficient to create an AsyncTask implementation that load data in background, instead of create an ASyncTask that shows a ProgressDialog while periodically checking if the data has finished loading, and sleeping otherwise.

Check out the API here, it contains good example of how to use it properly.

可爱咩 2025-01-12 19:46:34

您的代码看起来正确,并且不应阻塞主线程。

所以使用调试器! 在 doInBackground、Thread.sleep、onPostExecute、lwpd.execute 之后放置断点,您将了解代码在何处以及何时获得。

尝试找到“UI 线程到底在哪里被阻塞”的答案。

Your code looks correct, and should not block main thread.

So use debugger! Put breakpoint in doInBackground, Thread.sleep, onPostExecute, after lwpd.execute, and you will learn where the code gets and when.

Try to find answer to "where exactly is UI thread blocked".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文