为什么进度条不出现?

Why the progress bar does not appear?

我正在做的是创建一个 activity 从 api 请求 JSON。 我需要在处理过程中显示进度条。 这是我的 xml 代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WebService"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tips"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:singleLine="false"
        android:text="Tips: Press the button to get a random web link, then click the widget to open that link in a web view." />


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:onClick="runOnNewThread"
            android:text="Request Link"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:visibility="visible"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/button"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.538"
            />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <TextView
        android:id="@+id/result_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:singleLine="false"
        android:text="" />

</LinearLayout>

这是我的 activity

public class WebService extends AppCompatActivity {
    private static final String TAG = "WebServiceActivity";

    Handler handler = new Handler();
    TextView resultText;
    ProgressBar progressBar;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_service);

        resultText = (TextView) findViewById(R.id.result_textview);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressBar.setVisibility(View.INVISIBLE);
    }

    //button
    public void runOnNewThread(View view) throws InterruptedException {
        progressBar.setVisibility(View.VISIBLE);
        runnableThread runnableThread = new runnableThread();
        Thread thread = new Thread(runnableThread);
        thread.start();
        thread.join();
        Toast.makeText(this, "Thread ends", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.GONE);
    }

    class runnableThread implements Runnable{

        @Override
        public void run() {
            JSONArray jArray;
            try {
                String url = NetworkUtil.validInput("https://api.publicapis.org/entries");
                String resp = NetworkUtil.httpResponse(new URL(url));
                JSONObject jObject = new JSONObject(resp);
                jArray = jObject.getJSONArray("entries");
                JSONObject resultObj = jArray.getJSONObject(new Random().nextInt(1421));
                String API = resultObj.getString("API");
                String description = resultObj.getString("Description");
                String link = resultObj.getString("Link");

                handler.post(()->{
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    resultText.setText("");
                    resultText.append(API+"\n");
                    resultText.append(description+"\n");
                    resultText.append(link+"\n");
                });

            } catch (NetworkUtil.MyException e) {
                Toast.makeText(getApplication(),e.toString(),Toast.LENGTH_SHORT).show();
            } catch (MalformedURLException e) {
                Log.e(TAG,"MalformedURLException");
                e.printStackTrace();
            } catch (ProtocolException e) {
                Log.e(TAG,"ProtocolException");
                e.printStackTrace();
            } catch (IOException e) {
                Log.e(TAG,"IOException");
                e.printStackTrace();
            } catch (JSONException e) {
                Log.e(TAG,"JSONException");
                e.printStackTrace();
            }
        }




    }

}

吐司效果很好,每次点击按钮后都会出现。 当我在runOnNewThread函数中注释progressBar.setVisibility(View.GONE)时,进度条会出现但不会消失,但如果我在这里留下setVisibility,进度条将永远不会出现。 这是怎么回事?

在这里你把可见性消失的代码放在后台线程中它不会工作因为视图不会 运行 在后台线程中你应该在 ui 线程

中提供监听器
   public void runOnNewThread(View view) throws InterruptedException {
                progressBar.setVisibility(View.VISIBLE);
                runnableThread runnableThread = new runnableThread();
                Thread thread = new Thread(runnableThread);
                thread.start();
                thread.join();
        // here is the problem Progress bar is a view  , vie canton run in background thread
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(this, "Thread ends", Toast.LENGTH_SHORT).show();
                progressBar.setVisibility(View.GONE);
            }
        });
            }

您似乎在收到祝酒词后选择了使进度条消失的选项。

progressBar.setVisibility(View.GONE);

您可以尝试使用

progressBar.setVisibility(View.VISIBLE);

你的问题是你在 runOnNewThread() 中创建的线程没有用:你创建一个新的 Thread,启动它 然后等到线程完成 .而不是写

    Thread thread = new Thread(runnableThread);
    thread.start();
    thread.join();

你也可以写

    runnableThread.run();

效果一样

因为您正在阻塞 UI 线程,所以您在 UI 有时间显示进度条之前调用 progressBar.setVisibility(View.GONE);


解决方法是让新线程运行独立:

public void runOnNewThread(View view) throws InterruptedException {
    progressBar.setVisibility(View.VISIBLE);
    runnableThread runnableThread = new runnableThread();
    Thread thread = new Thread(runnableThread);
    thread.start();
}

并将Toast.makeText(...).show();progressBar.setVisibility(View.GONE);移动到独立任务的末尾:

class runnableThread implements Runnable {
    @Override
    public void run() {
        JSONArray jArray;
        try {
            // I didn't include all the code here
        } catch (NetworkUtil.MyException e) {
            WebService.this.runOnUiThread(() ->
                Toast.makeText(getApplication(), e.toString(), Toast.LENGTH_SHORT).show()
            );
        // I also didn't include all the catch clauses
        } finally {
            WebService.this.runOnUiThread(() -> {
                Toast.makeText(WebService.this, "Thread ends", Toast.LENGTH_SHORT).show();
                progressBar.setVisibility(View.GONE);
            });
        }
    }