Android progressBar setVisibility()不起作用

Posted

技术标签:

【中文标题】Android progressBar setVisibility()不起作用【英文标题】:Android progressBar setVisibility() not working 【发布时间】:2017-04-07 00:59:46 【问题描述】:

有人可以帮我理解为什么progressBar.setVisibility() 在使用CountDownTimer 时有效,但在下载async 时无效?事实上,async 下载的第一个 Toast 甚至没有显示,即使第二个 onPostExecute() 显示。下面是一个工作的,或者说不工作的演示。非常感谢。

我的MainActivity

public class MainActivity extends AppCompatActivity 

    ProgressBar progressBar;

    int[] items =  12982418, 12998698, 12993549, 12995125, 12987537, 12993021, 12991986, 13008408, 12983417, 12986060, 12998395, 12985644, 13014731, 12986433, 12985074, 12994455, 12994262, 12986759, 13011932, 13005211, 12993521, 12987900, 12992623, 12981736, 12986649, 12991524, 13000035, 12989278, 13013868, 13009417, 13013327, 12981605, 12985768, 13000158, 13015035, 13002596, 13015944, 12997893, 12999767, 13010949, 12996835, 13013517, 13006555, 13013143, 13010016, 13005792, 13016948, 13007235, 12998343, 12987102 ;
    int counter;

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

        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressBar.setIndeterminate(true);
        progressBar.setKeepScreenOn(true);
        progressBar.setVisibility(View.INVISIBLE);
    

    public void actionTimer(View view) 
        Toast.makeText(this, "starting progressBar - CountDownTimer", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.VISIBLE);
        new CountDownTimer(5000, 500) 
            @Override
            public void onTick(long millisUntilFinished) 
            
            @Override
            public void onFinish() 
                progressBar.setVisibility(View.INVISIBLE);
                Toast.makeText(getApplicationContext(), "timer done", Toast.LENGTH_SHORT).show();
            
        .start();
    

    public void actionJson(View view) 
        Toast.makeText(this, "starting progressBar - json fetch", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.VISIBLE);

        String urlTemplate = "https://hacker-news.firebaseio.com/v0/item/___ITEM_NUMBER___.json?print=pretty";
        counter = 0;

        for (int i = 0; i < items.length; i++) 
            String url = urlTemplate.replaceAll("___ITEM_NUMBER___", String.valueOf(items[i]));
            //Log.i("thisDoesNotWork", url);

            DownloadJson downloadJson = new DownloadJson();
            try 
                downloadJson.execute(url).get();
             catch (InterruptedException e) 
                e.printStackTrace();
             catch (ExecutionException e) 
                e.printStackTrace();
            
        
    

    public class DownloadJson extends AsyncTask<String, Void, String> 

        @Override
        protected String doInBackground(String... params) 
            Log.i("DownloadJson", "url=" + params[0]);

            URL url;
            HttpURLConnection urlConnection = null;

            try 
                url = new URL(params[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = urlConnection.getInputStream();

                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder resultBuilder = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) 
                    resultBuilder.append(line).append("\n");
                
                //Log.i("DownloadJson", "resultBuilder.length()=" + resultBuilder.length());
                return resultBuilder.toString();

             catch (Exception e) 
                e.printStackTrace();
                return "\"status\" : \"Hacker News json download failed\"";
            
        

        @Override
        public void onPostExecute(String s) 
            super.onPostExecute(s);
            counter += 1;
            if (counter == items.length) 
                progressBar.setVisibility(View.INVISIBLE);
                Toast.makeText(getApplicationContext(), "download done", Toast.LENGTH_SHORT).show();
            
        
    

我的XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_
    android:layout_
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.plaudev.progressbar.MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_
        android:layout_
        android:gravity="center_vertical">

        <Button
            android:text="@string/timer"
            android:layout_
            android:layout_
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:id="@+id/buttonTimer"
            android:layout_weight="1"
            android:onClick="actionTimer"
            android:layout_margin="25dp" />

        <Button
            android:text="@string/json"
            android:layout_
            android:layout_
            android:id="@+id/buttonJson"
            android:layout_weight="1"
            android:onClick="actionJson"
            android:layout_margin="25dp" />
    </LinearLayout>

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_
        android:layout_
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/progressBar" />
</RelativeLayout>

【问题讨论】:

您的 doInBackground 任务需要多长时间才能完成?可能是它正在完成并且进度条在 UI 中甚至可见之前就设置为不可见 onPostExecute 在 UI 线程上运行意味着他是对的。而不是 inVisible 尝试使用 GONE。在您的情况下,您应该始终使用消失 谢谢你们。我已经尝试过 GONE 但这不起作用。顺便说一句,这并不能解释为什么 CountDownTimer 方法适用于相同的 INVISIBLE。下载在几秒钟内完成。 你确定 `if (counter == items.length)` 它通过了吗? 下载按钮实现在哪里? 【参考方案1】:

答案是将整个for循环在onClickactionJson()中放入一个工作线程中,如下noted here:

public void actionJson(View view) 
        Toast.makeText(this, "starting progressBar - json fetch", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.VISIBLE);

        final String urlTemplate = "https://hacker-news.firebaseio.com/v0/item/___ITEM_NUMBER___.json?print=pretty";
        counter = 0;

        // simply put it in a worker thread does the job
        new Thread(new Runnable() 
            public void run() 
                for (int i = 0; i < items.length; i++) 
                    String url = urlTemplate.replaceAll("___ITEM_NUMBER___", String.valueOf(items[i]));
                    //Log.i("actionJson", url);
                    DownloadJson downloadJson = new DownloadJson();
                    try 
                        downloadJson.execute(url).get();
                     catch (InterruptedException e) 
                        e.printStackTrace();
                     catch (ExecutionException e) 
                        e.printStackTrace();
                    
                
            
        ).start();
    

因此,即使最初定义的 for 循环确实单独生成了一大堆 asyncTasks,它仍然以某种方式阻塞了主线程。

【讨论】:

以上是关于Android progressBar setVisibility()不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Android控件第4类——ProgressBar

ProgressBar中的android:progressBarStyle属性是啥意思?

一起学Android之ProgressBar

[ 转] [Android]多式样ProgressBar

android的Progressbar怎么用

android布局文件里的ProgressBar长形进度条怎么自定义样式