[英]Progress Bar during the loading of a ListView
因此,我想在填充ListView時顯示旋轉的加載指示器。 我已經成功實現了進度條,但是由於某種原因,它在顯示所有列表之前就消失了。 我想要的是在清單的TOTAL加載時間內出現的進度欄。 基本上,看起來,每個清單一次顯示一次,而不是一次全部顯示。 我正在做的是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;
}
}
該行為的原因是您正在啟動多個線程。
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的處理同步即可。 如果您仍然想立即顯示列表,但要保持微調框直到全部完成,則在活動中保留一個計數器,並通過設置器在BitmapWorker的postExecute中增加它,並在它的postExecute中減少它。 一旦計數器達到0,請刪除隱藏progressBar。
活動中:
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);
}
}
我遇到了這個確切的問題,要解決它,我必須編寫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
}
}
自我插件: https : //github.com/horvste/EasyWebPageDownloadForAndroid
這將使線程與實現分離,並解決您的問題。 除了已經為您實現之外,這與Tony建議的非常相似。
Github自述文件:
非常適合連接REST API,HTML解析和許多其他用途。 使用這個庫很容易:
公共類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正確更新,並且項目數量很大,請看這里: 列出listview在android中占用太多時間和內存
另一個選擇是僅列出一定數量的項目,然后使用下一頁按鈕或手勢來處理ListView加載太慢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.