EDITED
I am working on a contact list and trying to implement sectioned listview. When the app gets started, only one of the Header (Section) starts displaying itself after some chunks of items repeatedly and changing its position on scrolling up/down.
Here is my code :
private class MySimpleCursorAdapter extends SimpleCursorAdapter {
Holder holder = null;
LayoutInflater layoutInflater;
// String keyWord = "empty";
public MySimpleCursorAdapter(Context context, int layout, Cursor cur,
String[] from, int[] to, int flag) {
super(context, layout, cur, from, to, flag);
}
public String getTitle(String contName) {
return contName.substring(0, 1);
}
#Override
public View newView(Context context, Cursor mCursor, ViewGroup parent) {
holder = new Holder();
layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String cont_Name = mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
View view = null;
if ( ! keyWord.equalsIgnoreCase(getTitle(cont_Name)) || keyWord.equals(null))
{
view = layoutInflater.inflate(R.layout.section_header, null);
TextView sectionTitle = (TextView) view.findViewById(R.id.title2);
sectionTitle.setText(getTitle(cont_Name));
keyWord = getTitle(cont_Name);
Log.d("KeyWord", keyWord);
Log.d("Contact Name", cont_Name);
}
else if(keyWord.equalsIgnoreCase(getTitle(cont_Name))) {
view = layoutInflater.inflate(R.layout.pm_fragment, null);
holder.contactTitle= (TextView)view.findViewById(R.id.textView1);
holder.contactDetail = (TextView)view.findViewById(R.id.textView2);
holder.contactTitle.setText(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
holder.contactDetail.setText(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
Log.d("KeyWord", keyWord);
Log.d("Contact Name", cont_Name);
String contactId_String = ""+mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
long contactId = Long.parseLong(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID)));
DatabaseHandler handler = new DatabaseHandler(getActivity());
Contact matchedContact = handler.getContact(contactId) ;
String dbContactId= "";
if(matchedContact != null){
if(matchedContact.getID() != 0 && ""+matchedContact.getID() != null){
dbContactId= ""+matchedContact.getID();
}
if(dbContactId.equals(contactId_String)){
holder.myImage = (ImageView) view.findViewById(R.id.imageView1);
holder.myImage.getLayoutParams().height = 100;
holder.myImage.getLayoutParams().width = 100;
holder.myImage.setBackgroundResource(R.drawable.person_empty_online);
}
}else{
holder.myImage = (ImageView) view.findViewById(R.id.imageView1);
holder.myImage.getLayoutParams().height = 100;
holder.myImage.getLayoutParams().width = 100;
holder.myImage.setBackgroundResource(R.drawable.person_empty_offline);
}
handler.close();
keyWord = getTitle(cont_Name);
}
return view;
}
}
During Debugging, After the ending line return view ; , it enters in CursorAdapter.class and passes by through the lines:
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
and enters in if condtion, but app doesn't crash.
Finally Got my answer my own after two weeks...my if-else conditions were too complex , so i make comparison on some different criteria.
if (mCursor.getPosition() > 0 && mCursor.moveToPrevious())
{
preName = mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
mCursor.moveToNext();
}
else if(mCursor.getPosition() == 0)
{
preName = null;
}
else{
preName = null;
}
if(preName != null){
preTitle = getTitle(preName);
}
//===============================================================================
/*
* Setting Header And Contact Details
*/
//===============================================================================
if(mCursor.isFirst()){
holder.titleText.setVisibility(View.VISIBLE);
holder.titleText.setText(itemTitle);
}
else if(preName != null){
if(! itemTitle.equalsIgnoreCase(preTitle))
{
holder.titleText.setVisibility(View.VISIBLE);
holder.titleText.setText(itemTitle);
}else{
holder.titleText.setVisibility(View.GONE);
}
}
holder.contactTitle.setText(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
holder.contactDetail.setText(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
Related
Hy all,
In my APP in need show list of contact (it's ok for the moment) in the listview.
And I want when in swipe in the right of the number the APP call the number.
I have this for the moment :
MainActivity :
getSupportFragmentManager().beginTransaction().replace(R.id.fragmentLayout, new FragContact()).commit();
In my frag :
public class FragContact extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS) == true) {
explain();
} else {
//demander l'autorisation
}
} else {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final ListView list = (ListView) rootView.findViewById(android.R.id.list);
final List<Map<String, Object>> contacts = retrieveContacts(getActivity().getContentResolver());
if (contacts != null) {
final SimpleAdapter adapter = new SimpleAdapter(getActivity(), contacts, R.layout.contact, new String[]{"contactNumber", "photo"}, new int[]{R.id.name,
R.id.photo});
adapter.setViewBinder(new SimpleAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Object data, String textRepresentation) {
if ((view instanceof ImageView) & (data instanceof Bitmap)) {
final ImageView image = (ImageView) view;
final Bitmap photo = (Bitmap) data;
image.setImageBitmap(photo);
return true;
}
return false;
}
});
list.setAdapter(adapter);
}
return rootView;
}
return null;
} else {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final ListView list = (ListView) rootView.findViewById(android.R.id.list);
final List<Map<String, Object>> contacts = retrieveContacts(getActivity().getContentResolver());
if (contacts != null) {
final SimpleAdapter adapter = new SimpleAdapter(getActivity(), contacts, R.layout.contact, new String[]{"contactNumber", "photo"}, new int[]{R.id.name,
R.id.photo});
adapter.setViewBinder(new SimpleAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Object data, String textRepresentation) {
if ((view instanceof ImageView) & (data instanceof Bitmap)) {
final ImageView image = (ImageView) view;
final Bitmap photo = (Bitmap) data;
image.setImageBitmap(photo);
return true;
}
return false;
}
});
list.setAdapter(adapter);
}
return rootView;
}
}
public List<Map<String, Object>> retrieveContacts(ContentResolver contentResolver)
{
final List<Map<String, Object>> contacts = new ArrayList<Map<String, Object>>();
final Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID}, null, null, null);
if (cursor == null)
{
Log.e("retrieveContacts", "Cannot retrieve the contacts");
return null;
}
if (cursor.moveToFirst() == true)
{
do {
final long id = Long.parseLong(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)));
final String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (contactNumber != null) {
final Bitmap photo = getPhoto(contentResolver, id);
final Map<String, Object> contact = new HashMap<String, Object>();
contact.put("contactNumber", contactNumber);
contact.put("photo", photo);
contacts.add(contact);
}
}
while (cursor.moveToNext() == true);
}
if (cursor.isClosed() == false)
{
cursor.close();
}
return contacts;
}
private Bitmap getPhoto(ContentResolver contentResolver, long contactId)
{
Bitmap photo = null;
final Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
final Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
final Cursor cursor = contentResolver.query(photoUri, new String[] { ContactsContract.Contacts.Photo.DATA15 }, null, null, null);
if (cursor == null)
{
Log.e("getPhoto", "Cannot retrieve the photo of the contact with id '" + contactId + "'");
return null;
}
if (cursor.moveToFirst() == true)
{
final byte[] data = cursor.getBlob(0);
if (data != null)
{
photo = BitmapFactory.decodeStream(new ByteArrayInputStream(data));
}
}
if (cursor.isClosed() == false)
{
cursor.close();
}
return photo;
}
private void askForPermission()
{
requestPermissions(new String[] { Manifest.permission.READ_CONTACTS }, 2);
}
private void explain()
{
askForPermission();
}
}
Actualy I have there :
Thank for you're help.
its my following code.
public class Wishlist extends Activity {
Button checkout;
ListView ListCart;
String name, cusid, ffname, llname, phone, fax, password, email;
String[] qu, s;
int[] g;
int k = 0;
String cost;
ProgressDialog pDialog = null;
List<CartProducts> product_list;
Context ctx;
Integer pos = 0, total = 0, q = 0, gtot = 0, total1 = 0, sum = 0;
SQLiteDatabase FavData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_modifywishlist);
Intent page1 = getIntent();
cusid = page1.getStringExtra("cus_id");
ffname = page1.getStringExtra("fname");
llname = page1.getStringExtra("lname");
phone = page1.getStringExtra("ph");
fax = page1.getStringExtra("fax");
password = page1.getStringExtra("password");
email = page1.getStringExtra("email");
ListCart = (ListView) findViewById(R.id.list_item);
pDialog = new ProgressDialog(this);
ctx = this;
FavData = Wishlist.this.openOrCreateDatabase("SHOPPING_CARTFAV", MODE_PRIVATE, null);
FavData.execSQL("CREATE TABLE IF NOT EXISTS fav_items(product_id varchar, name varchar, price varchar, quantity integer, model varchar, image varchar, manufacturer varchar )");
ArrayList<CartProducts> myList = new ArrayList<CartProducts>();
Cursor crsr = FavData.rawQuery("SELECT * FROM fav_items", null);
final String[] productID = new String[crsr.getCount()];
final String[] ProductName = new String[crsr.getCount()];
final String[] ProductPrice = new String[crsr.getCount()];
final String[] ProductQuantity = new String[crsr.getCount()];
final String[] ProductModel = new String[crsr.getCount()];
final String[] ProductImage = new String[crsr.getCount()];
final String[] ProductManufacturer = new String[crsr.getCount()];
int j = 0;
while (crsr.moveToNext()) {
String id = crsr.getString(crsr.getColumnIndex("product_id"));
productID[j] = id;//product_id,name,price,quantity,model,image,manufacturer
name = crsr.getString(crsr.getColumnIndex("name"));
ProductName[j] = name;
String price = crsr.getString(crsr.getColumnIndex("price"));
ProductPrice[j] = price;
String s = ProductPrice[j].toString();
s = s.replace(",", "");
String[] parts = s.split("\\."); // escape .
String part1 = parts[0];
String part2 = parts[1];
part1 = part1.replace("₹", "");
total = Integer.parseInt(part1); // Toast.makeText(Table.this, part1, Toast.LENGTH_SHORT).show();
String qnty = crsr.getString(crsr.getColumnIndex("quantity"));
ProductQuantity[j] = qnty;
String s2 = ProductQuantity[j].toString();
total1 = Integer.parseInt(s2);
sum = total * total1;
String model = crsr.getString(crsr.getColumnIndex("model"));
ProductModel[j] = model;
String image = crsr.getString(crsr.getColumnIndex("image"));
ProductImage[j] = image;
String manufacturer = crsr.getString(crsr.getColumnIndex("manufacturer"));
ProductManufacturer[j] = manufacturer;
//Toast.makeText(getApplicationContext(), productID[j] + "" + ProductName[j] + "" + ProductPrice[j] + "" + ProductQuantity[j] + "" + ProductModel[j] + "" + ProductImage[j] + "" + ProductManufacturer[j], Toast.LENGTH_SHORT).show();
myList.add(new CartProducts(productID[j], ProductName[j], ProductPrice[j], ProductQuantity[j], ProductModel[j], ProductImage[j], ProductManufacturer[j]));
gtot = gtot + sum;
j++;
}
ListCart.setAdapter(new Wishlist_Listadapter(ctx, R.layout.activity_wishlist_cartrow, myList));
getListViewSize(ListCart);
String s1 = ProductPrice.toString();
}
public static void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
//do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
if (listItem != null) {
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
if (params != null) {
params.height = totalHeight
+ (myListView.getDividerHeight() * (myListAdapter
.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
}
myListView.requestLayout();
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}
}
Adapter class
Public class Wishlist_Listadapter extends ArrayAdapter<CartProducts> {
Bitmap bitmap;
ImageView img;
String urll, name,totalps;
SQLiteDatabase FavData;
Integer total = 0, quanty = 1, grandtot = 0, i = 0;
String it;
Button addbtn, minbtn;
EditText editqu;
int total1 = 0, quantity=0, fulltotal = 0, sum;
SQLiteOpenHelper dbhelper;
Wishlist_Listadapter cart = Wishlist_Listadapter.this;
private int resource;
private LayoutInflater inflater;
private Context context;
int count=1 ;
public Wishlist_Listadapter(Context ctx, int resourceId, List<CartProducts> objects) {
super(ctx, resourceId, objects);
resource = resourceId;
inflater = LayoutInflater.from(ctx);
context = ctx;
}
public View getView(int position, View convertView, ViewGroup parent) {
/* create a new view of my layout and inflate it in the row */
convertView = (RelativeLayout) inflater.inflate(resource, null);
final ViewHolder viewholder;
viewholder = new ViewHolder();
final CartProducts banqt = getItem(position);
totalps=(banqt.getPrice());
String s = totalps.toString();
s = s.replace(",", "");
String[] parts = s.split("\\."); // escape .
String part1 = parts[0];
String part2 = parts[1];
part1 = part1.replace("₹", "");// Toast.makeText(getContext(), part1, Toast.LENGTH_LONG).show();
total = Integer.parseInt(part1);
quanty = Integer.parseInt(banqt.getQuantity());
grandtot = total *quanty;
viewholder.total = (TextView) convertView.findViewById(R.id.txt_total);
viewholder.total.setText(String.valueOf(grandtot));
Button delet = (Button) convertView.findViewById(R.id.btn_remove);
delet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*delete function*/
it = banqt.getProduct_id();
FavData = context.openOrCreateDatabase("SHOPPING_CARTFAV", context.MODE_PRIVATE, null);
FavData.execSQL("DELETE FROM fav_items WHERE product_id=" + it + ";");
Intent intent = ((Wishlist) context).getIntent();
((Wishlist) context).finish();
context.startActivity(intent);
}
});
viewholder.txtName = (TextView) convertView.findViewById(R.id.product_name);
viewholder.txtName.setText(banqt.getName());
img = (ImageView) convertView.findViewById(R.id.img_product);
urll = banqt.getImage().toString();
urll = urll.replaceAll(" ", "%20");// Toast.makeText(getContext(),urll,Toast.LENGTH_LONG).show();
new LoadImage().execute(urll);
return convertView;
}
static class ViewHolder {
TextView txtName;
TextView total;
EditText editqu;
TextView txtprice;
}
private class LoadImage extends AsyncTask<String, String, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected Bitmap doInBackground(String... args) {
try {
bitmap = BitmapFactory.decodeStream((InputStream) new URL(args[0]).getContent());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
protected void onPostExecute(Bitmap image) {
if (image != null) {
img.setImageBitmap(image);
// pDialog.dismiss();
} else {
// pDialog.dismiss();
Toast.makeText(getContext(), "Image Does Not exist or Network Error", Toast.LENGTH_SHORT).show();
}
}
}
}
listview is working properly
i just inflate cardview in listview.
when using this code image cannot displaying. only dispaly last image in list view
params.height = totalHeight
+ (myListView.getDividerHeight() * (myListAdapter
.getCount() - 1));
my problem is: In listview only displaying last image
check this image:
Try adding your ImageView to Holder class and use like viewholder.img.setImageBitmap(new LoadImage().execute(urll)) and change the return type to Bitmap
Use BaseAdapter instead of ArrayAdapter. Load and show image with UIL, Picasso or other image loader library.
public class ImageAdapter extends BaseAdapter {
private List<ImageBean> list;
private ArrayList<ImageBean> arraylist;
private LayoutInflater inflater;
public ImageAdapter(Context context, List<ImageBean> list) {
this.list = list;
inflater = LayoutInflater.from(context);
this.arraylist = new ArrayList<>();
}
#Override
public int getCount() {
return list.size();
}
#Override
public ImageBean getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.recycler_view_item, parent, false);
holder.ivImage = (ImageView) convertView.findViewById(R.id.ivImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Loading image with UIL example
ImageLoader.getInstance().displayImage(getItem(position).getUrl(), holder.ivImage, ImageUtils.UIL_USER_AVATAR_DISPLAY_OPTIONS);
return convertView;
}
private class ViewHolder {
public ImageView ivImage;
}
}
I am trying to build a demo chatting App.I want to show the messages with section headers as Dates like "Today","Yesterday","May 21 2015" etc.I have managed to achieve this but since the new View method gets called whenever I scroll the list.The headers and messages get mixed up.
For simplicity, I have kept the header in the layouts itself and changing its visibility(gone and visible) if the date changes.
Can you help me out with this? Let me know if anyone needs any more info to be posted in the question.
public class ChatssAdapter extends CursorAdapter {
private Context mContext;
private LayoutInflater mInflater;
private Cursor mCursor;
private String mMyName, mMyColor, mMyImage, mMyPhone;
// private List<Contact> mContactsList;
private FragmentActivity mActivity;
private boolean mIsGroupChat;
public ChatssAdapter(Context context, Cursor c, boolean groupChat) {
super(context, c, false);
mContext = context;
mMyColor = Constants.getMyColor(context);
mMyName = Constants.getMyName(context);
mMyImage = Constants.getMyImageUrl(context);
mMyPhone = Constants.getMyPhone(context);
mIsGroupChat = groupChat;
mCursor = c;
// mActivity = fragmentActivity;
/*try {
mContactsList = PinchDb.getHelper(mContext).getContactDao().queryForAll();
} catch (SQLException e) {
e.printStackTrace();
}*/
}
#Override
public int getItemViewType(int position) {
Cursor cursor = (Cursor) getItem(position);
return getItemViewType(cursor);
}
private int getItemViewType(Cursor cursor) {
boolean type;
if (mIsGroupChat)
type = cursor.getString(cursor.getColumnIndex(Chat.COLMN_CHAT_USER)).compareTo(mMyPhone) == 0;
else type = cursor.getInt(cursor.getColumnIndex(Chat.COLMN_FROM_ME)) > 0;
if (type) {
return 0;
} else {
return 1;
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = null;
int itemViewType = getItemViewType(cursor);
if (v == null) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (itemViewType == 0) {
v = mInflater.inflate(R.layout.row_chat_outgoing, parent, false);
} else {
v = mInflater.inflate(R.layout.row_chat_incoming, parent, false);
}
}
return v;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = new ViewHolder();
View v = view;
final Chat chat = new Chat(cursor);
boolean fromMe = mIsGroupChat ? chat.getUser().compareTo(mMyPhone) == 0 : chat.isFrom_me();
if (fromMe) {
// LOGGED IN USER'S DATA SETTING....
holder.chat_name = (StyleableTextView) v
.findViewById(R.id.chat_user_name);
holder.chat_time = (StyleableTextView) v
.findViewById(R.id.chat_time);
holder.chat_tag = (StyleableTextView) v
.findViewById(R.id.chat_tag);
int color = Color.parseColor("#FFFFFF");
v.setBackgroundColor(color);
holder.chat_name.setText("#You");
holder.chat_time.setText(AppUtil.getEventTime(chat.getTimestampLong()));
// header text setting and process..
holder.chat_header_text = (TextView) v.findViewById(R.id.header_text);
String str_date = AppUtil.covertToDate(chat.getTimestampLong());
String pref_date = SharePreferencesUtil.getSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, "");
if (!str_date.equalsIgnoreCase(pref_date)) {
holder.chat_header_text.setVisibility(View.VISIBLE);
SharePreferencesUtil.putSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, str_date);
holder.chat_header_text.setText(str_date);
} else {
holder.chat_header_text.setVisibility(View.GONE);
}
String firstWord, theRest;
String mystring = chat.getText();
String arr[] = mystring.split(" ", 2);
if (arr.length > 1) {
firstWord = arr[0]; // the word with hash..
theRest = arr[1]; // rest of the body..
holder.chat_tag.setText(Html.fromHtml("<font color=\"#999999\"><b>" + firstWord + "</b></font>" + " " + "<font color=\"#000000\">" + theRest + "</font>"));
// holder.chat_text.setText(theRest);
// holder.chat_text.setClickable(false);
} else {
String msg = arr[0]; // the word with hash..
holder.chat_tag.setText(Html.fromHtml("<font color=\"#999999\"><b>" + msg + "</b></font>"));
//holder.chat_text.setText("");
}
updateTimeTextColorAsPerStatus(holder.chat_time, chat.getStatus());
v.setTag(holder);
} else {
// OTHER USER'S DATA SETTING....
holder.chat_name = (StyleableTextView) v
.findViewById(R.id.chat_user_name);
holder.chat_time = (StyleableTextView) v
.findViewById(R.id.chat_time);
holder.chat_tag = (StyleableTextView) v
.findViewById(R.id.chat_tag);
holder.chat_image = (ImageView) v
.findViewById(R.id.chat_profile_image);
String image = cursor.getString(cursor.getColumnIndex("image"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String color = cursor.getString(cursor.getColumnIndex("color"));
// set the values...
if (holder.chat_image != null) {
MImageLoader.displayImage(context, image, holder.chat_image, R.drawable.round_user_place_holder);
}
int back_color = Color.parseColor("#FFFFFF");
v.setBackgroundColor(back_color);
holder.chat_name.setText(name);
holder.chat_time.setText(AppUtil.getEventTime(chat.getTimestampLong()));
// header text setting and process..
holder.chat_header_text = (TextView) v.findViewById(R.id.header_text);
String str_date = AppUtil.covertToDate(chat.getTimestampLong());
String pref_date = SharePreferencesUtil.getSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, "");
Log.d("eywa", "str date is ::::: " + str_date + " pref date is :::::: " + pref_date);
/*if (!TextUtils.isEmpty(pref_date)) {
if (!pref_date.contains(str_date)) {
holder.chat_header_text.setVisibility(View.VISIBLE);
SharePreferencesUtil.putSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, pref_date + str_date);
holder.chat_header_text.setText(str_date);
} else {
holder.chat_header_text.setVisibility(View.GONE);
}
} else {
holder.chat_header_text.setVisibility(View.VISIBLE);
SharePreferencesUtil.putSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, pref_date + str_date);
holder.chat_header_text.setText(str_date);
}*/
if (!str_date.equalsIgnoreCase(pref_date)) {
holder.chat_header_text.setVisibility(View.VISIBLE);
SharePreferencesUtil.putSharedPreferencesString(mContext, Constants.CHAT_TIMESTAMP, str_date);
holder.chat_header_text.setText(str_date);
} else {
holder.chat_header_text.setVisibility(View.GONE);
}
String firstWord, theRest;
String mystring = chat.getText();
String arr[] = mystring.split(" ", 2);
if (arr.length > 1) {
firstWord = arr[0]; // the word with hash..
theRest = arr[1]; // rest of the body..
holder.chat_tag.setText(Html.fromHtml("<font color=\"#999999\"><b>" + firstWord + "</b></font>" + " " + "<font color=\"#000000\">" + theRest + "</font>"));
// holder.chat_text.setClickable(false);
} else {
String msg = arr[0]; // the word with hash..
holder.chat_tag.setText(Html.fromHtml("<font color=\"#999999\"><b>" + msg + "</b></font>"));
// holder.chat_text.setText("");
}
String phone = cursor.getString(cursor.getColumnIndex("user"));
final Contact contact = new Contact(name, phone, "", color, image);
if (holder.chat_image != null) {
holder.chat_image.setTag(contact);
// holder.chat_name.setTag(contact);
holder.chat_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Contact con = (Contact) v.getTag();
Intent intent = new Intent(mContext, OtherProfileActivity.class);
intent.putExtra(Constants.EXTRA_CONTACT, con);
mContext.startActivity(intent);
}
});
}
v.setTag(holder);
}
/*else
{
view=
}*/
}
private void updateTimeTextColorAsPerStatus(TextView chat_time, int status) {
if (status == 0) chat_time.setVisibility(View.INVISIBLE);
else {
chat_time.setVisibility(View.VISIBLE);
/* if (status == 1)
chat_time.setTextColor(mContext.getResources().getColor(android.R.color.white));*/
if (status == 2)
chat_time.setTextColor(mContext.getResources().getColor(android.R.color.darker_gray));
else if (status == 3)
chat_time.setTextColor(mContext.getResources().getColor(android.R.color.black));
}
}
#Override
public int getViewTypeCount() {
return 2;
}
public class ViewHolder {
public StyleableTextView chat_name;
public StyleableTextView chat_time;
public StyleableTextView chat_tag;
public ImageView chat_image;
public TextView chat_header_text;
}
#Override
public int getCount() {
if (getCursor() == null) {
return 0;
} else {
return getCursor().getCount();
}
}
}
I am using an extended BaseAdapter for my gridview in which I implement ViewHolder methods. also I pass my data with a Cursor to this adapter.
here is my getView()
public View getView(int position, View view, ViewGroup parent) { // inflate the layout for each item of listView
ViewHolder holder;
if (view == null) {
view = inflater.inflate(gridItemId, null);
Log.d("recyvleView", "inflating " + position);
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);
} else {
Log.d("recyvleView", "restoring " + position);
holder = (ViewHolder) view.getTag();
}
setupView(view, position,holder);
//setupGridView(view,holder);
return view;
}
I noticed that I have a huge memory leak in this so I tried to minimize everything to find the leak, so I commented most of the methods and here is what has been left from my setupView:
private void setupView(View view, int position, ViewHolder holder) {
// move the cursor to required position
cursor.moveToPosition(position);
Log.d("POSITION", String.valueOf(position));
//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);
view.setTag(holder);*/
}
even though almost all of it is commented, these two lines are still leaking, I know cause when I commented them out, no leak was there ... !
holder.tvItemCode.setText(cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_ITEMCODE.toString())));
holder.tvProductName.setText(cursor.getString(cursor.getColumnIndex(DatabaseColumnContent.COL_PRODUCT_ITEMDESC.toString())));
also this is my holder class :
public class ViewHolder {
public ImageView tvAttachment;
public ImageView ivStatus;
public TextView imageCount;
public TextView tvItemCode;
public TextView tvProductName;
public TextView tvRemain;
public RialTextView tvPrice;
public String priceDef;
public String itemId;
public String itemGuId;
public Button btnMore;
public Button btnPlus;
}
any suggestion, please ?! how can I stop it from leaking ?!
thanks in advance!
EDIT:
I get same result using cursor adapter as well.
Why are you using BaseAdapter? Android API has CursorAdapter and CursorLoader which handles all the cursor stuff. Looks like you are doing something wrong with cursors and this causes memory leaks.
I have chat app
In custom array adapter. I set random colors to usernames for each message with this code:
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
nameTextView.setTextColor(Color.parseColor(randomColor));
When new message arrive I add it to listview, and call adapter.notifyDataSetChanged();
This causes recoloring existing usernames in messages each time.
How can I prevent recoloring existing items in listview when calling adapter.notifyDataSetChanged();
Edit 1
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ChatMessageElement el = list.get(position);
ViewHolder holder = null;
NewMessagesLabelHolder labelHolder = null;
if (convertView == null) {
convertView = el.getView(inflater, parent);
if (el.isMessage()) {
holder = new ViewHolder();
holder.messageLayout = (RelativeLayout) convertView.findViewById(R.id.message_container);
holder.messageContent = (LinearLayout) convertView.findViewById(R.id.message_content);
holder.bottomIndicator = (LinearLayout) convertView.findViewById(R.id.bottom_indicators);
holder.dateTextView = (TextView) convertView.findViewById(R.id.message_date);
holder.timeAgo = (TextView) convertView.findViewById(R.id.time_ago);
holder.nameTextView = (TextView) convertView.findViewById(R.id.user_name);
holder.likesCountTextView = (TextView) convertView.findViewById(R.id.likes_count);
holder.likesLabelImageView = (ImageView) convertView.findViewById(R.id.likes_label);
holder.spamCountTextView = (TextView) convertView.findViewById(R.id.spam_count);
holder.spamLabelImageView = (ImageView) convertView.findViewById(R.id.spam_label);
holder.avatarImageView = (ImageView) convertView.findViewById(R.id.avatar);
holder.statusImageView = (ImageView) convertView.findViewById(R.id.delivered_label);
holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar);
holder.errorSign = (ImageView) convertView.findViewById(R.id.error_sign);
holder.spamSign = (ImageView) convertView.findViewById(R.id.spam_sign);
holder.bookmarkLabel = (ImageView) convertView.findViewById(R.id.bookmark_label);
holder.topIndicators = (LinearLayout) convertView.findViewById(R.id.topIndicators);
convertView.setTag(holder);
}
if (el.isNewMessagesLabel()) {
convertView = inflater.inflate(R.layout.chat_new_messages_label_layout, parent, false);
labelHolder = new NewMessagesLabelHolder();
labelHolder.newMessagesLabel = (TextView) convertView.findViewById(R.id.new_messages_label);
convertView.setTag(labelHolder);
}
} else {
if (el.isMessage()) {
holder = (ViewHolder) convertView.getTag();
}
if (el.isNewMessagesLabel()) {
labelHolder = (NewMessagesLabelHolder) convertView.getTag();
}
}
if (el.isMessage()) {
Message currentMessage = (Message) el;
drawMessage(holder, currentMessage, position);
}
if (el.isNewMessagesLabel()) {
NewMessagesLabel messagesLabel = (NewMessagesLabel) el;
drawNewMessagesLabel(labelHolder, messagesLabel);
}
return convertView;
}
private void drawMessage(ViewHolder holder, Message message, int position) {
String date = message.getCreatedAt();
String formattedDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "HH:mm", date);
String userName = message.getUserName();
holder.likesLabelImageView.setVisibility(View.GONE);
holder.likesCountTextView.setVisibility(View.GONE);
holder.spamCountTextView.setVisibility(View.GONE);
holder.spamLabelImageView.setVisibility(View.GONE);
holder.bookmarkLabel.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.progressBar.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.errorSign.setVisibility(View.GONE);
holder.spamSign.setVisibility(View.GONE);
holder.timeAgo.setVisibility(View.GONE);
holder.timeAgo.setText("");
holder.messageLayout.setAlpha(1f);
holder.topIndicators.setVisibility(View.VISIBLE);
if (message.isNewDay()) {
holder.timeAgo.setVisibility(View.VISIBLE);
String dayDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "MMMM d, yyyy", date);
//String dayDate = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()), context);
holder.timeAgo.setText(dayDate);
}else{
holder.timeAgo.setVisibility(View.GONE);
}
holder.avatarImageView.setImageResource(R.drawable.com_facebook_profile_default_icon);
if (GrouviDatabaseManager.getInstance(context).getCurrentUser().getId() == message.getUserId()) {
userName = USERNAME_ME;
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SEND)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SENDING)) {
holder.progressBar.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_LOCAL)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() == null || message.getStatus().equals(Message.MSG_STATUS_ERROR)) {
holder.messageLayout.setAlpha(0.4f);
holder.errorSign.setVisibility(View.VISIBLE);
}
}
if (message.getSpamCount() > 0 && currentMode == MODE_NORMAL) {
holder.messageLayout.setAlpha(0.4f);
holder.spamSign.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
holder.spamCountTextView.setText(Integer.toString(message.getSpamCount()));
holder.spamCountTextView.setVisibility(View.VISIBLE);
holder.spamLabelImageView.setVisibility(View.VISIBLE);
} else {
holder.messageLayout.setAlpha(1f);
holder.spamSign.setVisibility(View.GONE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
}
if (currentMode == MODE_REPORT) {
String timeAgo = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()));
holder.timeAgo.setText(timeAgo);
holder.timeAgo.setVisibility(View.VISIBLE);
}
if (message.getUserAvatar() != null && !message.getUserAvatar().isEmpty()) {
try {
Picasso
.with(context)
.load(message.getUserAvatar())
.error(R.drawable.com_facebook_profile_default_icon)
.placeholder(R.drawable.com_facebook_profile_default_icon)
.into(holder.avatarImageView);
} catch (Exception e) {
Log.e("Main", e.getMessage(), e);
}
}
colorUsername(holder, message, userName);
holder.nameTextView.setText(userName);
holder.dateTextView.setText(formattedDate);
if (message.getLikesCount()>0) {
holder.likesCountTextView.setText(Integer.toString(message.getLikesCount()));
holder.likesCountTextView.setVisibility(View.VISIBLE);
holder.likesLabelImageView.setVisibility(View.VISIBLE);
}
if (message.isBookmarked()) {
holder.bookmarkLabel.setVisibility(View.VISIBLE);
}
List<MessageComponent> messageComponentList;
messageComponentList = message.getMessageComponents();
drawMessageContent(holder, messageComponentList, message);
holder.nameTextView.setTag(position);
holder.avatarImageView.setTag(position);
holder.nameTextView.setOnClickListener(userClickListener);
holder.avatarImageView.setOnClickListener(userClickListener);
// hang empty onLingClickListener to display context menu when
// long click on whole message
holder.nameTextView.setOnLongClickListener(longClickListener);
holder.avatarImageView.setOnLongClickListener(longClickListener);
}
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor = prevColor;
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
prevColor = randomColor;
prevMsgUserID = message.getUserId();
}
You should keep color in the data class, for example in the Message class, or keep Map in the adapter, that maps Message to Color. Then randomly create a color, when it doesn't present in the map. or use the color, if it present in the map. Using a map is good solution than keeping in the data class, when the color doesn't related to message, when it is not a message property, so in that case, a good solution is a keeping it in the adapter class, in the map, for example
private Map<Message, String> colorsMap = new HashMap<Message, String>();
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor;
if(colorsMap.contains(message)) {
randomColor = colorsMap.get(message);
}
else {
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
colorsMap.put(message, randomColor);
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
}
Basically you have to create a Collection of user data model.
Like ArrayList<UserModel> arr = new ArrayList<UserModel>();
User Model can contain-> userId,userColor,groupId(if group chat supported) and map this model with you DB.
Means you have to make a column in db and add userBgColor in user table and map it with the model and this model in array list and supply the array list to your custom adapter .
Your can use ORMLite for rational mapping .
Then in getView()
{
UserModel model = arr.get(position);
String color = user.getUserColor();
}