首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android:如何在执行长期运行的操作时显示旋转器?

Android:如何在执行长期运行的操作时显示旋转器?
EN

Stack Overflow用户
提问于 2022-02-07 20:22:38
回答 3查看 358关注 0票数 1

我有一个ProgressBar in .xml,我想在长时间运行的操作中显示它。我使用

代码语言:javascript
运行
复制
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);

若要在某些onButtonClick方法中设置其可见性,请执行以下操作。如果上面的代码是方法中的全部代码,那么它就能正常工作。问题是当我有这样的方法时:

代码语言:javascript
运行
复制
public void onButtonClick (android.view.View view){
    ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
    progressSpinner.setVisibility(View.VISIBLE);

    longRunningMethod(); // This method takes 5-10 seconds to run

    progressSpinner.setVisibility(View.GONE);
}

UI只是锁定,直到longRunningMethod完成。这种方法工作得很好,但旋转器从来没有出现过。

我试着在一个不同的线程上运行所有内容:

代码语言:javascript
运行
复制
public void onButtonClick (android.view.View view){
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(this::longRunningMethod);
}

我在longRunningMethod中添加了旋转器可见性更改内容:

代码语言:javascript
运行
复制
private void longRunningMethod(){
    ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
    progressSpinner.setVisibility(View.VISIBLE);

    // Logic that takes 5-10 seconds to run.

    progressSpinner.setVisibility(View.GONE);
}

当我这样做时,UI没有锁定,但是在longRunningMethod中没有任何工作。旋转器不会显示,逻辑似乎也不工作,虽然这可能只是一个问题,因为这个逻辑没有在非UI线程上发挥的很好。我很困惑,旋转器的能见度将不会从这里更新。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-02-07 21:29:35

考虑到新浪提出的使用线程的建议,这门课现在看起来如下:

代码语言:javascript
运行
复制
public class MainActivity extends AppCompatActivity{
    
    // Irrelevant code (fields, init, other button handlers, etc...)

    private void onButtonClick(android.view.View view){
        LongRunningThread longRunningThread = new LongRunningThread();
        longRunningThread.start();
    }

    private class LongRunningThread extends Thread{
        public void run(){
            runOnUiThread(MainActivity.this::showSpinner);

            // Logic that takes 5-10 seconds to run

            runOnUiThread(MainActivity.this::hideSpinner);
        }
    }

    private void showSpinner(){
        ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
        progressSpinner.setVisibility(View.VISIBLE);
    }

    private void hideSpinner(){
        ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
        progressSpinner.setVisibility(View.GONE);
    }

}

这样做会显示长期运行逻辑运行时的进度旋转器,然后在长期运行逻辑完成后隐藏进度旋转器。UI始终保持响应性,并且不会锁定。

与原始代码相比,它使用线程而不是ExecutorService。它还通过AppCompatActivity.runOnUiThread()运行UI逻辑。

在不锁定UI的情况下,在UI更新的同时执行任何长期运行的任务,似乎解决的方法是创建线程并调用Thread.start()。线程应该包含长期运行的逻辑以及UI逻辑。线程中的UI逻辑必须使用runOnUiThread()运行。

票数 0
EN

Stack Overflow用户

发布于 2022-02-07 20:37:06

对于运行长任务操作,应使用Worker。必须在辅助线程中运行任务,然后将任务结果返回到UI。

第一种方法是使用AsyncTask

AsyncTask的目的是使UI线程能够正确和容易地使用。然而,最常见的用例是集成到UI中,这将导致上下文泄漏、丢失回调或配置更改时崩溃。它在不同版本的平台上也有不一致的行为,吞并了doInBackground的异常,并且不提供太多直接使用执行器的实用工具。

第二种是使用纯线程

所有Android应用程序都使用一个主线程来处理UI操作。从这个主线程调用长时间运行的操作会导致冻结和无响应.例如,如果应用程序从主线程发出网络请求,则会冻结应用程序的UI,直到收到网络响应为止。您可以创建额外的后台线程来处理长期运行的操作,而主线程则继续处理UI更新。

正式文件

最后一个方法是使用柯鲁丁 (只适用于kotlin)

if you are using kotlin i suggest this one otherwise use AsyncTask

只需尝试在其他线程中运行任务并使用类似于回调的接口返回结果

票数 2
EN

Stack Overflow用户

发布于 2022-02-07 20:40:33

首先,我建议熟悉android中的线程:

https://developer.android.com/guide/components/processes-and-threads

然后,有一些库来管理线程。

AsyncTask,Couroutin,Rxjava。。。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71024912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档