Jak zaktualizować niektóre dane w Listview bez użycia notifyDataSetChanged ()?
Próbuję stworzyćListView
z listą zadań pobierania.
Zadania pobierania są zarządzane w aService
(DownloadService). Za każdym razem, gdy odbierany jest fragment danych, zadanie wysyła postęp przezBroadcast
, otrzymany przezFragment
zawierająceListView
(SavedShowListFragment). Po otrzymaniuBroadcast
wiadomość, SavedShowListFragment aktualizuje postęp zadań pobierania w adapterze i wyzwalanotifyDataSetChanged()
.
Każdy wiersz na liście zawieraProgressBar
, aTextView
tytuł pobieranego pliku i tytuł dla wartości liczbowej postępu oraz aButton
wstrzymać / wznowić pobieranie lub odtworzyć zapisany pokaz po zakończeniu pobierania.
Problem polega na tym, że pauza / wznowienie / odtwarzanieButton
często nie odpowiada (onClick()
nie jest wywoływany) i myślę, że to dlatego, że cała lista jest bardzo często aktualizowana za pomocąnotifyDataSetChanged()
(za każdym razem, gdy odbierany jest fragment danych, tj. 1024 bajty, co może być wiele razy na sekundę, zwłaszcza gdy uruchomionych jest kilka zadań pobierania).
Myślę, że mogę zwiększyć rozmiar fragmentu danych w zadaniach pobierania, ale naprawdę uważam, że moja metoda nie jest wcale optymalna!
Może dzwonić bardzo częstonotifyDataSetChanged()
ZróbListView
Interfejs użytkownika nie odpowiada?
Czy jest jakiś sposób na aktualizację tylko niektórychViews
wListView
wiersze, czyli w moim przypadkuProgressBar
iTextView
z wartością numeryczną postępu, bez wywoływanianotifyDataSetChanged()
, która aktualizuje całą listę?
Aby zaktualizować postęp zadań pobierania wListView
, czy istnieje lepsza opcja niż „getChunk / sendBroadcast / updateData / notifyDataSetChanged”?
Poniżej znajdują się odpowiednie części mojego kodu.
Pobierz zadanie w usłudze pobierania
public class DownloadService extends Service {
//...
private class DownloadTask extends AsyncTask<SavedShow, Void, Map<String, Object>> {
//...
@Override
protected Map<String, Object> doInBackground(SavedShow... params) {
//...
BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
if(!this.isCancelled()){
outputStream.write(data, 0, x);
downloaded += x;
MyApplication.dbHelper.updateSavedShowProgress(savedShow.getId(), downloaded);
Intent intent_progress = new Intent(ACTION_UPDATE_PROGRESS);
intent_progress.putExtra(KEY_SAVEDSHOW_ID, savedShow.getId());
intent_progress.putExtra(KEY_PROGRESS, downloaded );
LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent_progress);
}
else{
break;
}
}
//...
}
//...
}
}
SavedShowListFragment
public class SavedShowListFragment extends Fragment {
//...
@Override
public void onResume() {
super.onResume();
mAdapter = new SavedShowAdapter(getActivity(), MyApplication.dbHelper.getSavedShowList());
mListView.setAdapter(mAdapter);
//...
}
private ServiceConnection mDownloadServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// Get service instance
DownloadServiceBinder binder = (DownloadServiceBinder) service;
mDownloadService = binder.getService();
// Set service to adapter, to 'bind' adapter to the service
mAdapter.setDownloadService(mDownloadService);
//...
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// Remove service from adapter, to 'unbind' adapter to the service
mAdapter.setDownloadService(null);
}
};
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(DownloadService.ACTION_UPDATE_PROGRESS)){
mAdapter.updateItemProgress(intent.getLongExtra(DownloadService.KEY_SAVEDSHOW_ID, -1),
intent.getLongExtra(DownloadService.KEY_PROGRESS, -1));
}
//...
}
};
//...
}
SavedShowAdapter
public class SavedShowAdapter extends ArrayAdapter<SavedShow> {
private LayoutInflater mLayoutInflater;
private List<Long> mSavedShowIdList; // list to find faster the position of the item in updateProgress
private DownloadService mDownloadService;
private Context mContext;
static class ViewHolder {
TextView title;
TextView status;
ProgressBar progressBar;
DownloadStateButton downloadStateBtn;
}
public static enum CancelReason{ PAUSE, DELETE };
public SavedShowAdapter(Context context, List<SavedShow> savedShowList) {
super(context, 0, savedShowList);
mLayoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
mContext = context;
mSavedShowIdList = new ArrayList<Long>();
for(SavedShow savedShow : savedShowList){
mSavedShowIdList.add(savedShow.getId());
}
}
public void updateItemProgress(long savedShowId, long progress){
getItem(mSavedShowIdList.indexOf(savedShowId)).setProgress(progress);
notifyDataSetChanged();
}
public void updateItemFileSize(long savedShowId, int fileSize){
getItem(mSavedShowIdList.indexOf(savedShowId)).setFileSize(fileSize);
notifyDataSetChanged();
}
public void updateItemState(long savedShowId, int state_ind, String msg){
SavedShow.State state = SavedShow.State.values()[state_ind];
getItem(mSavedShowIdList.indexOf(savedShowId)).setState(state);
if(state==State.ERROR){
getItem(mSavedShowIdList.indexOf(savedShowId)).setError(msg);
}
notifyDataSetChanged();
}
public void deleteItem(long savedShowId){
remove(getItem((mSavedShowIdList.indexOf(savedShowId))));
notifyDataSetChanged();
}
public void setDownloadService(DownloadService downloadService){
mDownloadService = downloadService;
notifyDataSetChanged();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
v = mLayoutInflater.inflate(R.layout.saved_show_list_item, parent, false);
holder = new ViewHolder();
holder.title = (TextView)v.findViewById(R.id.title);
holder.status = (TextView)v.findViewById(R.id.status);
holder.progressBar = (ProgressBar)v.findViewById(R.id.progress_bar);
holder.downloadStateBtn = (DownloadStateButton)v.findViewById(R.id.btn_download_state);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.title.setText(getItem(position).getTitle());
Integer fileSize = getItem(position).getFileSize();
Long progress = getItem(position).getProgress();
if(progress != null && fileSize != null){
holder.progressBar.setMax(fileSize);
holder.progressBar.setProgress(progress.intValue());
holder.status.setText(Utils.humanReadableByteCount(progress) + " / " +
Utils.humanReadableByteCount(fileSize));
}
holder.downloadStateBtn.setTag(position);
SavedShow.State state = getItem(position).getState();
/* set the button state */
//...
/* set buton onclicklistener */
holder.downloadStateBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int position = (Integer) v.getTag();
SavedShow.State state = getItem(position).getState();
if(state==SavedShow.State.DOWNLOADING){
getItem(position).setState(SavedShow.State.WAIT_PAUSE);
notifyDataSetChanged();
mDownloadService.cancelDownLoad(getItem(position).getId(), CancelReason.PAUSE);
}
else if(state==SavedShow.State.PAUSED || state==SavedShow.State.ERROR){
getItem(position).setState(SavedShow.State.WAIT_DOWNLOAD);
notifyDataSetChanged();
mDownloadService.downLoadFile(getItem(position).getId());
}
if(state==SavedShow.State.DOWNLOADED){
/* play file */
}
}
});
return v;
}
}