我有一个带有可下载文件列表视图的应用程序。我使用下载管理器来处理多个下载。现在我的问题是我需要更新已完成下载的列表视图行,因此在广播接收器中我会通过列表视图行来查找适当的数据行并更新它但我在列表视图中的第6项中收到Null指针异常。
BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
final ListView listView = getListView();
String[] a = null;
for (int i = 0; i < listView.getCount(); i++) {
View v = listView.getChildAt(i);
TextView et = (TextView) v.findViewById(R.id.dmrefrence);
Log.d( "position",et.getText().toString() );
Log.d( "i",Integer.toString(i) );
if(et.getText().toString() == Long.toString(referenceId) ){
ImageButton cancelButton = (ImageButton) v.findViewById(R.id.cancelButton);
cancelButton.setVisibility( View.GONE );
}
}
}
};//end of broadcast reciever
这是我的适配器:
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_item, null);
TextView title = (TextView)vi.findViewById(R.id.pid); // title
final TextView artist = (TextView)vi.findViewById(R.id.name); // artist name
TextView duration = (TextView)vi.findViewById(R.id.price); // duration
final TextView fileurl = (TextView)vi.findViewById(R.id.furl); // fileurl
ImageView thumb_image=(ImageView)vi.findViewById(R.id.image); // thumb image
final TextView refrenceid = (TextView)vi.findViewById(R.id.dmrefrence); // refrence id
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
title.setText(song.get(AllProductsActivity.TAG_PID));
artist.setText(song.get(AllProductsActivity.TAG_NAME));
duration.setText(song.get(AllProductsActivity.TAG_PRICE));
fileurl.setText(song.get(AllProductsActivity.TAG_FILEURL));
imageLoader.DisplayImage(song.get(AllProductsActivity.TAG_DESCRIPTION), thumb_image);
final ImageButton pauseButton=(ImageButton)vi.findViewById(R.id.cancelButton); // image button
final ImageButton imageButton=(ImageButton)vi.findViewById(R.id.imageButton1); // image button
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// starting background task to download product
final String dfileurl = fileurl.getText().toString();
final String fname = artist.getText().toString();
imageButton.setVisibility( View.GONE );
pauseButton.setVisibility( View.VISIBLE );
HomeFragment x = new HomeFragment();
//x.new DownloadFileFromURL().doInBackground(dfileurl);
//DownlmActivity x = new DownlmActivity();
long id = x.myClickdwnl(fname,dfileurl,pauseButton,activity.getApplicationContext());
refrenceid.setText(Long.toString(id));
//Log.d("id",Long.toString(id));
}
});
/* Cancel Download */
pauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// starting background task to download product
final String dnid = refrenceid.getText().toString();
pauseButton.setVisibility( View.GONE );
imageButton.setVisibility( View.VISIBLE );
HomeFragment x = new HomeFragment();
x.Canceldwnl(dnid,activity.getApplicationContext());
}
});
return vi;
}
}
答案 0 :(得分:0)
当您开始下载时,您会从以下说明中获得下载ID:
long id = x.myClickdwnl(fname,dfileurl,pauseButton,activity.getApplicationContext());
您需要跟踪哪个下载对应于给定位置(如果有)以及下载完成的项目(行)。为此,请将这2个成员添加到BaseAdapter
:
/** This associates your download_id to the position of the item in the ListView */
private LongSparseArray<int> downloadIdToPositionMap = new LongSparseArray();
/** This keeps track of the position of item which download is finished */
private ArrayList<Integer> finishedDownloadPositions = new ArrayList<Integer>();
现在位于imageButton
OnClickListener
中,而不是将download_id存储在TextView
(这不是它的目的),您可以将其存储在downloadIdToPositionMap
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// starting background task to download product
final String dfileurl = fileurl.getText().toString();
final String fname = artist.getText().toString();
imageButton.setVisibility( View.GONE );
pauseButton.setVisibility( View.VISIBLE );
HomeFragment x = new HomeFragment();
//x.new DownloadFileFromURL().doInBackground(dfileurl);
//DownlmActivity x = new DownlmActivity();
long id = x.myClickdwnl(fname,dfileurl,pauseButton,activity.getApplicationContext());
downloadIdToPositionMap.put(id, position);
//Log.d("id",Long.toString(id));
}
});
中。 {1}}:
BroadcastReceiver
在Adapter
,您必须通知您的BaseAdapter
下载已完成。您需要在/**
* Keep the position of the item associated to the {@code downloadId} in the list of finished downloads
* @param downloadId the download unique identifier
* @throws IllegalStateException if there is no entry matching {@code downloadId} in {@code this.downloadIdToPositionMap}
*/
public void setDownloadFinished(long downloadId) throws IllegalStateException{
int position = this.downloadIdToPositionMap.get(downloadId, -1);
if(position == -1) throw new IllegalStateException(String.format("Unknown finished download with id = %d", downloadId));
this.finishedDownloadPositions.add(position);
}
中添加另一种方法来执行此操作:
BroadcastReceiver
并将您的onReceive()
@Override
public void onReceive(Context context, Intent intent){
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
final BaseAdapter adapter = getListView().getAdapter();
adapter.setDownloadFinished(referenceId);
// Ask the adapter to refresh the ListView
adapter.notifyDataSetChanged();
}
方法更改为:
ListView
现在您知道在给定download_id的情况下,完成下载所对应的View
项。唯一缺少的是更新行的BaseAdapter
。您需要更改getView()
@Override
public View getView(final int position, View convertView, ViewGroup parent){
View vi = convertView;
if(convertView == null) vi = inflater.inflate(R.layout.list_item, null);
TextView title = (TextView)vi.findViewById(R.id.pid); // title
final TextView artist = (TextView)vi.findViewById(R.id.name); // artist name
TextView duration = (TextView)vi.findViewById(R.id.price); // duration
final TextView fileurl = (TextView)vi.findViewById(R.id.furl); // fileurl
ImageView thumb_image = (ImageView)vi.findViewById(R.id.image); // thumb image
final TextView refrenceid = (TextView)vi.findViewById(R.id.dmrefrence); // refrence id
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
title.setText(song.get(AllProductsActivity.TAG_PID));
artist.setText(song.get(AllProductsActivity.TAG_NAME));
duration.setText(song.get(AllProductsActivity.TAG_PRICE));
fileurl.setText(song.get(AllProductsActivity.TAG_FILEURL));
imageLoader.DisplayImage(song.get(AllProductsActivity.TAG_DESCRIPTION), thumb_image);
if(this.isDownloadFinished(position)){
final ImageButton pauseButton=(ImageButton)vi.findViewById(R.id.cancelButton); // image button
final ImageButton imageButton=(ImageButton)vi.findViewById(R.id.imageButton1); // image button
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// starting background task to download product
final String dfileurl = fileurl.getText().toString();
final String fname = artist.getText().toString();
imageButton.setVisibility( View.GONE );
pauseButton.setVisibility( View.VISIBLE );
HomeFragment x = new HomeFragment();
//x.new DownloadFileFromURL().doInBackground(dfileurl);
//DownlmActivity x = new DownlmActivity();
long id = x.myClickdwnl(fname,dfileurl,pauseButton,activity.getApplicationContext());
refrenceid.setText(Long.toString(id));
downloadIdToPositionMap.put(id, position);
//Log.d("id",Long.toString(id));
}
});
/* Cancel Download */
pauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// starting background task to download product
final String dnid = refrenceid.getText().toString();
pauseButton.setVisibility( View.GONE );
imageButton.setVisibility( View.VISIBLE );
HomeFragment x = new HomeFragment();
x.Canceldwnl(dnid,activity.getApplicationContext());
}
});
}
return vi;
}
方法:
BaseAdapter
最后,添加此方法(到/**
* Return wether the given position corresponds to an item which download is finished
* @param position the position of the item
* @return {@code true} if the download associated with the item at position is finished, {@code false} otherwise
*/
private boolean isDownloadFinished(int position){
return this.finishedDownloadPositions.contains(position);
}
)以检查下载是否已完成,给定位置:
getItem()
<小时/> 请注意,我还没有对代码进行测试,因此可能包含一些错误,但如果你掌握了逻辑,你应该可以修复它们。
另一方面,您在ListView
方法中做得太多了。请记住,当您滚动OnClickListener
时,每次项目可见时都会调用它。为避免滞后,您应考虑实施ViewHolder pattern。
同时避免对pauseButton.setOnClickListener(new View.OnClickListener() {// Stripped method body for readability});
使用匿名声明。
在您的代码中,OnClickListener
会为ListView
中的每个可见项创建一个新的BaseAdapter
。你可以通过将你的听众定义为private View.OnClickListener pauseListener = new new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// Stripped method body for readability
}
});
public View getView(int position, View convertView, ViewGroup parent) {
// Stripped method body for readability
pauseButton.setOnClickListener(this.pauseListener);
}
中的新成员来避免这种情况:
{{1}}