Wie aktualisiere ich einige Daten in einer Listenansicht ohne notifyDataSetChanged ()?

Ich versuche eineListView mit einer Liste von Download-Aufgaben.

Die Download-Aufgaben werden in a verwaltetService (DownloadService). Jedes Mal, wenn ein Datenblock empfangen wird, sendet der Task den Fortschritt über aBroadcast, erhalten von derFragment mit demListView (SavedShowListFragment). Bei Erhalt derBroadcast Nachricht aktualisiert das SavedShowListFragment den Fortschritt der Download-Aufgaben im Adapter und löst ausnotifyDataSetChanged().

Jede Zeile in der Liste enthält einProgressBar, einTextView für den Titel der heruntergeladenen Datei und einen für den numerischen Wert des Fortschritts und aButton um den Download anzuhalten / fortzusetzen oder die gespeicherte Show abzuspielen, wenn der Download beendet ist.

Das Problem ist, dass die Pause / Resume / PlayButton reagiert oft nicht (onClick() heißt nicht), und ich denke das liegt daran, dass die ganze Liste sehr häufig mit aktualisiert wirdnotifyDataSetChanged() (Jedes Mal, wenn ein Datenblock empfangen wird, d. h. 1024 Bytes, was viele Male pro Sekunde sein kann, insbesondere wenn mehrere Download-Aufgaben ausgeführt werden).

Ich schätze, ich könnte den Datenblock bei den Download-Aufgaben vergrößern, aber ich denke wirklich, dass meine Methode überhaupt nicht optimal ist!

Könnte sehr häufig anrufennotifyDataSetChanged() mach dasListView Benutzeroberfläche reagiert nicht?

Gibt es eine Möglichkeit, nur einige zu aktualisierenViews in demListView Zeilen, d. h. in meinem Fall dieProgressBar und dasTextView mit dem numerischen Wert des Fortschritts, ohne aufzurufennotifyDataSetChanged(), was aktualisiert die ganze Liste?

So aktualisieren Sie den Fortschritt der Download-Aufgaben in derListViewGibt es eine bessere Option als "getChunk / sendBroadcast / updateData / notifyDataSetChanged"?

Unten sind die relevanten Teile meines Codes.

Download-Aufgabe im Download-Service

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;
    }
} 

Antworten auf die Frage(3)

Ihre Antwort auf die Frage