我正在编写一个广播应用程序,用户可以在其中下载一些节目。
当用户单击音频播放器上的下载按钮时,该节目将以SavedShow
的形式添加到数据库中。
用户可以在SavedShow
中看到SavedShowsFragment
实例的状态,该实例显示ListView
以及保存的节目列表。ListView
的每一行中都有保存的节目的标题,状态(NOT_STARTED/DOWNLOADING/PAUSED/DOWNLOADED/ERROR
),ProgressBar
和Button
,用于暂停下载,恢复下载或播放文件(如果已下载)。
现在,我不知道如何将列表的每个项目绑定到我的DownloadService
,也不知道如何在适配器中实现来自DownloadService
的侦听器。
基本上,我希望每一行:
从我的DownloadTask.onProgressUpdate
的DownloadService
获取进度
下载完成或出现错误时,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
方法,我将绑定到Service
的SavedShowFragment
传递给SavedShowAdapter
。
为了在DownloadService
中获得Adapter
侦听器,我在BroadcastReceiver
中设置了SavedShowFragment
,然后调用SavedShowAdapter
的方法修改数据并调用notifyDataSetChanged()
。
关于android - 如何将ListView适配器中的项目绑定(bind)到服务?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17638692/