我正在编写一个广播应用程序,用户可以在其中下载一些节目。

当用户单击音频播放器上的下载按钮时,该节目将以SavedShow的形式添加到数据库中。

用户可以在SavedShow中看到SavedShowsFragment实例的状态,该实例显示ListView以及保存的节目列表。

ListView的每一行中都有保存的节目的标题,状态(NOT_STARTED/DOWNLOADING/PAUSED/DOWNLOADED/ERROR),ProgressBarButton,用于暂停下载,恢复下载或播放文件(如果已下载)。

现在,我不知道如何将列表的每个项目绑定到我的DownloadService,也不知道如何在适配器中实现来自DownloadService的侦听器。

基本上,我希望每一行:


从我的DownloadTask.onProgressUpdateDownloadService获取进度
下载完成或出现错误时,DownloadService会通知您
DownloadService调用方法(例如,如果正在下载文件,则在单击按钮时暂停下载)


有人可以帮忙吗?

SavedShowsFragment

public class SavedShowsFragment extends Fragment {

    private DownloadService mDownloadService;
    private boolean mBoundToDownloadService = false;

    private ListView mListView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.saved_show_list, container, false);
    }

    @Override
    public void onActivityCreated (Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);
    }

    private void setSavedShowList(){

        mListView = (ListView) getView().findViewById(R.id.listview);

        SavedShowAdapter adapter = new SavedShowAdapter(getActivity(), MyApplication.dbHelper.getSavedShowList());
        mListView.setAdapter(adapter);
    }

    @Override
    public void onCreate (Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        // start services

        Intent intent = new Intent(getActivity(), DownloadService.class);
        getActivity().startService(intent);
    }

    @Override
    public void onResume() {
        super.onResume();

        setSavedShowList();

        // bind service

        Intent intent = new Intent(getActivity(), StreamService.class);
        getActivity().bindService(intent, mDownloadServiceConnection, Context.BIND_AUTO_CREATE);

    }

    @Override
    public void onPause() {

        // unbind service

        if (mBoundToDownloadService) {
            getActivity().unbindService(mDownloadServiceConnection);
        }

        super.onPause();
    }

    private ServiceConnection mDownloadServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {

            /*
             * Get service instance
             */

            DownloadServiceBinder binder = (DownloadServiceBinder) service;
            mDownloadService = binder.getService();
            mBoundToDownloadService = true;

            /*
             * Start download for NOT_STARTED saved show
             */

            for(SavedShow savedShow : MyRadioApplication.dbHelper.getSavedShowList()){

                if(savedShow.getState()==SavedShow.State.NOT_STARTED){
                    mDownloadService.downLoadFile(savedShow.getId());
                }
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBoundToDownloadService = false;
        }
    };

}


SavedShowAdapter

public class SavedShowAdapter extends ArrayAdapter<SavedShow> {

    private LayoutInflater mLayoutInflater;

    static class ViewHolder {
        TextView title, status;
        ProgressBar progressBar;
        Button downloadStateBtn;
    }


    public SavedShowAdapter(Context context, List<SavedShow> saved_show_list) {
        super(context, 0, saved_show_list);
        mLayoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        View v = convertView;

        if (v == null) {

            v = mLayoutInflater.inflate(R.layout.podcast_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 = (Button)v.findViewById(R.id.btn_download_state);

            v.setTag(holder);
        } else {
            holder = (ViewHolder) v.getTag();
        }

        holder.downloadStateBtn.setTag(position);

        // TODO set button state according to item state

        holder.downloadStateBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                int position = (Integer) v.getTag();

                    // TODO call DownloadService method (download or pause) according to the state
            }
        });

        //holder.title.setText(getItem(position).getTitle());

        // do a publish progress listener for progress bar

        return v;
    }
}


下载服务

public class DownloadService extends Service {

    private static final int MAX_DOWNLOAD_TASKS = 10;

    private final IBinder mBinder = new DownloadServiceBinder();

    private class MaxDownloadsException extends Exception
    {

        private static final long serialVersionUID = 6859017750734917253L;

        public MaxDownloadsException()
        {
            super(getResources().getString(R.string.max_downloads));
        }
    }

    private List<DownloadTask> mTaskList= new ArrayList<DownloadTask>();

    private void addTaskToList(DownloadTask task) throws MaxDownloadsException {

        if(mTaskList.size() < MAX_DOWNLOAD_TASKS+1){
            mTaskList.add(task);
        }
        else{
            throw new MaxDownloadsException();
        }
    }

    private void removeTaskToList(DownloadTask task) {

        mTaskList.remove(task);

        // if no more tasks, stop service

        if(mTaskList.size() == 0){
            stopSelf();
        }

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_NOT_STICKY;
    }

    /*
     * Binding-related methods
     */

    public class DownloadServiceBinder extends Binder {
        DownloadService getService() {
            return DownloadService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public void downLoadFile(long savedShowId){

        new DownloadTask().execute(savedShowId);

    }

    private class DownloadTask extends AsyncTask<Long, Integer, Void> {

        private SavedShow savedShow;

        private int contentLength;

        @Override
        protected Void doInBackground(Long... params) {

            savedShow = MyApplication.dbHelper.getSavedShow(params[0]);

            int contentLength;

            HttpURLConnection connection = null;
            BufferedInputStream in = null;

            try {

                URL url = new URL(savedShow.getUrl());

                connection = (HttpURLConnection) url.openConnection();

                long fileLength = new File(getFilesDir(), savedShow.getFilename()).length();

                FileOutputStream outputStream = openFileOutput(savedShow.getFilename(), MODE_PRIVATE | MODE_APPEND);

                int downloaded = 0;
                contentLength = connection.getContentLength();

                // If there is already a file with that filename,
                // add 'Range' property in header

                if(fileLength != 0){
                    connection.setRequestProperty("Range", "bytes=" + fileLength + "-");
                }

                in = new BufferedInputStream(connection.getInputStream());

                //BufferedOutputStream out = new BufferedOutputStream(outputStream, 1024);

                byte[] data = new byte[1024];
                int x = 0;

                while ((x = in.read(data, 0, 1024)) >= 0) {
                    outputStream.write(data, 0, x);
                    downloaded += x;
                    publishProgress((int) (downloaded));
                }
            } catch (IOException e) {
                MyApplication.dbHelper.updateSavedShowError(savedShow.getId(), e.toString());

            }
            finally{
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if(connection != null){
                    connection.disconnect();
                }
            }
            return null;

        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);

            // How can I pass values to SavedShowAdapter's items?
        }

        @Override
        protected void onPostExecute(Void nothing) {
            super.onPostExecute(nothing);

            // TODO remove task

            // How can I notify SavedShowAdapter's items?
        }
    }
}

最佳答案

这是我所做的:


为了从DownloadService调用SavedShowAdapter方法,我将绑定到ServiceSavedShowFragment传递给SavedShowAdapter
为了在DownloadService中获得Adapter侦听器,我在BroadcastReceiver中设置了SavedShowFragment,然后调用SavedShowAdapter的方法修改数据并调用notifyDataSetChanged()

关于android - 如何将ListView适配器中的项目绑定(bind)到服务?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17638692/

10-09 07:04