ListView images changing During Scroll - android

im try to make listview with dynamic images, using asyntask its download image and set into listview. my problem is while scroll down images get randomly changed..
class ps1 extends ArrayAdapter<String> {
Context context;
String[] images1;
List mList;
String[] namearray;
String[] rating;
static class ViewHolder {
ImageView localImageView1;
ImageView localImageView2;
ImageView localImageView3;
}
ps1(Context paramContext, String[] paramArrayOfString1, String[] paramArrayOfString2, String[] paramArrayOfString3) {
super(paramContext, R.layout.list2, R.id.imageView1, paramArrayOfString1);
this.context = paramContext;
this.images1 = paramArrayOfString3;
this.namearray = paramArrayOfString1;
this.rating = paramArrayOfString2;
}
public View getView(int paramInt, View paramView, ViewGroup paramViewGroup) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
ViewHolder viewHolder = new ViewHolder();
if (paramView == null) {
paramView = inflater.inflate(R.layout.list2, paramViewGroup, false);
}
viewHolder.localImageView1 = (ImageView) paramView
.findViewById(R.id.imageView1);
viewHolder.localImageView2 = (ImageView) paramView
.findViewById(R.id.imageView2);
viewHolder.localImageView3 = (ImageView) paramView
.findViewById(R.id.imageView3);
viewHolder.localImageView1.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView2.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView3.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView1.setTag(this.namearray[paramInt]);
new LoadImage().execute(viewHolder.localImageView1);
viewHolder.localImageView2.setTag(this.rating[paramInt]);
new LoadImage().execute(viewHolder.localImageView2);
viewHolder.localImageView3.setTag(this.images1[paramInt]);
new LoadImage().execute(viewHolder.localImageView3);
return paramView;
}
}
class LoadImage extends AsyncTask<Object, Void, Bitmap> {
private ImageView imv;
private Bitmap download_Image(String paramString) {
Bitmap localBitmap = null;
try {
Object localObject = null;
localBitmap = BitmapFactory
.decodeStream(((HttpURLConnection) new URL(paramString)
.openConnection()).getInputStream());
localObject = localBitmap;
if (localObject != null) {
return localBitmap;
}
} catch (Exception e) {
}
return localBitmap;
}
protected Bitmap doInBackground(Object... paramVarArgs) {
this.imv = ((ImageView) paramVarArgs[0]);
Log.d("fsdf", (String) this.imv.getTag());
return download_Image((String) this.imv.getTag());
}
protected void onPostExecute(Bitmap paramBitmap) {
this.imv.setImageBitmap(paramBitmap);
}
}

I have also experienced the same . I am also searching for a right solution . As far as i have searched , i came to know that ListView clears the previous view while scrolling down and re-loads it when you scroll back . So while scrolling up and down, your images may get re-cycled and mis-aligned . ( I am also waiting for the correct solution ) .
But i have tackled it using SmartImageView , which is a library that directly downloads the image and sets it to the ImageView . It will maintain the images in cache and so you could get the right images .
Comparatively this was faster too .

Try this snippet code which i have used in application and it's working fine in my application and i am sure it will work at your end.
In my condition i am retrieving images and some data from server and maintain all images on list scrolling fine.
class OfferCustomListAdapter extends ArrayAdapter<String>
{
private Context context;
Boolean OddNumber;
ArrayList<String> getDealID = new ArrayList<String>();
ArrayList<String> getInAdpterUNamedlist = new ArrayList<String>();
ArrayList<String> getShopNData = new ArrayList<String>();
ArrayList<String> getUserFav = new ArrayList<String>();
ArrayList<String> getTotalAmt = new ArrayList<String>();
ArrayList<String> getDealImage = new ArrayList<String>();
ArrayList<Boolean> getBoolnState = new ArrayList<Boolean>();
//String Oflist[] ;
int favCount=0;
public OfferCustomListAdapter(Context context,ArrayList<String> dealIdlist, ArrayList<Boolean> AddBoolnList, ArrayList<String> dealNamelist,ArrayList<String> ShopNList,ArrayList<String> UserFave,ArrayList<String> TotalAmt,ArrayList<String> ImageList) {
super(context, android.R.layout.simple_list_item_1,dealNamelist);
this.context=context;
//Oflist = getFolwerUNamelis;
getDealID = dealIdlist;
getInAdpterUNamedlist = dealNamelist;
getShopNData = ShopNList;
getUserFav = UserFave;
getTotalAmt = TotalAmt;
getDealImage = ImageList;
getBoolnState = AddBoolnList;
}
#Override
public View getView(final int pos, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(this.context);
//view = inflater.inflate(R.layout.offer_custom_list, parent,false);
view = inflater.inflate(R.layout.reservatin_row, parent,false);
holder = new ViewHolder();
//holder.FollowrName = (TextView) view.findViewById(R.id.OfferNameTxt);
holder.DealName = (TextView) view.findViewById(R.id.tv_name);
holder.ShopName = (TextView) view.findViewById(R.id.tv_address);
holder.FavBtn = (ImageView) view.findViewById(R.id.Ofr_FavBtn);
holder.listLayout = (LinearLayout) view.findViewById(R.id.OfferListLayout);
holder.profile_image = (ImageView)view.findViewById(R.id.profile_img);
holder.OfferAmtBtn =(Button)view.findViewById(R.id.TotalOfrBtn);
//holder.FavBtn = (ImageView) view.findViewById(R.id.offerFavBtn);
holder.FavBtn.setTag(pos);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if ( pos % 2 == 0 ){
System.out.println("You entered an even number. "+pos % 2);
holder.listLayout.setBackgroundResource(R.drawable.offer_list_bg);
}else{
System.out.println("You entered an odd number.");
holder.listLayout.setBackgroundResource(R.drawable.special_offer_bg);
}
/*if(getUserFav.get(pos).equals("0")){
//BolArraylist.add(false);
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
}else{
//BolArraylist.add(true);
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
}*/
holder.DealName.setText(getInAdpterUNamedlist.get(pos));
holder.ShopName.setText(getShopNData.get(pos));
holder.OfferAmtBtn.setText("$"+getTotalAmt.get(pos));
imgLoader.DisplayImage(getDealImage.get(pos), holder.profile_image);
holder.FavBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (isNetworkAvailable()) {
if(!userid.equals("")){
Offer_ID = getDealID.get(pos);
GUsrFavState = getUserFav.get(pos);
if(GUsrFavState.equals("0")){
GUsrFavState="1";
getUserFav.remove(pos);
getUserFav.add(pos, "1");
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
getBoolnState.set(pos, true);
new Call_OfferFavWS().execute();
}else{
GUsrFavState="0";
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
getUserFav.remove(pos);
getUserFav.add(pos, "0");
getBoolnState.set(pos, false);
new Call_OfferFavWS().execute();
}
}else{
Intent CallSignIn = new Intent(DollarMainActivity.this,SingInActivity.class);
startActivity(CallSignIn);
}
} else {
Toast alrtMsg = Toast.makeText(DollarMainActivity.this, "No network connection available !!!", Toast.LENGTH_LONG);
alrtMsg.setGravity(Gravity.CENTER, 0, 0);
alrtMsg.show();
}
}
});
if(getBoolnState.get(pos)){
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
}else{
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
}
return view;
}
class ViewHolder {
public TextView DealName,ShopName;
public ImageView FavBtn, profile_image;
public LinearLayout listLayout;
public Button OfferAmtBtn;
}
}
Hope it will help you.
if you need any help pls let me know.

Related

'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference

I just created an application on android optimized for the mobile phone. Now as the client asked to optimize for 17inch screen size without building separate apk. I almost implemented with some minor UI changes. But in case of listviews, they need Gridviews. So What I did was I created a separate layout for bigger screen with gridview I used a code to detect the screen size and in activity I used a code to detect the screen size and if it's bigger, then I initialized Gridview and after async task i added to a cardview adapter and set the gridview adapter to cardview adapter.
I switched gridview and listview as:
if(Constants.isScreenLarge(getActivity())) {
// width > height, better to use Landscape
mygrid = (GridView) getView().findViewById(R.id.card_gridview);
} else {
listView = (ListView)getView().findViewById(R.id.card_listView);
listView.addHeaderView(new View(getActivity()));
listView.addFooterView(new View(getActivity()));
}
Using Restclient helper:
public void fetchTransaction(){
loading.setVisibility(View.VISIBLE);
pd.setMessage("Fetching Transactions..Please Wait");
pd.setCancelable(false);
pd.show();
String fromDate = from.getText().toString();
String toDate = to.getText().toString();
//mydb.deleteAllTransactions();
cardArrayAdapter = new CardArrayAdapter(this.getActivity().getApplicationContext(), R.layout.list_item_card);
cardArrayAdapter.clear();
String android_id = Settings.Secure.getString(getActivity().getContentResolver(),
Settings.Secure.ANDROID_ID);
String userid = prefs.getString("userId","0");
Log.e("TRANSACTON", Constants.BASE_URL_TRANSACTIONS+"?deviceid="+android_id+"&userid="+userid+"&from="+fromDate+"&to="+toDate);
RestClientHelper.getInstance().get(Constants.BASE_URL_TRANSACTIONS+"?deviceid="+android_id+"&userid="+userid+"&from="+fromDate+"&to="+toDate, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
pd.dismiss();
try{
mydb.deleteAllTransactions();
JSONObject result = new JSONObject(response);
JSONArray posts = result.optJSONArray("result");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String id = post.optString("id");
String heading = post.optString("heading");
String description = post.optString("description");
String amount = post.optString("amount");
String imageurl = post.optString("imageurl");
String credit = post.optString("credit");
String date = post.optString("date");
String type = post.optString("type");
String service = post.optString("service");
String cost = post.optString("cost");
String balance = post.optString("balance");
String amountinfo = post.optString("amountinfo");
Log.e("ENTERING TO DB","DATA"+i);
Card card = new Card(heading, description,amount,date,credit,imageurl,cost,balance,amountinfo,id,service);
cardArrayAdapter.add(card);
//mydb.addTransactionContact(new TransactionData(heading, description, amount, imageurl,credit,type,date));
}
} catch (JSONException e) {
e.printStackTrace();
}
catch(Exception e){
}
finally {
//showTransaction();
rl = (RelativeLayout)getView().findViewById(R.id.noItems);
rl.setVisibility(view.INVISIBLE);
if(Constants.isScreenLarge(getActivity())) {
// width > height, better to use Landscape
mygrid.setAdapter(cardArrayAdapter);
} else {
listView.setAdapter(cardArrayAdapter);
}
cardArrayAdapter.notifyDataSetChanged();
}
}
#Override
public void onError(String error) {
pd.dismiss();
SnackbarManager.show(Snackbar.with(getActivity()) // context
.text("An Error occured.. Try after sometime"));
textView2.setText("Some Error Ocurred");
rl = (RelativeLayout)getView().findViewById(R.id.noItems);
rl.setVisibility(view.VISIBLE);
loading.setVisibility(View.INVISIBLE);
}
});
}
My CardArrayAdapter code is:
public class CardArrayAdapter extends ArrayAdapter<Card> {
private static final String TAG = "CardArrayAdapter";
private List<Card> cardList = new ArrayList<Card>();
private Context mContext;
DatabaseUserTable mydb;
PreferenceHelper prefs;
ProgressDialog pd;
static class CardViewHolder {
TextView line1;
TextView line2;
ImageView cimageView;
TextView amount;
TextView credit;
TextView date;
TextView cost;
TextView balance;
TextView amountinfo;
TextView costinfo;
TextView balanceinfo;
}
public CardArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.mContext = context;
mydb = new DatabaseUserTable(this.mContext);
prefs = new PreferenceHelper(this.mContext);
pd = new ProgressDialog(this.mContext);
}
#Override
public void add(Card object) {
cardList.add(object);
super.add(object);
}
#Override
public int getCount() {
return this.cardList.size();
}
#Override
public Card getItem(int index) {
return this.cardList.get(index);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
CardViewHolder viewHolder;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_card, parent, false);
viewHolder = new CardViewHolder();
viewHolder.line1 = (TextView) row.findViewById(R.id.line1);
viewHolder.line2 = (TextView) row.findViewById(R.id.line2);
viewHolder.amount = (TextView) row.findViewById(R.id.amount);
viewHolder.date = (TextView) row.findViewById(R.id.date);
viewHolder.credit = (TextView) row.findViewById(R.id.credit);
viewHolder.cimageView = (ImageView) row.findViewById(R.id.imageId);
viewHolder.cost = (TextView) row.findViewById(R.id.cost);
viewHolder.balance = (TextView) row.findViewById(R.id.balance);
viewHolder.amountinfo = (TextView) row.findViewById(R.id.amountinfo);
viewHolder.costinfo = (TextView) row.findViewById(R.id.costinfo);
viewHolder.balanceinfo = (TextView) row.findViewById(R.id.balanceinfo);
row.setTag(viewHolder);
} else {
viewHolder = (CardViewHolder)row.getTag();
}
Card card = getItem(position);
viewHolder.line1.setText(card.getLine1());
viewHolder.line1.setTextColor(Color.parseColor("#000000"));
viewHolder.line2.setText(card.getLine2());
viewHolder.line2.setTextColor(Color.parseColor("#999999"));
viewHolder.amount.setText(card.getAmount());
viewHolder.amount.setTextColor(Color.parseColor("#000000"));
viewHolder.date.setText(card.getDate());
viewHolder.date.setTextColor(Color.parseColor("#999999"));
viewHolder.credit.setText(card.getCredit());
viewHolder.credit.setTextColor(Color.parseColor("#000000"));
viewHolder.cost.setText(card.getCost());
viewHolder.cost.setTextColor(Color.parseColor("#000000"));
viewHolder.balance.setText(card.getBalance());
viewHolder.balance.setTextColor(Color.parseColor("#000000"));
viewHolder.amountinfo.setText(card.getAmountinfo());
viewHolder.amountinfo.setTextColor(Color.parseColor("#000000"));
viewHolder.costinfo.setText("Cost");
viewHolder.costinfo.setTextColor(Color.parseColor("#000000"));
viewHolder.balanceinfo.setText("Balance");
viewHolder.balanceinfo.setTextColor(Color.parseColor("#000000"));
final String salesid = card.getSalesid();
final String servicename = card.getServiceName();
row.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Log.e("TRANSACTIONS SERVICENAM",servicename);
if(servicename.equals("VOUCHER")) {
alertBox(v,salesid);
}
else if(servicename.equals("WALLET")) {
SnackbarManager.show(Snackbar.with(v.getRootView().getContext()) // context
.text("No Reprinting available for this transaction"));
}
else if(servicename.equals("ELECTRICITY")) {
errorAlert(v,"Printing not yet supported");
//alertBoxElectricity(v,salesid);
}
else if(servicename.equals("MONEY TRANSFER")) {
//errorAlert(v,"Printing not yet supported");
alertBoxMoney(v,salesid);
}
else{
alertBoxOther(v,salesid);
}
//Toast.makeText(v.getContext(), amountinfo, Toast.LENGTH_SHORT).show();
/*SnackbarManager.show(Snackbar.with(this) // context
.text(amountinfo));*/
}
});
Log.e("card.getLine1()",card.getLine1());
Log.e("TRASACTION URL",Constants.BASE_URL_IMAGE+card.getUrl());
Picasso.with(mContext).load(Constants.BASE_URL_IMAGE+card.getUrl()).fit().placeholder(R.drawable.mobeeloadicon).error(R.drawable.mobeeloadicon).into(viewHolder.cimageView);
return row;
}
But I got the error as:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a
null object reference
How can I change CardArrayAdapter as GridViewAdapter preserving all the Card data. Any Help please
UPDATE
I got this right. It was a silly mistake. I was populating the wrong layout.

OutOfMemory Exception in gridview

basically I have a gridview, in which I show my products (from 10 or 20 up to 1K+ items) each item has a couple of custom textviews, and an Imageview.
I use ViewHolder pattern and also Picasso library to load images asynchronously. I have no problem with showing items, speed or whatsoever, so I think it's safe to say that my getview function works quite nice, although I have one major problem which is with scrolling the gridview, up and down, my memory monitor only shows increase of course the increment rate depends on the item-view contents as when I commented the image loading part for example, the rate decreased.
what I guess is somehow the generated views are always staying in the memory and something prevents them from getting collected by the GC.
although sometimes, when I scroll slowly GC comes and collects and memory gets free, but scrolling fast will always result in OOM, sooner or later.
my main question is that if I have a memory leak or not?! since the gc sometimes works (slow scrlling), and sometimes lets the app crashes with OOM Exception.
and clearly I hope to find out my problem and every little bit of help would be appreciated in advance.
xml of the fragment-layout which hosts the Gridview:
<GridView
android:id="#+id/gv_Main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:animationCache="false"
android:clickable="true"
android:descendantFocusability="beforeDescendants"
android:gravity="center"
android:scrollingCache="false"
android:verticalSpacing="10dp"
/>
my adapter(this extends CursorAdapter, although I have exactly same problem whit baseadapter as well):
public class ShygunInventoryGridCursorAdapter extends CursorAdapter {
private Context mContext;
private Cursor cursor;
private int numColumns;
private int listItemId, listItemNoImageId, gridItemId;
private String[] type;
private String[] columnTitle;
private int[] viewId;
private String textTemp;
private CyberSetting cyberSetting;
private String unitDesc = "";
private boolean isMain;
private int size;
private LayoutInflater inflater;
private int thumbSize = 200;
private File pic;
private TPictureCatalog pictureCatalog;
private TProductCatalog productCatalog;
//private ViewGroup hostActivity;
//int idTemp;
private LayoutInflater cursorInflater;
public ShygunInventoryGridCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
this.mContext = context;
cursorInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
//this.cursor = c;
productCatalog=TProductCatalog.getInstance();
cyberSetting=CyberSetting.getInstance();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = cursorInflater.inflate( R.layout.listview_inventory_product_griditems, parent, false);
ViewHolder holder = new ViewHolder();
holder.tvAttachment = (ImageView) view.findViewById(R.id.iv_inventory_products_griditems_attachment);
holder.imageCount = (TextView) view.findViewById(R.id.imagecount);
holder.tvItemCode = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_ItemCode);
holder.tvProductName = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_Title);
holder.tvPrice = (RialTextView) view.findViewById(R.id.tv_inventory_products_griditems_Price);
holder.tvRemain = (TextView) view.findViewById( R.id.tv_inventory_products_griditems_Remain);
holder.btnMore =(com.rey.material.widget.Button) view.findViewById(R.id.btn_inventory_products_griditems_More);
holder.btnPlus = (com.rey.material.widget.Button) view.findViewById(R.id.btn_inventory_products_griditems_addOne);
view.setTag(holder);
Log.d("CurAd","newView");
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
Log.d("CurAd","bindView");
ViewHolder holder;
holder = (ViewHolder) view.getTag();
holder.itemId = cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_ITEM_ID.toString()));
TSimpleProduct tempProduct = productCatalog.getSimpleProductById(Integer.parseInt(holder.itemId));
holder.itemGuId = cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_GUID.toString()));
holder.tvItemCode.setText(cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_ITEMCODE.toString())));
holder.tvProductName.setText(cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_ITEMDESC.toString())));
//Remain
if (cyberSetting.getSettingValue(TCyberSettingKey.SHOWITEMREMAIN).equals("1")) {
textTemp = (mContext.getString(R.string.restrictedInfo));
} else {
if (tempProduct.getDefaultUnitValue() == 2 && tempProduct.isUnitDependent()) {
String titleRemain2 = DatabaseColumnContent.COL_PRODUCT_CURSOR_REMAIN2.toString();
textTemp = cursor.getString(cursor.getColumnIndex(titleRemain2));
}
if (cyberSetting.getSettingValue(TCyberSettingKey.SHOWITEMREMAIN).equals("2")) {
if (textTemp == null) {
textTemp = "0";
}
int t = Integer.parseInt(textTemp);
if (t > 0) {
textTemp = mContext.getString(R.string.productAvailable);
} else {
textTemp = mContext.getString(R.string.productUnAvailable);
}
}
}
holder.tvRemain.setText(textTemp);
//Price
String priceLevel = "0";
try {
Register register = Register.getInstance();
priceLevel = register.getPriceLevel();
} catch (NoDaoSetException e) {
e.printStackTrace();
}
if(!priceLevel.equals("0"))
textTemp = cursor.getString(cursor.getColumnIndex(priceLevel));
else
textTemp = "0.0";
if (tempProduct.getDefaultUnitValue() == 2 && tempProduct.isUnitDependent()) {
double price2;
price2 = TLineItem.convertPrice1ToPrice2(Double.parseDouble(textTemp), tempProduct.isUnit1Bigger(), tempProduct.getUnitCoef());
textTemp = TGeneralTools.ConvertDoubleToEnglishString(price2);
if (tempProduct.getUnitDesc2() != null && !tempProduct.getUnitDesc2().equals(""))
unitDesc = " (" + tempProduct.getCompleteUnitDesc2() + ")";
} else {
if (tempProduct.getUnitDesc1() != null && !tempProduct.getUnitDesc1().equals(""))
unitDesc = " (" + tempProduct.getCompleteUnitDesc1() + ")";
}
holder.priceDef = textTemp;
holder.tvPrice.setText(textTemp + unitDesc);
holder.tvRemain.setText(holder.tvRemain.getText() + unitDesc);
//image
pictureCatalog = TPictureCatalog.getInstance();
String defGuid = "";
if (tempProduct.getHasAttachContent() >= 1 && pictureCatalog.isDownloadedAlbumAvailable()) {
defGuid = pictureCatalog.getDefaultPictureGuid(holder.itemGuId);
if (tempProduct.getHasAttachContent() == 1) {
holder.imageCount.setVisibility(View.GONE);
} else {
holder.imageCount.setVisibility(View.VISIBLE);
holder.imageCount.setText(String.valueOf(tempProduct.getHasAttachContent()));
}
} else {
holder.imageCount.setVisibility(View.GONE);
}
String filename = Environment.getExternalStorageDirectory().getPath()
+ FileAddressContent.APPLICATION_HOME_DIRECTORY
+ FileAddressContent.PICTURES_ROOT_DIRECTORY
//+ FileAddressContent.PICTURES_THUMBS_DIRECTORY.toString()
+ defGuid + FileAddressContent.PICTURES_EXTENSION;
pic = new File(filename);
if (pic.exists())
Picasso.with(mContext)
.load(pic)
.error(R.drawable.noimage)
//.placeholder(R.drawable.loading)
.resize(thumbSize, thumbSize)
.centerInside()
.into(holder.tvAttachment);
else
Picasso.with(mContext)
.load(R.drawable.noimage)
.resize(thumbSize, thumbSize)
.centerInside()
.into(holder.tvAttachment);
holder.tvAttachment.setMinimumHeight(thumbSize);
setupGridView(view, holder);
}
private void setupGridView(View view, final ViewHolder holder) {
/*final ImageView iv = (ImageView) view.findViewById(R.id.iv_inventory_products_griditems_attachment);
com.rey.material.widget.Button btMore = (com.rey.material.widget.Button) view.findViewById(R.id.btn_inventory_products_griditems_More);
com.rey.material.widget.Button btPlus = (com.rey.material.widget.Button) view.findViewById(R.id.btn_inventory_products_griditems_addOne);
//final TextView tvTitle = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_Title);
final RialTextView tvPrice = (RialTextView) view.findViewById(R.id.tv_inventory_products_griditems_Price);
final TextView tvItemId = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_ItemId);
final TextView tvGuId = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_GuId);
//final TextView tvRemain = (TextView) view.findViewById(R.id.tv_inventory_products_griditems_Remain);*/
holder.tvAttachment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/* BitmapDrawable bitmapDrawable = ((BitmapDrawable) iv.getDrawable());*/
showImageDialog(holder.itemGuId);
}
});
holder.btnMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*addToInvoiceDialog(tvTitle.getText().toString(), tvPrice.getText().toString(), tvItemId.getText().toString(),
tvRemain.getText().toString(),iv.getDrawable(),tvGuId.getText().toString());*/
showAddToInvoiceFragment(holder.itemId, holder.priceDef);
}
});
holder.btnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//InventoryFragment.AddToInvoice(holder.itemId, 1, holder.priceDef, null, null);
}
});
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
private void showImageDialog(String ReferenceGuId) {
//InventoryFragment.openAlbum(ReferenceGuId);
}
private void showAddToInvoiceFragment(String itemId, String priceDef) {
//InventoryFragment.showAddToInvoiceFragment(itemId, priceDef);
}
}
this is the part in my java code where I set the adapter:
ShygunInventoryGridCursorAdapter listAdapter1 = new ShygunInventoryGridCursorAdapter(context,cursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
gridView.setNumColumns(colCount);
gridView.setAdapter(listAdapter1);
MAT screen( I could not reach anywhere here, I mean non of roots or ... was my own code)
Not to mention, adding System.gc() at the end of get View method in the adapter will solve everything, but I'm sure it's not the right thing to do

ListView disappears after reloading it again

I have 3 arraylist that i have combined to show in listview. Wehen i click on to generate listview, it works fine the first time but when i hit back and then click the button again, the listview shows nothing. Not sure what is cause it. I checked other post but couldnt find an answer. I am not too good with Arraylist so any details would be greatly appreciated.
I have also noticed this message in Log cat. not sure what it means.
onVisibilityChanged() is called, visibility : 0
public class Edit extends Activity implements OnItemClickListener {
private int pic;
public String filename ="User Info";
//Declaring SHareddPreference as userprofile
static SharedPreferences userprofile;
ListView listView;
List<RowItem> rowItems;
// String[] titles, descriptions;
File imgpath=null;
Context context=this;
CustomListAdapter adapter;
private List<String> Titles = new ArrayList<String>();
private List<String> Actions = new ArrayList<String>();
private List<Bitmap> Images = new ArrayList<Bitmap>();
int x;
int y=1;
int z=1;
static int a=1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aname);
listView = (ListView)findViewById(R.id.listing);
userprofile = getSharedPreferences(filename,0);
Intent pdf=getIntent();
pic= userprofile.getInt("lastpic",pic);
x=pic;
Log.d("editpic",new Integer(pic).toString());
while(y!=x){
String comment = commentresult();
Titles.add(comment);
y++;
Log.d("y",new Integer(y).toString());
}
while(z!=x){
String act = actionresult();
Actions.add(act);
z++;
Log.d("z",new Integer(z).toString());}
while(a!=x){
Bitmap photo = getbitmap();
Images.add(photo);
a++;
Log.d("a",new Integer(a).toString());}
Titles.toArray();
Actions.toArray();
Images.toArray();
rowItems = new ArrayList<RowItem>();
for (int i = 0; i < Images.size(); i++) {
RowItem item = new RowItem(Images.get(i), Titles.get(i),Actions.get(i));
rowItems.add(item);
}
Log.d("TAG", "listview null? " + (listView == null));
CustomListAdapter adapter = new CustomListAdapter(this,
R.layout.aname_list_item, rowItems);
Log.d("TAG", "adapter=null? " + (adapter == null));
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
listView.setOnItemClickListener(this);
}
public static Bitmap getbitmap() {
String photo1 =userprofile.getString("picpath"+a, "");
File imgpath=new File(photo1);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bmp=DecodeImage.decodeFile(imgpath, 800, 1000, true);
bmp.compress(Bitmap.CompressFormat.JPEG, 100 , stream);
Bitmap photo2=bmp;
return photo2;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast toast = Toast.makeText(getApplicationContext(),
"Item " + (position + 1) + ": " + rowItems.get(position),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
public String commentresult()
{
// String com2 = null;
// while(y!=x){
String comment=userprofile.getString("comment"+y, "");
String com1=comment;
String com2=com1;
// }
return com2;
}
public String actionresult()
{
// String act2 = null;
// while(y!=x){
String action=userprofile.getString("action"+z, "");
String act1=action;
String act2=act1;
// }
return act2;
}
private static final long delay = 2000L;
private boolean mRecentlyBackPressed = false;
private Handler mExitHandler = new Handler();
private Runnable mExitRunnable = new Runnable() {
#Override
public void run() {
mRecentlyBackPressed=false;
}
};
#Override
public void onBackPressed() {
//You may also add condition if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) // in case of Fragment-based add
if (mRecentlyBackPressed) {
mExitHandler.removeCallbacks(mExitRunnable);
mExitHandler = null;
super.onBackPressed();
}
else
{
mRecentlyBackPressed = true;
Toast.makeText(this, "press again to exit", Toast.LENGTH_SHORT).show();
mExitHandler.postDelayed(mExitRunnable, delay);
}
}
#Override
public void onDestroy() {
// Destroy the AdView.
super.onDestroy();
}
Custom List Adapter:
public class CustomListAdapter extends ArrayAdapter<RowItem> {
Context context;
List<RowItem> items;
public CustomListAdapter(Context context, int resourceId,
List<RowItem> items) {
super(context, resourceId, items);
this.context = context;
this.items = items;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public RowItem getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtTitle;
TextView txtDesc;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.aname_list_item, null);
holder = new ViewHolder();
holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
holder.txtTitle = (TextView) convertView.findViewById(R.id.rab);
holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// String name=items.get(position).getDesc();
holder.txtDesc.setText(rowItem.getDesc());
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageBitmap(rowItem.getImageId());
// holder.imageView.setImageResource(Images.get(position) .getPlaceholderleft());
return convertView;
}
}
It looks like this is because you've made your variables x, y, z and a all static, which means there is a single instance of the variables shared by all instances of the class. Therefore, when you call onCreate the second time, all your while loop termination conditions are already met, so the while loops never execute. It's unclear to me why you've made these static, so unless you need them to be, you should remove the static keyword for these variables.
Why are you creating another object of ListView in onCreate() and onResume()
Remove code from onResume()
Also replace this line in onCreate()
old line ListView listView = (ListView)findViewById(R.id.listing);
New line listView = (ListView)findViewById(R.id.listing);

Wrong Loading Data when using Viewholder in BaseAdapter Android

I am using BaseAdapter for loading the data in gridview. When the data is loaded to the gridview, and the user tries to scroll, I used to get incorrect data. In order to fix that I used ViewHolder. That actually fixed the issue, however, when the users click any of the data in the gridview, instead of getting the correct id from the item, all the items are returning a similar id number.
public class ProductAdapter extends BaseAdapter {
// Context context;
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
ViewHolder holder;
int layoutResourceId;
Event event;
EventDBAdapter eventDb;
int id;
PersianCalendar sc;
String Today;
SharedPreferences Prefrences_test;
String date, userid;
String newText = "";
String test;
int status;
MoodsDBAdapter moodsDBAdapter;
Mood mood;
ArrayList<MoodsNote> arrayMoodsNote;
MoodsNoteDBAdapter moodsNoteDBAdapter;
MoodsNote moodsNote;
public ProductAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
// this.context = context;
eventDb = new EventDBAdapter(activity);
event = new Event();
moodsDBAdapter = new MoodsDBAdapter(activity);
mood = new Mood();
moodsNoteDBAdapter = new MoodsNoteDBAdapter(activity);
data = d;
// this.layoutResourceId = layoutResourceId;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Prefrences_test = activity.getSharedPreferences("temp", 0);
date = Prefrences_test.getString("date", "");
userid = Prefrences_test.getString("userid", "");
sc = new PersianCalendar();
Today = date;
eventDb = new EventDBAdapter(activity.getApplicationContext());
event = eventDb.getName(Today);
try {
arrayMoodsNote = moodsNoteDBAdapter.getItems(event.getID());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
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;
holder = null;
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
if (vi == null) {
vi = inflater.inflate(R.layout.note_mood_list_item, null);
holder = new ViewHolder();
holder.title = (TextView) vi.findViewById(R.id.mood_text);
holder.txt_id = (TextView) vi.findViewById(R.id.txt_id_mood);
holder.thumb_image = (ImageView) vi.findViewById(R.id.mood_img);
holder.linear = (LinearLayout) vi.findViewById(R.id.mood_layout);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
holder.linear.setBackgroundResource(R.drawable.bg_mood);
//holder.txt_id.setText("");
String titles = song.get("name");
holder.title.setText(titles);
Resources res = activity.getResources();
int resourceId = res.getIdentifier(song.get("icon"), "drawable",
activity.getPackageName());
holder.thumb_image.setBackgroundResource(resourceId);
holder.txt_id.setText(song.get("id"));
try {
for (MoodsNote m : arrayMoodsNote) {
int moodd = m.getMOOD();
if (Integer.parseInt(holder.txt_id.getText().toString()) == moodd)
{
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
}
} catch (Exception e) {
// TODO: handle exception
}
holder.thumb_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(activity, holder.txt_id.getText().toString(), 0).show();
status = 1;
event = new Event();
int tedad = eventDb.getDate(date);
if (tedad <= 0) {
event = new Event(userid, date);
eventDb.insert(event);
}
event = eventDb.getName(date);
moodsNote = new MoodsNote();
id = 0;
id = Integer.parseInt(holder.txt_id.getText().toString());
// id = rowItem.getID();
int tedadd = moodsNoteDBAdapter.getLastItemID(id);
if (tedadd <= 0)
{
moodsNote.setMOOD(id);
moodsNote.setEVENT(event.getID());
moodsNoteDBAdapter.insert(moodsNote);
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
else {
moodsNoteDBAdapter.deleteId(id);
holder.linear.setBackgroundResource(R.drawable.bg_mood);
}
}
});
return vi;
}
static class ViewHolder {
ImageView thumb_image;
TextView txt_id, title;
LinearLayout linear;
}

ListView too slow when scrolling

This seems to be a common question but I haven't been able to implement any of the solutions I have found. I have a Listview with a custom adapter that displays a thumbnail and text field in a row. The thumbnails are from a folder that I previously created and put the pictures I take from my app.
Here is my list activity:
private LayoutInflater mInflater;
private Vector<RowData> data;
private CustomAdapter adapter;
private RowData rd;
static File path = Environment.getExternalStorageDirectory();
static File fnames = new File(path, "MyImages");
static String[] title = fnames.list();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blog);
mInflater = (LayoutInflater) getSystemService(
Activity.LAYOUT_INFLATER_SERVICE);
setListName();
data = new Vector<RowData>();
for(int i=0;i<title.length;i++){
try {
rd = new RowData(i,title[i]);
} catch (ParseException e) {
e.printStackTrace();
}
data.add(rd);
}
getListView().setTextFilterEnabled(true);
getListView().setScrollingCacheEnabled(false);
}
public void onRestart()
{
super.onRestart();
setListName();
}
private Vector<RowData> setListName()
{
data = new Vector<RowData>();
String[] title = fnames.list();
//get the databases textblog
DatabaseHandler db = new DatabaseHandler(this);
List<TextBlog> textBlogs = db.getAllText();
int positionRaw = textBlogs.size();
for (int i=0;i<textBlogs.size(); i++) {
rd = new RowData(i, textBlogs.get(i).getText());
data.add(rd);
}
for(int i=0;i<title.length;i++) {
try {
rd = new RowData(positionRaw,title[i]);
positionRaw++;
} catch (ParseException e) {
e.printStackTrace();
}
data.add(rd);
}
adapter = new CustomAdapter(this, R.layout.list,R.id.title, data);
setListAdapter(adapter);
getListView().setTextFilterEnabled(true);
adapter.notifyDataSetChanged();
return data;
}
//Create thumbnail from file picture
private Bitmap decodeFile(File f) {
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while (o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
//Set row object
private class RowData
{
protected int mId;
protected String mTitle;
RowData(int id,String title){
mId=id;
mTitle = title;
}
#Override
public String toString() {
return mId+" "+mTitle+" ";
}
and here is my custom adaptor:
public class CustomAdapter extends ArrayAdapter<RowData>
{
public CustomAdapter(Context context, int resource, int textViewResourceId,
List<RowData> objects)
{
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
TextView title = null;
ImageView thumb=null;
RowData rowData= getItem(position);
if(null == convertView) {
convertView = mInflater.inflate(R.layout.list, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
title = holder.gettitle();
title.setText(rowData.mTitle);
thumb=holder.getImage();
File file = new File(path + "/MyImages/" + rowData.mTitle);
//Check what kind of file is it to add thumbnail
//Way too slow use asynchronous task
if (rowData.mTitle.substring(rowData.mTitle.lastIndexOf('.') + 1).equalsIgnoreCase("mp4") == true)
{
Bitmap thumbVideo = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
thumb.setImageBitmap(thumbVideo);
}
else if (rowData.mTitle.substring(rowData.mTitle.lastIndexOf('.') + 1).equalsIgnoreCase("3gpp") == true)
{
thumb.setImageDrawable(getResources().getDrawable(R.drawable.voice));
}
else
{
thumb.setImageBitmap(decodeFile(file));
}
return convertView;
}
private class ViewHolder {
private View mRow;
private TextView title = null;
private ImageView thumb=null;
public ViewHolder(View row) {
mRow = row;
}
public TextView gettitle() {
if(null == title) {
title = (TextView) mRow.findViewById(R.id.title);
}
return title;
}
public ImageView getImage() {
if (null == thumb) {
thumb = (ImageView) mRow.findViewById(R.id.img);
}
return thumb;
}
}
}
}
I am quiet sure it's because of the thumbnails creation and I have to implement it in a AsynchTask, but I tried witout any success.
Can anyone suggest where I'm going wrong, or at list give me a tips?
You are trying to implement here the ViewHolder pattern, but your implementation looks wrong.
The idea of this pattern is to reduce the call to findViewById()which has an impact on your performance. Only if the row is null (convertView) you should call findViewById(), otherwise reuse the previous view saved with the setTag()
Lets take a look at your code:
if(null == convertView){
convertView = mInflater.inflate(R.layout.list, null);
holder = new ViewHolder();
convertView.setTag(holder);
}
// .......
title = holder.gettitle();
// .........
thumb=holder.getImage();
Notice that holder.getTitle(), and holder.getImage() are called after the if statement. This means they will be called every time regardless if the convertView is null or not.
Now, taking a look at these getters we see that they contain code that calls findViewById();
Ex. for the getTitle()
public TextView gettitle() {
if(null == title){
title = (TextView) mRow.findViewById(R.id.title);
}
return title;
}
So, basically, you don't use here ViewHolder pattern, just some mixed code, and in the end the findViewById() is called every time which reduces the performance of ListView.
To do it correctly you should call findViewById() only when the convertView is null.
Ex:
if(null==convertView){
convertView = mInflater.inflate(R.layout.list, null);
holder = new ViewHolder();
// Getting a refernce to the views with findViewById()
title = holder.gettitle();
thumb=holder.getImage();
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
// Then you set the appropriate values to your views through the holder:
holder.title.setText("");
holder.thumb.setImageBitmap(...);
This is the correct way to implement ViewHolder pattern
(PS: You'll need to change the access modifier for the title, thumb,... to public.)

Categories

Resources