【问题标题】:Progress Bar during the loading of a ListView加载 ListView 期间的进度条
【发布时间】:2014-06-02 19:43:58
【问题描述】:

所以,我想在填充 ListView 时显示一个旋转的加载指示器。我成功地实现了进度条,但由于某种原因,它在所有列表显示之前消失了。我想要的是在列表的总加载时间内出现的进度条。基本上,看起来,每个列表一次显示一个,而不是全部加载后一次显示。 我正在做的是 1.创建一个新的自定义适配器类 2. 使用这个适配器类在 AsyncTask 中填充 ListView 3.设置ListView到这个适配器

这工作正常,进度条在所有列表显示之前消失。有人有什么想法吗?

活动类:

public class MainActivity extends ActionBarActivity {

ArrayList<Location> arrayOfLocations;
LocationAdapter adapter;
// public static Bitmap bitmap;
Button refresh;
ProgressBar progress;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    progress=(ProgressBar)findViewById(R.id.progressbar_loading);
    // Construct the data source
    arrayOfLocations = new ArrayList<Location>();

    // Create the adapter to convert the array to views
    adapter = new LocationAdapter(this, arrayOfLocations);

    FillLocations myFill = new FillLocations();
    myFill.execute();



    refresh = (Button) findViewById(R.id.refresh);
    refresh.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            finish();
            startActivity(getIntent());
        }
    });

}


private class FillLocations extends AsyncTask<Integer, Void, String> {
    String msg = "Done";

    protected void onPreExecute() {
        progress.setVisibility(View.VISIBLE);
    }

    // Decode image in background.
    @Override
    protected String doInBackground(Integer... params) {

        String result = "";
        InputStream isr = null;
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://afs.spotcontent.com/"); // YOUR
                                                                                // PHP
                                                                                // SCRIPT
                                                                                // ADDRESS
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            isr = entity.getContent();
            // resultView.setText("connected");
        } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
        }
        // convert response to string
        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(isr, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            isr.close();

            result = sb.toString();
        } catch (Exception e) {
            Log.e("log_tag", "Error  converting result " + e.toString());
        }

        // parse json data
        try {
            JSONArray jArray = new JSONArray(result);

            for (int i = 0; i < jArray.length(); i++) {
                final JSONObject json = jArray.getJSONObject(i);

                try {

                    BitmapWorkerTask myTask = new BitmapWorkerTask(
                            json.getInt("ID"), json);
                    myTask.execute();

                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        } catch (Exception e) {
            // TODO: handle exception
            Log.e("log_tag", "Error Parsing Data " + e.toString());
        }
        return msg;

    }

    protected void onPostExecute(String msg) {
        // Attach the adapter to a ListView
        ListView listView = (ListView) findViewById(R.id.listView1);

        // View header = (View) getLayoutInflater().inflate(
        // R.layout.listview_header, null);
        // listView.addHeaderView(header);

        listView.setAdapter(adapter);
        progress.setVisibility(View.GONE);

    }
}
}

适配器类:

public class LocationAdapter extends ArrayAdapter<Location> {
public LocationAdapter(Context context, ArrayList<Location> locations) {
   super(context, R.layout.item_location, locations);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   // Get the data item for this position
   Location location = getItem(position);    
   // Check if an existing view is being reused, otherwise inflate the view
   if (convertView == null) {
      convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_location, parent, false);
   }

   // Lookup view for data population
   TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
   TextView tvDetails = (TextView) convertView.findViewById(R.id.tvDetails);
   TextView tvDistance = (TextView) convertView.findViewById(R.id.tvDistance);
   TextView tvHours = (TextView) convertView.findViewById(R.id.tvHours);
   ImageView ivIcon = (ImageView) convertView.findViewById(R.id.imgIcon);

   // Populate the data into the template view using the data object
   tvName.setText(location.name);
   tvDetails.setText(location.details);
   tvDistance.setText(location.distance);
   tvHours.setText(location.hours);
   ivIcon.setImageBitmap(location.icon);
   // Return the completed view to render on screen
   return convertView;
}
}

【问题讨论】:

  • 您的 ListView 有多大?如果您的数据来自本地,可能会立即显示进度情况而您什么都看不到
  • 他们不是来自本地,现在有 60 项。但是在显示第一个后该指示符消失。我希望它只有在显示 ALL 时才会消失。我正在努力寻找如何做到这一点

标签: java android listview android-listview android-asynctask


【解决方案1】:

这种行为的原因是您正在启动多个线程。

FillLocations preExecute --> SHOW ProgressBar
BitmapWorkerTask_1 --> new thread
BitmapWorkerTask_2 --> new thread
...
BitmapWorkerTask_N --> new thread

FillLocations postExecute --> HIDE ProgressBar
BitmapWorkerTask_K --> continue execution
BitmapWorkerTask_K+1 --> continue execution

等等

如果您希望列表在全部加载之前一直显示,只需使 BitmapWorker 的处理同步即可。如果您仍想立即显示列表但保留微调器直到它全部完成,则在您的活动中保留一个计数器并在 preexecute 中增加它并通过 setter 在 BitmapWorker 的 postExecute 中减少它。一旦计数器达到 0,移除隐藏进度条。

活动中:

private int asynchCounter = 0;
private void updateCounter(int delta){
    asynchCounter+=delta;
    if(asynchCounter<=0){
        progress.setVisibility(View.GONE);
    }else{
        progress.setVisibility(View.VISIBLE);
    }
}

而不是 BitmapWorkerTask 使用

class CountedBitmapWorkerTask extends BitmapWorkerTask {
protected void onPreExecute() {
    super.onPreExecute();
    updateCounter(1);
}
protected void onPostExecute(String msg) {
        super.onPostExecute();
        updateCounter(-1);

    }
}

【讨论】:

  • 感谢您的回答。我对第一段代码到底在做什么感到困惑。
  • 它跟踪“活动”或“运行”CountedBitmapWorkerTasks 的数量。然后它仅在没有运行时显示进度条,这意味着您的所有图像都已下载
  • 所以对于 BitmapWorkerTask,你提供的代码将在我所拥有的之外,对吗?
  • 你是对的,我更新了调用 super.onPreExecute() 和 super.onPostExecute() 的答案
  • 嗯,我已经实现了这个,我的应用程序冻结了
【解决方案2】:

我遇到了这个确切的问题,为了解决它,我必须写 AsyncTask 完整的监听器。它向 UI 线程发送通知,表明数据已加载并且必须更改某些内容,在这种情况下隐藏 ProgressBar

这是这个应该是什么样子的基本示例。我不确定这在你将它复制到你的项目后是否对你有用,但是你需要完整的监听器,所以在研究了这个案例之后你应该能够找到解决方案。

AsyncTaskCompleteListener.java - 监听器接口。

public interface AsyncTaskCompleteListener {
       public void onTaskComplete();
}

LoadDataTask.java

class LoadDataTask extends AsyncTask<Object, Object, Object> { 
    /* Your object types according to your task. */

    private AsyncTaskCompleteListener callback; // Callback field

    public LoadDataTask(AsyncTaskCompleteListener cb){
        this.callback = cb; 
    }

    @Override
        protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Object doInBackground(String... urls) {
        /* Your task here */
        return result;
    }

    @Override
    protected void onPostExecute(Object o) {
           callback.onTaskComplete(); // Set the Callback
    }
}

MainActivity.java

   public class MainActivity implements AsyncTaskCompleteListener{
       /* ...Other methods and fields... */


       /* onTaskComplete method which fires after your data is loaded. */
       @Override
       public void onTaskComplete(){
           // Hide ProgressBar
       }
   }

【讨论】:

  • 感谢托尼的回答。我似乎无法正常工作,您是否有任何链接指向您获得此信息的位置,以便我可以阅读它?谢谢
  • 很抱歉没有展开。我从我自己的项目中得到了这个,但这里有一些关于类似案例的细节。 jameselsey.co.uk/blogs/techblog/…
【解决方案3】:

自插:https://github.com/horvste/EasyWebPageDownloadForAndroid

这会将线程与实现分开并解决您的问题。这与 Tony 的建议非常相似,只是它已经为您实现了。

Github 自述文件:

非常适合连接到 REST API、HTML 解析和许多其他用途。使用这个库很容易:

  1. 创建一个实现 OnProgressUpdate 的类

公共类 SampleClass 实现 OnProgressUpdate {

    @Override
    public void onUpdate(Integer percentProgress) {

    }

    @Override
    public void onUpdateFailure() {

    }

    @Override
    public void onSuccess(StringBuilder result) {

    }

    @Override
    public void onFailure() {

    }
}

} 实例化 DownloadWebPage 对象

DownloadWebPage webPage = new DownloadWebPage(new SampleClass(), myUrl);

从 DownloadWebPage 调用 .downloadHtml()

webPage.downloadHtml();

此外,如果 asynchtask 正确更新并且项目数量很大,请查看此处: listing a listview is taking too much time and memory in android

另一种选择是只列出一定数量的项目,然后有一个下一页按钮或手势来处理 ListView 加载太慢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2017-06-12
    • 2012-06-08
    相关资源
    最近更新 更多