简体   繁体   English

Android:如何在执行长时间运行的操作时显示微调器?

[英]Android: How to show a spinner while performing a long-running operation?

I have a ProgressBar in.xml that I want to show when a long-running operation.我有一个 ProgressBar in.xml,我想在长时间运行的操作时显示它。 I use我用

ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);

to set its visibility in some onButtonClick method.在某些 onButtonClick 方法中设置其可见性。 If the above code is all that is in the method, it works just fine.如果上面的代码就是方法中的全部,那么它工作得很好。 The problem is when I have a method like this:问题是当我有这样的方法时:

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);
}

The UI just locks up until longRunningMethod is done. UI 只是锁定,直到 longRunningMethod 完成。 That method works just fine, but the spinner never shows.该方法工作得很好,但微调器从未显示。

I tried running everything on a different thread with this:我尝试用这个在不同的线程上运行所有东西:

public void onButtonClick (android.view.View view){
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(this::longRunningMethod);
}

And I added the spinner visibility changing stuff to longRunningMethod:我将微调器可见性更改内容添加到 longRunningMethod:

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);
}

When I do this, the UI doesn't lock up, but nothing in longRunningMethod works.当我这样做时,UI 不会锁定,但 longRunningMethod 中的任何内容都不起作用。 The spinner won't show and the logic also doesn't seem to work, although this may just be a problem with that logic not playing nice on not-the-UI-thread.微调器不会显示,逻辑似乎也不起作用,尽管这可能只是逻辑在非 UI 线程上运行不佳的问题。 I am very confused that the spinner visibility won't update from here though.我很困惑微调器的可见性不会从这里更新。

For running long task operations, you should use Worker Thread.要运行长任务操作,您应该使用工作线程。 You must run your task in worker thread and then return task results to UI.您必须在工作线程中运行您的任务,然后将任务结果返回给 UI。

First method is using AsyncTask :第一种方法是使用AsyncTask

AsyncTask was intended to enable proper and easy use of the UI thread. AsyncTask 旨在使 UI 线程的使用变得正确和容易。 However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes.然而,最常见的用例是集成到 UI 中,这会导致上下文泄漏、错过回调或配置更改时崩溃。 It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground, and does not provide much utility over using Executors directly.它还在不同版本的平台上具有不一致的行为,吞噬来自 doInBackground 的异常,并且与直接使用 Executors 相比没有提供太多实用性。

Second one is using Pure Thread第二个是使用纯线程

All Android apps use a main thread to handle UI operations.所有 Android 应用程序都使用主线程来处理 UI 操作。 Calling long-running operations from this main thread can lead to freezes and unresponsiveness.从此主线程调用长时间运行的操作可能会导致冻结和无响应。 For example, if your app makes a.network request from the main thread, your app's UI is frozen until it receives the.network response.例如,如果您的应用程序从主线程发出 .network 请求,您的应用程序的 UI 将被冻结,直到它收到 .network 响应。 You can create additional background threads to handle long-running operations while the main thread continues to handle UI updates.您可以创建额外的后台线程来处理长时间运行的操作,同时主线程继续处理 UI 更新。

official document官方文件

and the last method is using Coroutine (just for kotlin)最后一种方法是使用协程(仅适用于科特林)

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

Just try to run your tasks in other Thread and return results by using a callback like interface只需尝试在其他线程中运行您的任务并使用类似接口的回调返回结果

first of all I recommend that get familiar with threads in android:首先,我建议熟悉 android 中的线程:

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

then, there is some lib to manage threads然后,有一些库来管理线程

AsyncTask, Couroutin, Rxjava.异步任务、协程、Rxjava。 . . . .

Taking Sina's suggestion to use a Thread, the class now looks like:采取新浪的建议使用线程,class 现在看起来像:

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);
    }

}

Doing this shows the progress spinner while the long-running logic is running and then hides the progress spinner after the long-running logic has completed.这样做会在长时间运行的逻辑运行时显示进度微调器,然后在长时间运行的逻辑完成后隐藏进度微调器。 The UI stays responsive throughout and doesn't lock up. UI 始终保持响应并且不会锁定。

Compared to the original code, this uses Thread instead of ExecutorService.与原始代码相比,这里使用了 Thread 而不是 ExecutorService。 It also runs UI logic via AppCompatActivity.runOnUiThread().它还通过 AppCompatActivity.runOnUiThread() 运行 UI 逻辑。

It would seem the answer to doing any long-running tasks alongside UI updates, without locking up the UI, is to create a Thread and call Thread.start().在不锁定 UI 的情况下,在 UI 更新的同时执行任何长时间运行的任务的答案似乎是创建一个 Thread 并调用 Thread.start()。 The Thread should contain the long-running logic as well as the UI logic. Thread 应该包含长时间运行的逻辑以及 UI 逻辑。 The UI logic within that Thread must be run using runOnUiThread().该线程中的 UI 逻辑必须使用 runOnUiThread() 运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM