Комбинация сервисов, ProgressBar, Gridview (и его уведомлений об изменении) QuickAction-реализации идет не так
(Извините за мои ошибки в правописании)
У меня проблема в сочетании некоторых вещей:
Я использую GridView для загрузки содержимого шоу из базы данных. OnClick загружается файл, который можно просмотреть позже. Это около 20 МБ. Эта загрузка выполняется службой.
Каждый элемент в gridView содержит индикатор в макете. этот индикатор просто отображается, если элемент загружается в фоновом режиме через сервис.
Сервис отправляет широковещательную рассылку о прогрессе загрузки, Intent содержит идентификатор элемента, чтобы найти его в данных Адаптера для просмотра сетки.
BroadcastReceiver не зарегистрирован в моей Активности для получения Обновления Прогресса (помните, возможна одновременная загрузка), который вызывает функцию "setProgress" в gridview-адаптере
public void setProgress(long id, int progress)
{
for (int i = 0;i < list.size();i++)
{
if (list.get(i).getId() == id)
{
list.get(i).setProgress(progress);
notifyDataSetChanged();
}
}
}
На данный момент все работает отлично.
Дополнительно я использую реализацию QuickAction с http:// www. londatiga.net/it/how-to-create-quickaction-dialog-in-android/ (Пробелы, потому что я не могу опубликовать более двух гиперссылок)
Теперь возникает проблема:
Иногда, я полагаю, когда вызывается notifydatasetchanged и пользователь нажимает на элемент, быстрое действие отображается в неправильной позиции.
Чтобы сделать это более понятным, вот две картинки:
Первый - это то, что должно произойти (в этом случае щелчок по первому элементу сетки) http://dl.dropbox.com/u/9031500/expected.png
На втором рисунке показано, что происходит иногда (только когда выполняются некоторые загрузки, поэтому я предполагаю, что это происходит из-за "notifydatasetchanged" и перестройки представлений). Это также был щелчок по первому элементу, к сожалению, быстрое действие показано для четвертого элемента: http://dl.dropbox.com/u/9031500/wrong.png
Это моя реализация в моей деятельности для вызова быстрого действия:
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showQuickAction(view, position);
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showQuickAction(view, position);
return true;
}
private void showQuickAction(View view, int position)
{
RelativeLayout facsimile = (RelativeLayout) view.findViewById(R.id.lib_item_image_layout);
Log.i(LOGTAG, "Position:"+position);
currentPaper = TZReader.paperDao.load(libraryAdapter.getItemId(position));
Log.i(LOGTAG,"Set CurrentPaper:"+currentPaper.getTitelWithDate());
ActionItem downloadItem = new ActionItem(ACTION_ITEM_DOWNLOAD, "Download", getResources().getDrawable(R.drawable.ic_action_download));
ActionItem readItem = new ActionItem(ACTION_ITEM_READ, "Lesen", getResources().getDrawable(R.drawable.ic_action_read));
ActionItem deleteItem = new ActionItem(ACTION_ITEM_DELETE, "Löschen", getResources().getDrawable(R.drawable.ic_action_delete));
ActionItem cancelItem = new ActionItem(ACTION_ITEM_CANCEL, "Abbrechen", getResources().getDrawable(R.drawable.ic_action_cancel));
QuickAction mQuickAction = new QuickAction(this, QuickAction.HORIZONTAL);
switch (currentPaper.getState())
{
case Paper.DOWNLOADED_READABLE:
mQuickAction.addActionItem(readItem);
mQuickAction.addActionItem(deleteItem);
break;
case Paper.DOWNLOADED_BUT_UPDATE:
mQuickAction.addActionItem(downloadItem);
mQuickAction.addActionItem(deleteItem);
break;
case Paper.IS_DOWNLOADING:
mQuickAction.addActionItem(cancelItem);
break;
case Paper.NOT_DOWNLOADED:
mQuickAction.addActionItem(downloadItem);
break;
}
//Set listener for action item clicked
mQuickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
@Override
public void onItemClick(QuickAction source, int pos, int actionId) {
//here we can filter which action item was clicked with pos or actionId parameter
switch(actionId)
{
case ACTION_ITEM_DOWNLOAD:
Intent downloadIntent = new Intent(getApplicationContext(), DownloadService.class);
downloadIntent.putExtra(DownloadService.PARAMETER_PAPER_DB_ID_LONG, currentPaper.getId());
startService(downloadIntent);
break;
case ACTION_ITEM_READ:
break;
case ACTION_ITEM_DELETE:
DeleteAlertDialogFragment newFragment = DeleteAlertDialogFragment.newInstance(currentPaper.getId());
newFragment.setStyle(SherlockDialogFragment.STYLE_NO_TITLE,0);
newFragment.show(getSupportFragmentManager(), "dialog");
break;
case ACTION_ITEM_CANCEL:
break;
}
}
});
mQuickAction.show(facsimile);
}
Может быть, у кого-то есть идеи или советы для меня, как я могу справиться с этой проблемой! Спасибо за миллион заранее!
1 ответ
Я нашел решение для моей проблемы.
Решение состоит в том, что я реализую свой собственный ProgressBar, который теперь содержит BroadcastListerner, и устанавливаю прогресс для каждого элемента. Таким образом, я могу изменить значение без необходимости называть "notifydatasetchanged". идеально подходит для моих нужд. Я все еще не удивлен, если это хорошее решение, но оно работает хорошо.
Вот код для Progressbar:
public class ListeningProgressBar extends ProgressBar {
public ListeningProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
final IntentFilter intentDownloadProgressFilter = new IntentFilter(DownloadService.DOWNLOAD_PROGRESS_BROADCAST);
private long paperId = 0;
private boolean isReceiverRegistered = false;
@Override
protected void onAttachedToWindow() {
getContext().getApplicationContext().registerReceiver(downloadProgressBroadcastReceiver,intentDownloadProgressFilter);
isReceiverRegistered = true;
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
if (isReceiverRegistered)
{
getContext().getApplicationContext().unregisterReceiver(downloadProgressBroadcastReceiver);
isReceiverRegistered = false;
}
super.onDetachedFromWindow();
}
private BroadcastReceiver downloadProgressBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadService.PARAMETER_PAPER_DB_ID_LONG, -1);
int progressValue = intent.getIntExtra(DownloadService.PARAMETER_PAPER_PROGRESS_INT, 0);
if (paperId == id)
{
setProgress(progressValue);
}
}
};
public long getPaperId() {
return paperId;
}
public void setPaperId(long paperId) {
this.paperId = paperId;
}
}
Я просто использую его как обычный пользовательский вид в моем XML-макете. В адаптере я установил идентификатор своего контента, чтобы дать получателю данные только для установки прогресса, если это правильный контент.
В конце концов, моя проблема решена, прогресс обновляется без необходимости вызывать notifydatasetchanged. Да уж!