Комбинация сервисов, 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. Да уж!

Другие вопросы по тегам