我有一个ProgressBar in .xml,我想在长时间运行的操作中显示它。我使用
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);若要在某些onButtonClick方法中设置其可见性,请执行以下操作。如果上面的代码是方法中的全部代码,那么它就能正常工作。问题是当我有这样的方法时:
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完成。这种方法工作得很好,但旋转器从来没有出现过。
我试着在一个不同的线程上运行所有内容:
public void onButtonClick (android.view.View view){
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(this::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);
}当我这样做时,UI没有锁定,但是在longRunningMethod中没有任何工作。旋转器不会显示,逻辑似乎也不工作,虽然这可能只是一个问题,因为这个逻辑没有在非UI线程上发挥的很好。我很困惑,旋转器的能见度将不会从这里更新。
发布于 2022-02-07 21:29:35
考虑到新浪提出的使用线程的建议,这门课现在看起来如下:
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()运行。
发布于 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
只需尝试在其他线程中运行任务并使用类似于回调的接口返回结果
发布于 2022-02-07 20:40:33
首先,我建议熟悉android中的线程:
https://developer.android.com/guide/components/processes-and-threads
然后,有一些库来管理线程。
AsyncTask,Couroutin,Rxjava。。。
https://stackoverflow.com/questions/71024912
复制相似问题