I have a ListView inside an Activity and each of its item is customized to have some TextViews along with a DropDownList item and an ImageView. Inside an OnScrollListener() implementation each item of a listView gets populated using an ArrayAdapter populating text views with values taken from an arrayList and ImageView with the .jpeg file stored on SD card. Following is the screenSHot of listView Item
The problem arises when the .jpeg file from sdCard is converted to a bitmap (i.e. BitmapFactory.decodeFile(fileName) ) and then gets assigned to an image View using setImageBitmap(Bitmap bmp). As the setting bitmap image to an image view is a lengthy process it cannot keep pace with the scroll listener implementation and the ImageView of different ListView rows gets populated with the image it was assigned to any row above. Can anybody please suggest some workout to cater this issue specifically the assignment of images from SD Card to an imageView. Its not like my listView item is overLoaded with controls that is why i am facing this problem. I also have tried it with single ImageView item inside each row and it behaves the same way. Your suggestion to improvise this are welcome and surely will be of great help. Thank you :-)
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
AssetDetailHolder assetDetailholder = null;
try {
if (row == null) {
LayoutInflater inflator = ((Activity) context)
.getLayoutInflater();
row = inflator.inflate(layoutResourceID, parent, false);
assetDetailholder = new AssetDetailHolder();
assetDetailholder.itemPosition = position;
assetDetailholder.txtVwlineCOde = (TextView) row
.findViewById(R.id.lineCodeValue_ad);
assetDetailholder.txtvwLocation = (TextView) row
.findViewById(R.id.locationValue_ad);
assetDetailholder.txtvwLocationDetail = (TextView) row
.findViewById(R.id.detailLocationValue_ad);
assetDetailholder.txtvwInventoryNo = (TextView) row
.findViewById(R.id.InventoryNoValue_ad);
assetDetailholder.spnrconditionCode = (Spinner) row
.findViewById(R.id.spinner_ad);
assetDetailholder.txtvwAssetName = (TextView) row
.findViewById(R.id.AssetNameValue_ad);
assetDetailholder.subNoThumbnail = (ImageView) row
.findViewById(R.id.IV_subNoThumbnail);
row.setTag(assetDetailholder);
} else {
assetDetailholder = (AssetDetailHolder) row.getTag();
assetDetailholder.itemPosition = position;
}
AssetDetail assetDetail = assetsDetailList[position];
new ThumbnailTask(position, assetDetailholder, assetDetail, context)
.execute();
if (assetDetail.assetLineCodeDesc.equals("")) {
assetDetailholder.txtVwlineCOde
.setText(assetDetail.strLineCOde);
} else {
assetDetailholder.txtVwlineCOde.setText(assetDetail.strLineCOde
+ "(" + assetDetail.assetLineCodeDesc + ")");
}
if (assetDetail.assetLocationNameDesc.equals("")) {
assetDetailholder.txtvwLocation
.setText(assetDetail.strLocationName);
} else {
assetDetailholder.txtvwLocation
.setText(assetDetail.strLocationName + "("
+ assetDetail.assetLocationNameDesc + ")");
}
assetDetailholder.txtvwLocationDetail
.setText(assetDetail.strLocationDetail);
if (assetDetail.strInventoryNumber.contains("-")) {
assetDetailholder.txtvwInventoryNo
.setText(assetDetail.strInventoryNumber.split("-")[0]);
} else {
assetDetailholder.txtvwInventoryNo
.setText(assetDetail.strInventoryNumber);
}
assetDetailholder.txtvwAssetName.setText(assetDetail.assetName);
String conditionCodeString = assetDetail.assetConditionCode;
if (conditionCodeString != "" || conditionCodeString != null) {
try {
int conditionCodeInteger = Integer
.parseInt(conditionCodeString);
assetDetailholder.spnrconditionCode
.setSelection(conditionCodeInteger);
} catch (Exception e) {
assetDetailholder.spnrconditionCode.setSelection(0);
}
} else {
assetDetailholder.spnrconditionCode.setSelection(0);
}
// String thumbnailDir = Common
// .getSubNoDirectory(context, assetDetail);
// if (new File(thumbnailDir).isDirectory()) {
//
// File thumbnailFile = new File(Common.getSubNoImgFilePath(
// thumbnailDir, assetDetail, SubNo_ImageSample.A));
//
// if (thumbnailFile.exists()) {
// assetDetailholder.subNoThumbnail
// .setImageBitmap(BitmapFactory
// .decodeFile(thumbnailFile.getAbsolutePath()));
// }
// }
} catch (Exception e) {
e.printStackTrace();
}
return row;
}
static class AssetDetailHolder {
TextView txtVwlineCOde;
TextView txtvwLocation;
TextView txtvwLocationDetail;
TextView txtvwInventoryNo;
TextView txtvwAssetName;
Spinner spnrconditionCode;
ImageView subNoThumbnail;
public int itemPosition;
}
private static class ThumbnailTask extends AsyncTask<Void, Void, Void> {
private int mPosition;
private AssetDetailHolder mHolder;
private Context cntxt;
private AssetDetail assetItem;
private Bitmap thumbnailBmp;
public ThumbnailTask(int position, AssetDetailHolder holder,
AssetDetail asset, Context context) {
mPosition = position;
mHolder = holder;
assetItem = asset;
cntxt = context;
}
#Override
protected Void doInBackground(Void... params) {
String thumbnailDir = Common.getSubNoDirectory(cntxt, assetItem);
if (new File(thumbnailDir).isDirectory()) {
File thumbnailFile = new File(Common.getSubNoImgFilePath(
thumbnailDir, assetItem, SubNo_ImageSample.A));
if (thumbnailFile.exists()) {
thumbnailBmp = BitmapFactory.decodeFile(thumbnailFile
.getAbsolutePath());
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (mHolder.itemPosition == mPosition && thumbnailBmp != null) {
mHolder.subNoThumbnail.setImageBitmap(thumbnailBmp);
}
// super.onPostExecute(result);
}
}
http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
This will be hopefull to you :P
Related
I want to make my expandable list smooth.
After looking a lot in the internet,
I added a viewHolder and changed my method where I load the data to be asynchronously. But my list is still slow!!!.
Can you take a look? I added the activity where I load asynchronously the data with my DataProvider and then I init my adapter. This help me to see my activity and a spinner until the data is loaded and then updated on my view.
But I dont have a fluid list when I scroll or when I try to expand a category. Can you help and tell me what to change ? I think that it can be the images but I save them locally to make it faster (I added my methods) and it can be something else....
MyActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set layout for this activity
setContentView(R.layout.expandable_list);
// Set actionbar title
getActionBar().show();
getActionBar().setTitle(Html.fromHtml("<font color='#fffffff'>Groups</font>"));
if (loggedUserId != null)
Log.d("TAG", "My Groups for user ID: " + loggedUserId);
// Connect between buttons to layout id
expandableListView = (ExpandableListView) findViewById(R.id.exp_list);
spinner = (ProgressBar) findViewById(R.id.spinner);
createCategoryButton = (ImageButton) findViewById(R.id.createCategory);
textLoading = (TextView) findViewById(R.id.textLoading);
// Loading data to expandable group list asynchronously
AsyncTask<String, String, HashMap<String, List<Group>>> task = new AsyncTask<String, String, HashMap<String, List<Group>>>() {
#Override
protected HashMap<String, List<Group>> doInBackground(String... params) {
return DataProvider.getInfo();
}
#Override
protected void onPostExecute(HashMap<String, List<Group>> listHashMap) {
super.onPostExecute(listHashMap);
// Setting adapter and creating group list
groupCategories = listHashMap;
groupsList = new ArrayList<String>(groupCategories.keySet());
adapter = new Adapter(GroupsListActivity.this, groupCategories, groupsList, GroupsListActivity.this);
expandableListView.setAdapter(adapter);
// Hide spinner after loading
spinner.setVisibility(View.GONE);
textLoading.setVisibility(View.GONE);
}
};
task.execute();
My adapter:
#Override
public View getGroupView(final int parent, boolean isExpanded, View convertView, ViewGroup parentView) {
final String categoryName = (String) getGroup(parent);
ParentViewHolder pHolder = null;
if (convertView == null) {
// Creates a ViewHolder and store references to layouts we want to bind data to.
pHolder = new ParentViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.expandable_list_parent, parentView, false);
// Connect between buttons to layout id
pHolder.categoryNameTextView = (TextView) convertView.findViewById(R.id.categoryName);
pHolder.editCategory = (ImageButton) convertView.findViewById(R.id.editCategory);
pHolder.deleteCategory = (ImageButton) convertView.findViewById(R.id.deleteCategory);
//Save holder
convertView.setTag(pHolder);
} else {
// Get the ViewHolder back
pHolder = (ParentViewHolder) convertView.getTag();
}
// Hide edit and delete button for category name Others
if (categoriesList.get(parent).equals("Others")) {
pHolder.editCategory.setVisibility(View.GONE);
pHolder.deleteCategory.setVisibility(View.GONE);
} else {
pHolder.editCategory.setVisibility(View.VISIBLE);
pHolder.deleteCategory.setVisibility(View.VISIBLE);
}
// Set category name on row
pHolder.categoryNameTextView.setTypeface(null, Typeface.BOLD);
pHolder.categoryNameTextView.setText(categoryName + ": " + getChildrenCount(parent));
// Set edit category button listener
final ParentViewHolder finalPHolder = pHolder;
pHolder.editCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finalPHolder.editCategory.setEnabled(false);
editCategoryName(activity, finalPHolder.categoryNameTextView.getText().toString().toString().split(": ")[0], finalPHolder.editCategory, parent);
}
});
// Set delete category button listener
pHolder.deleteCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finalPHolder.deleteCategory.setEnabled(false);
deleteCategory(activity, categoryName, finalPHolder.deleteCategory);
}
});
return convertView;
}
#Override
public View getChildView(final int parent, final int child, boolean lastChild, View convertView, ViewGroup parentView) {
final Group group = (Group) getChild(parent, child);
ChildViewHolder cHolder = null;
if (convertView == null) {
// Creates a ViewHolder and store references to layouts we want to bind data to.
cHolder = new ChildViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.expandable_list_child, parentView, false);
// Connect between buttons to layout id
cHolder.groupImage = (ImageView) convertView.findViewById(R.id.groupImage);
cHolder.groupName = (TextView) convertView.findViewById(R.id.groupName);
cHolder.moveCategory = (ImageButton) convertView.findViewById(R.id.moveCategory);
cHolder.groupFavoritesButton = (ImageButton) convertView.findViewById(R.id.groupFavorites);
cHolder.groupLeaveGroupButton = (Button) convertView.findViewById(R.id.groupLeave);
cHolder.groupImageProgressbar = (ProgressBar) convertView.findViewById(R.id.groupImageProgressBar);
//Save holder
convertView.setTag(cHolder);
} else {
// Get the ViewHolder back
cHolder = (ChildViewHolder) convertView.getTag();
}
// Set group name on row
cHolder.groupName.setText(group.getName());
// Load group image
cHolder.groupImageProgressbar.setVisibility(View.VISIBLE);
final ChildViewHolder finalHolder = cHolder;
Model.getInstance().getGroupImage(group.getImageName(), new Model.LoadImageListener() {
#Override
public void onResult(Bitmap imageBmp) {
if (imageBmp != null) {
finalHolder.groupImage.setImageBitmap(imageBmp);
finalHolder.groupImageProgressbar.setVisibility(View.GONE);
finalHolder.groupImage.setVisibility(View.VISIBLE);
}
}
});
// Set move category button listener
cHolder.moveCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finalHolder.moveCategory.setEnabled(false);
showDialogMoveCategory(activity, group.getGroupID(), finalHolder.moveCategory);
}
});
// After click on group image - open profile for this group
cHolder.groupImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onGroupSelected(group.getGroupID());
}
});
// Setting favorite Button Image
boolean isFavorite = Model.getInstance().groupIsFavorite(loggedUserId, group.getGroupID());
if (isFavorite)
cHolder.groupFavoritesButton.setBackgroundResource(R.mipmap.favorites_on);
else
cHolder.groupFavoritesButton.setBackgroundResource(R.mipmap.favorites_off);
// Setting favorite Button Action
cHolder.groupFavoritesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Add group to favorites
if (!Model.getInstance().groupIsFavorite(loggedUserId, group.getGroupID())) {
finalHolder.groupFavoritesButton.setBackgroundResource(R.mipmap.favorites_on);
Toast.makeText(activity,
"The group " + group.getName() + " was added to favorites", Toast.LENGTH_SHORT).show();
Model.getInstance().changeFavoriteStatus(loggedUserId, group.getGroupID(), "true");
} else {
// Delete group from favorites
finalHolder.groupFavoritesButton.setBackgroundResource(R.mipmap.favorites_off);
Toast.makeText(activity,
"The group " + group.getName() + " was removed from favorites", Toast.LENGTH_SHORT).show();
Model.getInstance().changeFavoriteStatus(loggedUserId, group.getGroupID(), "false");
}
}
});
// After click on group action - leave group
cHolder.groupLeaveGroupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finalHolder.groupLeaveGroupButton.setEnabled(false);
showDialogLeaveGroup(activity, "Are you sure ?", "This action will remove yourself from the group " + group.getName(), group.getGroupID(), parent, child);
finalHolder.groupLeaveGroupButton.setEnabled(true);
}
});
return convertView;
}
Images methods:
public void getGroupImage(final String imageName, final LoadImageListener listener) {
AsyncTask<String, String, Bitmap> task = new AsyncTask<String, String, Bitmap>() {
#Override
protected Bitmap doInBackground(String... params) {
Bitmap bmp = loadImageFromFile(imageName); //first try to find the image on the device
// Bitmap bmp = null;
if (bmp == null) { //if image not found - try downloading it from parse
bmp = modelParse.getGroupImage(imageName);
if (bmp != null)
saveImageToFile(bmp, imageName); //save the image locally for next time *****
}
Bitmap scaledBitmap = scaleDown(bmp, 200, true);
return scaledBitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
listener.onResult(result);
}
};
task.execute();
}
private void saveImageToFile(Bitmap imageBitmap, String imageFileName) {
FileOutputStream fos;
OutputStream out = null;
try {
File dir = context.getExternalFilesDir(null);
out = new FileOutputStream(new File(dir, imageFileName + ".jpg"));
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private Bitmap loadImageFromFile(String fileName) {
Bitmap bitmap = null;
try {
File dir = context.getExternalFilesDir(null);
InputStream inputStream = new FileInputStream(new File(dir, fileName + ".jpg"));
bitmap = BitmapFactory.decodeStream(inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return bitmap;
}
I`m create list of points of sales from SQLite using custom adapter
dbHelper = new YourVoiceDatabaseHelper(getActivity());
pointsList = new ArrayList<Point>();
List<Point> pl = new ArrayList<Point>();
PointsListArrayAdapter adapter;
adapter = new PointsListArrayAdapter(getActivity().getApplicationContext(),
pointsList,
getActivity().getFilesDir(),
getResources().getString(R.string.Local_Resorces_Folder),
dbHelper);
pointsListView.setAdapter(adapter);
pl = dbHelper.getAllPoints();
if(myLocation != null) {
for (Point el : pl) {
elLocation.setLatitude(Double.parseDouble(el.getLatitude()));
elLocation.setLongitude(Double.parseDouble(el.getLongtitude()));
if (myLocation.distanceTo(elLocation) <= 999) {
pointsList.add(el);
}
}
} else {
Toast.makeText(getActivity(), "Не удалось определить ваше местоположение, проверте ваши разрешения и настройки",
Toast.LENGTH_LONG).show();
} adapter.notifyDataSetChanged();
To custom adapter I send instance of my database ad using it in there and this slows my main tread. I`m trying to use AsyncTask in adapter to get images path from database and set images but Async do absolutely NOTHING
package ua.com.it_artel.tvoy_golos.service;
public class PointsListArrayAdapter extends BaseAdapter {
Context context;
private List<Point> pointsList;
private File appFolder;
private String resoursesFolder;
private YourVoiceDatabaseHelper dbHelper;
private String imagePath;
public PointsListArrayAdapter(Context context, List<Point> pointsList, File appFolder, String resoursesFolder, YourVoiceDatabaseHelper dbHelper) {
this.context = context;
this.pointsList = pointsList;
this.appFolder = appFolder;
this.resoursesFolder = resoursesFolder;
this.dbHelper = dbHelper;
}
#Override
public int getCount() {
return pointsList.size();
}
#Override
public Object getItem(int position) {
return pointsList.get(position);
}
#Override
public long getItemId(int position) {
return pointsList.get(position).getId();
}
static class ViewHolder {
ImageView image;
TextView adress;
TextView name;
TextView distance;
Location elLocation;
Point point;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
View rowView = convertView;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.list_element_layout_type_1, parent, false);
viewHolder = new ViewHolder();
viewHolder.elLocation = new Location("");
viewHolder.image = (ImageView) rowView.findViewById(R.id.item_image);
viewHolder.adress = (TextView) rowView.findViewById(R.id.item_text);
viewHolder.name = (TextView) rowView.findViewById(R.id.item_name);
viewHolder.distance = (TextView) rowView.findViewById(R.id.item_distance);
rowView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.elLocation.setLatitude(Double.parseDouble(pointsList.get(position).getLatitude()));
viewHolder.elLocation.setLongitude(Double.parseDouble(pointsList.get(position).getLongtitude()));
viewHolder.point = pointsList.get(position);
new AdapterImageSetter().execute(viewHolder);
viewHolder.adress.setText(pointsList.get(position).getAddress());
viewHolder.name.setText(dbHelper.getPartnerByUID(pointsList.get(position).getPartnerUid()).getName());
viewHolder.distance.setText(String.valueOf(Math.round(MyLocationListener.myLocation.distanceTo(viewHolder.elLocation))) + " м");
return rowView;
}
private class AdapterImageSetter extends AsyncTask<ViewHolder, Void, ViewHolder> {
#Override
protected ViewHolder doInBackground(ViewHolder... params) {
ViewHolder viewHolder = params[0];
imagePath = dbHelper.getPointsPartnerImage(viewHolder.point.getPartnerUid());
if (imagePath.equals("")) {
viewHolder.image.setImageResource(R.drawable.no_image);
} else {
Drawable dr = Drawable.createFromPath(appFolder.getPath() + "/" + resoursesFolder + "/" + imagePath);
viewHolder.image.setImageDrawable(dr);
}
return viewHolder;
}
}
}
I have tried different variations in AsyncTask and Runnable but it doesn`t work, like if there are no code.. Hope u understand my English and someone give advice
you can not perform ui related operations in doInBackground method for ui related operation just use onpostexcecute method
more about asynch task http://developer.android.com/reference/android/os/AsyncTask.html
in your code you you setting imege
if (imagePath.equals("")) {
viewHolder.image.setImageResource(R.drawable.no_image);
} else {
Drawable dr = Drawable.createFromPath(appFolder.getPath() + "/" + resoursesFolder + "/" + imagePath);
viewHolder.image.setImageDrawable(dr);
}
just add this code in onPostExecute
It`s work! I also add some code in Async, all work BUT but toooo much time is necessary for images and names appeared.
private class AdapterImageSetter extends AsyncTask {
#Override
protected ViewHolder doInBackground(ViewHolder... params) {
ViewHolder viewHolder = params[0];
viewHolder.imagePath = dbHelper.getPointsPartnerImage(viewHolder.point.getPartnerUid());
viewHolder.pointName = dbHelper.getPartnerByUID(viewHolder.point.getPartnerUid()).getName();
return viewHolder;
}
#Override
protected void onPostExecute(ViewHolder viewHolder) {
if (viewHolder.imagePath.equals("")) {
viewHolder.image.setImageResource(R.drawable.no_image);
} else {
Drawable dr = Drawable.createFromPath(appFolder.getPath() + "/" + resoursesFolder + "/" + viewHolder.imagePath);
viewHolder.image.setImageDrawable(dr);
}
viewHolder.name.setText(viewHolder.pointName);
Log.i("IMAGE PATH", viewHolder.imagePath);
Log.i("PARTNER UID", viewHolder.point.getPartnerUid());
}
}
For more information: this list is on first screen when u open app.
In first activity I replace fragment and шт the fragment I'm doing all the operations. have any ideas how to speed up operations in AsyncTask?
Thank you very much for the help!
I am working on a project. In my project when user clicks on a list item, it downloads a file from some source and saves it into internal storage.
I want to show an image in list items of listview if file is already download.
The code below is working fine but it is also showing image for the list items whose file is yet not downloaded.
Here is my adapter class code.
package life.quran.com.quranlife;
public class SurahBaseSearchAdapter extends BaseAdapter {
Context mContext;
LayoutInflater mInflator;
private List<Surah> surahList = null;
private ArrayList<Surah> arrayList;
Surah surah;
ArrayList<String> imgfileLocation = null;
String searchhighlightString = "";
public SurahBaseSearchAdapter(Context context, List<Surah> list) {
mContext = context;
surahList = list;
mInflator = LayoutInflater.from(context);
arrayList = new ArrayList<Surah>();
arrayList.addAll(surahList);
}
public class ViewHolder {
TextView sname;
TextView sno;
ImageView dlimg;
}
#Override
public int getCount() {
return surahList.size();
}
#Override
public Object getItem(int position) {
return surahList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
imgfileLocation = new ArrayList<>();
surah = surahList.get(position);
File f = mContext.getFilesDir();
String filepath = f.getAbsolutePath();
File _file = new File(filepath+"/surah_"+surah.getSurah_id()+".json");
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflator.inflate(R.layout.item_template,null);
holder.sname = (TextView) convertView.findViewById(R.id.txt_surahName);
holder.sno = (TextView) convertView.findViewById(R.id.txtsuraNo);
holder.dlimg = convertView.findViewById(R.id.dlimg);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.sname.setText(surah.getSurah_name());
holder.sno.setText(surah.getSurah_no());
if (_file.exists()) {
holder.dlimg.setImageResource(R.drawable.newdlimg);
}
String hSurahName = surah.getSurah_name().toLowerCase(Locale.getDefault());
if(hSurahName.contains(searchhighlightString)) {
int startpos = hSurahName.indexOf(searchhighlightString);
int endpos = startpos + searchhighlightString.length();
Spannable spanText = Spannable.Factory.getInstance().newSpannable(holder.sname.getText());
spanText.setSpan(new ForegroundColorSpan(Color.BLUE),startpos,endpos,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.sname.setText(spanText,TextView.BufferType.SPANNABLE);
}
return convertView;
}
public void filter(String charText) {
searchhighlightString = charText;
charText = charText.toLowerCase(Locale.getDefault());
surahList.clear();
if(charText.length() == 0) {
surahList.addAll(arrayList);
} else {
for(Surah surah : arrayList) {
if(surah.getSurah_name().toLowerCase(Locale.getDefault()).contains(charText)) {
surahList.add(surah);
}
}
}
notifyDataSetChanged();
}
}
Let me know if anything is unclear
You require to set default drawable if file not exist condition. Add else part to this if condition like
if (_file.exists()) {
holder.dlimg.setImageResource(R.drawable.newdlimg);
}else{
holder.dlimg.setImageResource(R.drawable.<default_image>);
}
You should clear image in ViewHolder after previous usage. Just change your code to something like this:
if (_file.exists()) {
holder.dlimg.setImageResource(R.drawable.newdlimg);
} else {
//clear image from previous usage
//do not sure is it legal to set null. You need to check it.
holder.dlimg.setImageResource(null)
}
I have a ListView,I am having a custom ListItem designed for it having some TextView's and an ImageView. I want to change that particular image when clicked . I have tried but when i click on that image from ListView, the below listItem's image is changing.
For example if i click on 0th position image then image is changing of 1st position ListIem and when i scroll up and down the List,it changes randomly.
I dont know what is happening with it,I have used notifydatasetChanged on my adapter,But its not working,My code is as below.
Please help me,Thank you,
Code
private class RssAdapter extends ArrayAdapter<RSSFeed_SelectedHotelResult> {
private List<RSSFeed_SelectedHotelResult> rssFeedLst;
int selectedPosition;
public RssAdapter(Context context, int textViewResourceId,
List<RSSFeed_SelectedHotelResult> rssFeedLst) {
super(context, textViewResourceId, rssFeedLst);
this.rssFeedLst = rssFeedLst;
Boolean addtoShotlist;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
if (convertView == null) {
view = View.inflate(HotelListActivity.this, R.layout.list_row,
null);
rssHolder = new RssHolder();
rssHolder.iv_add = (ImageView) view.findViewById(R.id.iv_add);
rssHolder.rssTitleView = (TextView) view
.findViewById(R.id.title);
rssHolder.tv_offer = (TextView) view.findViewById(R.id.tv_ofr);
rssHolder.rssImagHotel = (ImageView) view
.findViewById(R.id.hotelImage);
rssHolder.rssImageHotelRate = (ImageView) view
.findViewById(R.id.rateHotel2);
rssHolder.rssHotelPrice = (TextView) view
.findViewById(R.id.textHotelRate);
rssHolder.rssHotelAddress = (TextView) view
.findViewById(R.id.textHotelDesc);
// rssHolder.adres = (TextView) view.findViewById(R.id.adres);
// rssHolder.rssHotelRating = (TextView)
// view.findViewById(R.id.textHotelRating);
rssHolder.rating_hotel = (RatingBar) view
.findViewById(R.id.rateHotelImage);
rssHolder.tv_currcode = (TextView) view
.findViewById(R.id.tv_currcode);
view.setTag(rssHolder);
} else {
rssHolder = (RssHolder) view.getTag();
}
final RSSFeed_SelectedHotelResult rssFeed = rssFeedLst
.get(position);
rssHolder.rssTitleView.setText(rssFeed.getName());
imageLoader.DisplayImage(rssFeed.getHotel_image(),
rssHolder.rssImagHotel);
imageLoader.DisplayImage_rating(rssFeed.getHote_rate_image(),
rssHolder.rssImageHotelRate);
rssHolder.rssHotelPrice.setText(rssFeed.getHotel_price());
rssHolder.rssHotelAddress.setText(rssFeed.getHotel_desc());
rssHolder.rating_hotel.setRating(Float.valueOf(rssFeed
.getHotel_rate()));
rssHolder.tv_currcode.setText(Consts.currencyCode);
if (rssFeed.getoffer() != null) {
rssHolder.tv_offer.setText("**" + rssFeed.getoffer() + "**");
} else {
rssHolder.tv_offer.setText("");
}
rssHolder.iv_add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
selectedPosition = position;
try {
if (position == selectedPosition) {
rssHolder.iv_add
.setBackgroundResource(R.drawable.fill);
} else {
rssHolder.iv_add
.setBackgroundResource(R.drawable.plus12);
}
} catch (IndexOutOfBoundsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out
.println("::::::::::::My data in side hotel List activity:::::::::;"
+ position
+ ""
+ rssFeed.getName()
+ "\n"
+ rssFeed.getHotel_price());
/*
* RSSFeed_SelectedHotelResult rssFeed1 = rssFeedLst
* .get(position);
*/
}
});
return view;
}
}
For notify data-set changed your calling the wrong method the correct method is adapter.notifyDataSetChanged()
1.) Write this code inside your custom adapter getView :
if (position == selectedPosition) {
imageview.setBackgroundResource(R.drawable.image1);
} else {
imageview.setBackgroundResource(R.drawable.normal);
}
2.) Make a method in custom adapter :
public void setSelected(int position) {
selectedPosition = position;
}
//where selectPosition is private int selectedPosition = -1;
3.) Call this method from activity listitem click like :
((Category_Adapter) adapter).setSelected(position);
listview.invalidate();
Make sure your listview set to single choice mode.
private class RssAdapter extends ArrayAdapter<RSSFeed_SelectedHotelResult> {
private List<RSSFeed_SelectedHotelResult> rssFeedLst;
private int selectedPosition =-1;// initalize position
public RssAdapter(Context context, int textViewResourceId,
List<RSSFeed_SelectedHotelResult> rssFeedLst) {
super(context, textViewResourceId, rssFeedLst);
this.rssFeedLst = rssFeedLst;
Boolean addtoShotlist;
}
//make this method
public void setSelected(int position) {
selectedPosition = position;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
if (convertView == null) {
view = View.inflate(HotelListActivity.this, R.layout.list_row,
null);
rssHolder = new RssHolder();
rssHolder.iv_add = (ImageView) view.findViewById(R.id.iv_add);
rssHolder.rssTitleView = (TextView) view
.findViewById(R.id.title);
rssHolder.tv_offer = (TextView) view.findViewById(R.id.tv_ofr);
rssHolder.rssImagHotel = (ImageView) view
.findViewById(R.id.hotelImage);
rssHolder.rssImageHotelRate = (ImageView) view
.findViewById(R.id.rateHotel2);
rssHolder.rssHotelPrice = (TextView) view
.findViewById(R.id.textHotelRate);
rssHolder.rssHotelAddress = (TextView) view
.findViewById(R.id.textHotelDesc);
// rssHolder.adres = (TextView) view.findViewById(R.id.adres);
// rssHolder.rssHotelRating = (TextView)
// view.findViewById(R.id.textHotelRating);
rssHolder.rating_hotel = (RatingBar) view
.findViewById(R.id.rateHotelImage);
rssHolder.tv_currcode = (TextView) view
.findViewById(R.id.tv_currcode);
view.setTag(rssHolder);
} else {
rssHolder = (RssHolder) view.getTag();
}
final RSSFeed_SelectedHotelResult rssFeed = rssFeedLst
.get(position);
rssHolder.rssTitleView.setText(rssFeed.getName());
imageLoader.DisplayImage(rssFeed.getHotel_image(),
rssHolder.rssImagHotel);
imageLoader.DisplayImage_rating(rssFeed.getHote_rate_image(),
rssHolder.rssImageHotelRate);
rssHolder.rssHotelPrice.setText(rssFeed.getHotel_price());
rssHolder.rssHotelAddress.setText(rssFeed.getHotel_desc());
rssHolder.rating_hotel.setRating(Float.valueOf(rssFeed
.getHotel_rate()));
rssHolder.tv_currcode.setText(Consts.currencyCode);
if (rssFeed.getoffer() != null) {
rssHolder.tv_offer.setText("**" + rssFeed.getoffer() + "**");
} else {
rssHolder.tv_offer.setText("");
}
rssHolder.iv_add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//remove selectposition = position
try {
if (position == selectedPosition) {
rssHolder.iv_add
.setBackgroundResource(R.drawable.fill);
} else {
rssHolder.iv_add
.setBackgroundResource(R.drawable.plus12);
}
} catch (IndexOutOfBoundsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out
.println("::::::::::::My data in side hotel List activity:::::::::;"
+ position
+ ""
+ rssFeed.getName()
+ "\n"
+ rssFeed.getHotel_price());
/*
* RSSFeed_SelectedHotelResult rssFeed1 = rssFeedLst
* .get(position);
*/
}
});
return view;
}
}
Finally call adapter selected method from activity listitem click and set position.
I have an ArrayList of my class WorkOrder. This ArrayList this populating a ListView, however, when my SELECT returns a very large result, I have problems to fill the listView. Curious somehow load the information as my need. When searching, I found some ways to use using setOnScrollListener event, but it was unclear how the information is uploaded to the listView.
My doubts are:
How do I load the information? They must be requested from the server as needed or we fill the entire ArrayList and do a control later?
Where can I find a simple tutorial for my need?
To fill my listView, I use the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pending_wos);
new LoadPendingWorkOrders().execute();
}
private class LoadPendingWorkOrders extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
progress = ProgressDialog.show(PendingWorkOrders.this,
getResources().getString(R.string.Wait), getResources()
.getString(R.string.LoadingPendingWOs));
}
#Override
protected Void doInBackground(Void... params) {
try {
worker = Application.getInstance().getUser();
WorkOrderQueries woQ = WorkOrderQueriesFactory
.createWorkOrderQueriesFactory();
pendingWorkOrders = woQ
.selectPendingWorkOrders(asset, fromDate, workType,
workRequestType, workOrderState);
for (WorkOrder w : pendingWorkOrders) {
if (w.getDataCompare() >= 0) {
w.setFlag(getResources().getDrawable(
R.drawable.green));
} else {
w.setFlag(getResources()
.getDrawable(R.drawable.red));
}
}
} catch (QueryException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
setListAdapter(new PendingWOArrayAdapter(getApplicationContext(),
R.layout.pending_wos_list, pendingWorkOrders));
ListView listView = getListView();
listView.setTextFilterEnabled(true);
if (progress != null)
progress.dismiss();
}
}
this is my adapter class:
public class PendingWOArrayAdapter extends ArrayAdapter<WorkOrder> {
private List<WorkOrder> workOrders = new ArrayList<WorkOrder>();
public PendingWOArrayAdapter(Context context, int textViewResourceId,
List<WorkOrder> objects) {
super(context, textViewResourceId, objects);
this.workOrders = objects;
}
static class ViewHolder {
protected ImageView flagIcon;
protected TextView workOrderName;
protected TextView workOrderState;
protected TextView priority;
protected TextView plannedDate;
protected TextView asset;
protected CheckBox chkDownloadWorkOrder;
}
public int getCount() {
return this.workOrders.size();
}
public WorkOrder getItem(int index) {
return this.workOrders.get(index);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WorkOrder pendingWO = getItem(position);
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.pending_wos_list, parent, false);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.flagIcon = (ImageView) row.findViewById(R.id.flagIcon);
viewHolder.workOrderName = (TextView) row
.findViewById(R.id.TxtWorkOrder);
viewHolder.workOrderState = (TextView) row
.findViewById(R.id.TxtWorkOrderState);
viewHolder.priority = (TextView) row.findViewById(R.id.TxtPriority);
viewHolder.plannedDate = (TextView) row
.findViewById(R.id.TxtPlannedDate);
viewHolder.asset = (TextView) row.findViewById(R.id.TxtAsset);
viewHolder.chkDownloadWorkOrder = (CheckBox) row
.findViewById(R.id.ChkDownloadWorkOrder);
viewHolder.chkDownloadWorkOrder
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
WorkOrder workOrder = (WorkOrder) viewHolder.chkDownloadWorkOrder
.getTag();
workOrder.setSelected(buttonView.isChecked());
}
});
row.setTag(viewHolder);
viewHolder.chkDownloadWorkOrder.setTag(pendingWO);
} else {
((ViewHolder) row.getTag()).chkDownloadWorkOrder.setTag(workOrders
.get(position));
}
ViewHolder holder = (ViewHolder) row.getTag();
holder.workOrderName.setText(pendingWO.toString());
holder.workOrderState.setText("Estado OS: " + pendingWO.getWorkOrderState() + " - "
+ pendingWO.getWorkOrderStateName());
holder.priority.setText("Prioridade: " + pendingWO.getPriority());
holder.plannedDate.setText("Data Prevista: "
+ pendingWO.getPlannedDate());
holder.asset.setText("Ativo: " + pendingWO.getAsset() + " - "
+ pendingWO.getAssetName());
holder.flagIcon.setImageDrawable(pendingWO.getFlag());
holder.chkDownloadWorkOrder.setChecked(pendingWO.isSelected());
if (pendingWO.isChkVisible()) {
holder.chkDownloadWorkOrder.setVisibility(View.VISIBLE);
} else {
holder.chkDownloadWorkOrder.setVisibility(View.GONE);
}
return row;
}
}
it seems that the size of this list is too big to keep in memory without loss of performance. I would consider using a CursorAdapter, it is a better and cleaner solution to your problem, in my opinion.
Two good tutorials:
http://developer.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/part_4_-_using_cursoradapters/
http://www.gustekdev.com/2013/05/custom-cursoradapter-and-why-not-use.html