In one of activity contains RecyclerView in which certain items are rendered and on clicking any item its moving to another activity which is having a massive data from a server, its like a detail page of news along with images from server to render in its gallery section, using ViewPager along PagerAdapter(Some news articles may contains 20-30 images.
Whenever I move forward and backward from these activites my application crashes with OutOfMemory Error.
So far I have tried calling System.gc() and then finish() after moving back from detail activity to the one containing RecyclerView but still getting OutOfMemory errors.
I know its a memory leak as its getting large amount of data and then rendering at different places in activity but don't know how to handle it.
I have read some solutions mentioning android:largeHeap but it also doesn't guarentee that you may get large heap with some other cons like frequent pausings.
PagerAdapter:
public class SingleNewsGalleryAdapter extends PagerAdapter {
private String URL="some url";
Context mContext;
LayoutInflater mLayoutInflater;
List<String> newsList= Collections.emptyList();
int width=-1;
int heigth=-1;
public SingleNewsGalleryAdapter(Context context,List<String> newsList) {
this.newsList = newsList;
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return newsList.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((RelativeLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
final int pos = position;
View itemView = mLayoutInflater.inflate(R.layout.single_news_pager_layout, container, false);
final Holder holder = new Holder();
holder.imageView = (ImageView) itemView.findViewById(R.id.slidr_img);
holder.left = (ImageView) itemView.findViewById(R.id.swipe_left);
if(position==0){
holder.left.setColorFilter(ContextCompat.getColor(mContext, R.color.trans_black));
}
holder.right= (ImageView) itemView.findViewById(R.id.swipe_right);
if(position==(newsList.size()-1)){
holder.right.setColorFilter(ContextCompat.getColor(mContext, R.color.trans_black));
}
holder.left.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(pos>0){
int desc = pos-1;
if(mContext instanceof SingleNewsActivity){
((SingleNewsActivity)mContext).changePage(desc);
}
}
}
});
holder.right.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(pos<newsList.size()){
if(mContext instanceof SingleNewsActivity){
int inc = pos+1;
((SingleNewsActivity)mContext).changePage(inc);
//Toast.makeText(mContext,pos+"",Toast.LENGTH_LONG).show();
}
}
}
});
String news = newsList.get(position);
//imageView.setImageResource(newsList.get(position).getNews_photo());
int dpiCheck=0;
String res="";
switch (mContext.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
dpiCheck=1;
break;
case DisplayMetrics.DENSITY_MEDIUM:
dpiCheck=2;
break;
case DisplayMetrics.DENSITY_HIGH:
dpiCheck=3;
break;
case DisplayMetrics.DENSITY_XHIGH:
dpiCheck=4;
break;
}
if(dpiCheck==3){
res="525x255x1-";
}
else if(dpiCheck==4){
res="700x340x1-";
}
// res = width+"x"+height+"x1-";
String url = URL+res+news;
Uri uri = Uri.parse(url);
Picasso.with(this.mContext).load(uri).into(holder.imageView);
container.addView(itemView);
return itemView;
}
#Override
public float getPageWidth(int position) {
return 1f;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((RelativeLayout) object);
}
static class Holder {
ImageView imageView;
ImageView left;
ImageView right;
}
}
and my RecyclerAdapter from the listing activity:
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.MyViewHolder> {
String URL = "some url";
List<News> newsList = Collections.emptyList();
Context ctx;
int layoutID;
public NewsAdapter(List<News> newsList, Context ctx, int layout) {
this.layoutID = layout;
this.newsList = newsList;
this.ctx = ctx;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(layoutID, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
News news = newsList.get(position);
String title = news.getNews_title();
holder.title.setText(title);
String desc = news.getNews_description();
String htmlDesc;
String formatedDesc =desc.substring(0, Math.min(desc.length(), 50))+"...";
if (Build.VERSION.SDK_INT >= 24) {
holder.desc.setText(Html.fromHtml(desc, Html.FROM_HTML_SEPARATOR_LINE_BREAK_DIV));
} else {
holder.desc.setText(Html.fromHtml(desc));
}
String authorName;
if(news.getAuthor().trim().equals("") || news.getAuthor()==null){
authorName="Anonymous";
}
else{
authorName = news.getAuthor().trim();
}
holder.author.setText(authorName);
//Format Date
SimpleDateFormat fromUser = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat myFormat = new SimpleDateFormat("d/M/yy");
String formatedDate="";
try {
formatedDate = myFormat.format(fromUser.parse(news.getNews_add_date()));
} catch (ParseException e) {
e.printStackTrace();
}
holder.date.setText(formatedDate);
//view counter format
Integer viewCount = Integer.parseInt(news.getViews());
DecimalFormat formatter = new DecimalFormat("##,##,###");
String number = formatter.format(viewCount);
holder.views.setText(number);
//comments counter format
Integer commentCount = Integer.parseInt(news.getComments());
formatter = new DecimalFormat("##,##,###");
String c_number = formatter.format(commentCount);
holder.comments.setText(c_number);
int dpiCheck=0;
String res="";
switch (ctx.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
dpiCheck=1;
break;
case DisplayMetrics.DENSITY_MEDIUM:
dpiCheck=2;
break;
case DisplayMetrics.DENSITY_HIGH:
dpiCheck=3;
break;
case DisplayMetrics.DENSITY_XHIGH:
dpiCheck=4;
break;
}
if(dpiCheck==3){
res="165x165x1-";
}
else if(dpiCheck==4){
res="220x220x1-";
}
String url = URL+res+news.getNews_photo();
Uri uri = Uri.parse(url);
Picasso.with(this.ctx).load(uri).into(holder.image);
}
#Override
public int getItemCount() {
return newsList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title,desc,date,views,comments,author;
ImageView image;
public MyViewHolder(View view) {
super(view);
title = (TextView)view.findViewById(R.id.news_title);
author = (TextView)view.findViewById(R.id.author);
desc =(TextView)view.findViewById(R.id.news_desc);
date=(TextView)view.findViewById(R.id.date);
views = (TextView)view.findViewById(R.id.view_counter);
comments = (TextView)view.findViewById(R.id.comment_counter);
image = (ImageView) view.findViewById(R.id.news_img);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String id="";
String cat="";
String brand="";
if(Build.VERSION.SDK_INT>=24){
id= newsList.get(getAdapterPosition()).getNews_id();
cat = newsList.get(getAdapterPosition()).getCat_id();
brand = newsList.get(getAdapterPosition()).getBrand_id();
}
else{
id= newsList.get(getPosition()).getNews_id();
cat = newsList.get(getPosition()).getCat_id();
brand = newsList.get(getPosition()).getBrand_id();
}
Intent intent = new Intent(view.getContext(), SingleNewsActivity.class);
intent.putExtra("NEWSID",id);
intent.putExtra("NEWSCAT",cat);
intent.putExtra("NEWSBRAND",brand);
ctx.startActivity(intent);
// Toast.makeText(view.getContext(), "position = " + id, Toast.LENGTH_SHORT).show();
}
});
}
}
public void setFilter(List<News> newList){
this.newsList = new ArrayList<>();
this.newsList.addAll(newList);
notifyDataSetChanged();
}
public void loadMore(List<News> newList){
this.newsList.addAll(newList);
notifyDataSetChanged();
}
}
The Error Statement OutOfMemory Error at NewsAdapter.onCreateViewHolder(NewsAdapter.java:49)
where the onCreateViewHolder is called.
Related
I have a list of array adapters that have the following layout which contains checkbox, textview increase, textview count, and textview decrease :
layout product adapter.
what the problem is how to call or implement clicklistener from ProdukActivity.java on each object that appears on the adapter. I just want to know how does it work with object in adapter so i can count the product price in every checkbox is checked.
Here is my adapter code :
public class ProductAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<ProductModel> productItems;
public ProductAdapter(Activity activity, List<ProductModel> productItems) {
this.activity = activity;
this.productItems = productItems;
}
#Override
public int getCount() {
return productItems.size();
}
#Override
public Object getItem(int location) {
return productItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_produk, null);
CheckBox namaProduk = (CheckBox) convertView.findViewById(R.id.checkBox_productName);
TextView kurangProduk = (TextView) convertView.findViewById(R.id.decrease_product);
TextView hitungProduk = (TextView) convertView.findViewById(R.id.count_product);
TextView tambahProduk = (TextView) convertView.findViewById(R.id.increase_product);
TextView hargaProduk = (TextView) convertView.findViewById(R.id.product_price);
ProductModel produk = productItems.get(position);
namaProduk.setText(produk.getProduct_name());
hargaProduk.setText(produk.getProduct_price());
return convertView;
}
}
and here is my ProdukActivity.java :
public class ProdukLaundry extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
ActionBar actionBar;
ListView listProduk;
SwipeRefreshLayout swipeProduct;
List<ProductModel> productList = new ArrayList<ProductModel>();
ProductAdapter productAdapter;
int success;
AlertDialog.Builder dialog;
RadioButton radioReguler, radioExpress;
TextView tvTotal;
Button next;
String product_id, laundry_id, product_name, product_price, service_type;
private int offset = 0;
private static final String TAG = ProdukLaundry.class.getSimpleName();
private static String url_select = Server.URL + "selectproduk.php";
public static final String TAG_PRODUCT_ID = "product_id";
public static final String TAG_LAUNDRY_ID = "laundry_id";
public static final String TAG_PRODUCT_NAME = "product_name";
public static final String TAG_PRODUCT_PRICE = "product_price";
public static final String TAG_SERVICE_TYPE = "service_type";
private static final String TAG_SUCCESS = "success";
private static final String TAG_MESSAGE = "message";
int countcheckBox = 0;
int totalCount = 0;
boolean regular = true;
boolean express = false;
boolean checkBox = false;
Transaction transaction;
String tag_json_obj = "json_obj_req";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_produk);
// menghubungkan variablel pada layout dan pada java
listProduk = (ListView)findViewById(R.id.list_produk);
swipeProduct = (SwipeRefreshLayout)findViewById(R.id.swipeProduct);
radioExpress = (RadioButton)findViewById(R.id.radio_express);
radioReguler = (RadioButton)findViewById(R.id.radio_regular);
tvTotal = (TextView)findViewById(R.id.total);
next = (Button)findViewById(R.id.button_next);
actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
laundry_id = getIntent().getStringExtra(TAG_LAUNDRY_ID);
// untuk mengisi data dari JSON ke dalam adapter
productAdapter = new ProductAdapter(ProdukLaundry.this, productList);
listProduk.setAdapter(productAdapter);
// menampilkan widget refresh
swipeProduct.setOnRefreshListener(this);
swipeProduct.post(new Runnable() {
#Override
public void run() {
swipeProduct.setRefreshing(true);
productList.clear();
productAdapter.notifyDataSetChanged();
callProduct();
}
}
);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onRefresh() {
productList.clear();
productAdapter.notifyDataSetChanged();
callProduct();
}
public void onClick(View view){
switch (view.getId()){
case R.id.increase_product:
countcheckBox++;
changeCheckBox();
hitung();
break;
case R.id.decrease_product:
if (countcheckBox>0){
countcheckBox--;
changeCheckBox();
hitung();
}
break;
case R.id.button_next:
save();
break;
default:
break;
}
}
public void onRadioButtonClicked(View view) {
boolean checked = ((RadioButton) view).isChecked();
switch(view.getId()) {
case R.id.radio_regular:
if (checked) {
regular = true;
express = false;
hitung();
}
break;
case R.id.radio_express:
if (checked){
regular = false;
express = true;
hitung();
}
break;
}
}
public void changeCheckBox(){
tvTotal.setText(countcheckBox+"");
}
public void hitung(){
int totalCount = 0;
int expressCost = 20000;
int harga = Integer.parseInt(product_price);
if (checkBox){
if (express){
totalCount+=(harga+expressCost)*countcheckBox;
}else{
totalCount+=harga*countcheckBox;
}
}
this.totalCount = totalCount;
tvTotal.setText(this.totalCount+"");
}
private void save() {
if (tvTotal.getText().toString().equals("0")){
Toast.makeText(this, "Choose Service.",
Toast.LENGTH_SHORT).show();
return;
}
String transId = "variabel transaksi id";
String uid = "variabel produk id";
String type;
if (regular) {
type = "regular";
} else {
type = "express";
}
transaction = new Transaction(transId, uid, type);
if (checkBox) {
transaction.setCheckBox(String.valueOf(countcheckBox));
}
transaction.total = String.valueOf(totalCount);
/*Intent intent = new Intent(this, LocationActivity.class);
intent.putExtra("transaction", transaction);
startActivity(intent);*/
}
Add listener for every object like below, inside getView of adapter. And inside the listener, do your handling
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_produk, null);
final CheckBox namaProduk = (CheckBox) convertView.findViewById(R.id.checkBox_productName);
TextView kurangProduk = (TextView) convertView.findViewById(R.id.decrease_product);
TextView hitungProduk = (TextView) convertView.findViewById(R.id.count_product);
TextView tambahProduk = (TextView) convertView.findViewById(R.id.increase_product);
TextView hargaProduk = (TextView) convertView.findViewById(R.id.product_price);
ProductModel produk = productItems.get(position);
namaProduk.setText(produk.getProduct_name());
hargaProduk.setText(produk.getProduct_price());
namaProduk.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
//check here
}
}
}
);
kurangProduk.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do your task here
}
}
);
hitungProduk.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do your task here
}
}
);
tambahProduk.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do your task here
}
}
);
hargaProduk.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do your task here
}
}
);
return convertView;
}
I'm trying to develop android application which can load images from the url in to RecyclerView With the help of Picasso library. But the problem comes that after some sequence "in my case after every 6 image" same image is duplicating in recyclerview. I'm added some code
#Override
public int getItemCount() {
return data.length;
}
#Override
public long getItemId(int position) {
return position;
}
in my adapter but this is not working for me.
Below is my currant adapter code please help me to findout the solution for this.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private Img[] data;
public MyAdapter(Context context, Img[] data) {
this.context = context;
this.data = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.image_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final Img user = data[position];
final String imageStr = user.getImgurl();
String taKey = loadTaluka();
final String id = user.getImgId().toString();
if (user.getTaluka().equals(taKey)) {
float date = Float.parseFloat(user.getDateTime());
float lastDayDate = Float.parseFloat(dispDate()) - 1;
if (date >= lastDayDate) {
Picasso.with(holder.myImg.getContext()).load(imageStr).placeholder(R.drawable.loading_1).networkPolicy(NetworkPolicy.OFFLINE).into(holder.myImg, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(holder.myImg.getContext()).load(imageStr).placeholder(R.drawable.loading_1).into(holder.myImg);
}
});
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, LoadImg.class);
intent.putExtra("url", imageStr);
intent.putExtra("id", id);
context.startActivity(intent);
}
});
}
}
#Override
public int getItemCount() {
return data.length;
}
#Override
public long getItemId(int position) {
return position;
}
/*
#Override
public int getItemViewType(int position) {
return position;
}*/
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView userTitle;
TextView age;
TextView country;
TextView url;
public ImageView myImg;
public MyViewHolder(View itemView) {
super(itemView);
myImg = (ImageView) itemView.findViewById(R.id.postImg);
}
}
//Extras
private String loadTaluka() {
SharedPreferences sf = context.getSharedPreferences("Taluka", MODE_PRIVATE);
return sf.getString("taluka", "a");
}
//Image Viewholder Adapter End
private String dispDate() {
Date c = Calendar.getInstance().getTime();
#SuppressLint("SimpleDateFormat") SimpleDateFormat day = new SimpleDateFormat("dd");
String dayFinal = day.format(c);
#SuppressLint("SimpleDateFormat") SimpleDateFormat month = new SimpleDateFormat("MM");
String monthFinal = month.format(c);
#SuppressLint("SimpleDateFormat") SimpleDateFormat year = new SimpleDateFormat("yyyy");
String yearFinal = year.format(c);
#SuppressLint("SimpleDateFormat") SimpleDateFormat hour = new SimpleDateFormat("HH");
String hourFinal = hour.format(c);
String finalDate = Integer.toString(Integer.parseInt(dayFinal) + Integer.parseInt(monthFinal) + Integer.parseInt(yearFinal)) + "." + hourFinal;
return finalDate;
}
}
-Thankyou.
Because of Recycler views RAM Management, the recycler view try to load cards from the cache and because of your recycler view's cache, the items loads incorrectly.
for preventing this you must add an else to your if like this:
if (date >= lastDayDate)
{
//Do Your Code
}
else
{
//The Default Item View Settings Here...
}
I have an issue in RecycleView. My screen has two tabs, both tabs contain recycleview.It call normally most of the time but sometimes give empty screen. Just I wrote log & system.out and found this issue. I will paste my adapter class code here.
public class ExpandableListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int HEADER = 0;
public static final int CHILD = 1;
List<ContentTitle> titles;
Context context;
private List<Item> titleData = new ArrayList<Item>();
public ExpandableListAdapter(List<Item> data) {
this.titleData = data;
System.out.println("===this.titleData===" + this.titleData.size());
}
public void replaceContentFragment(String title,int id,int bookmarked) {
try {
SkillsApp SkillsApp = (SkillsApp) context.getApplicationContext();
Fragment fragment = new ContentActivityFragment();
FragmentManager fragmentManager = skillsUSAApp.mainActivity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
SkillsApp.subtitleID = id;
SkillsApp.isbookmark = (bookmarked == 0)? false:true;
SkillsApp.mainActivity.getSupportActionBar().setTitle(title);
SkillsApp.selectedSubtitleID = id;
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) {
View view = null;
try{
context = parent.getContext();
final SkillsApp skillsApp = (SkillsAApp)context.getApplicationContext();
if(!skillsApp.isDrawer){
switch (type) {
case HEADER:
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.main_title, parent, false);
ListHeaderViewHolder header = new ListHeaderViewHolder(view);
return header;
case CHILD:
LayoutInflater inflater1 = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater1.inflate(R.layout.sub_title, parent, false);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("Child", "child");
TextView text = (TextView) view.findViewById(R.id.header_title);
}
});
return new RecyclerView.ViewHolder(view) {
};
}
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try{
System.out.println("==========##########");
final Item item = titleData.get(position);
final SkillsAApp skillsAApp = (SkillsAApp)context.getApplicationContext();
System.out.println("===onBindViewHolder item===" + item.mainTitle.title);
switch (item.type) {
case HEADER:
final ListHeaderViewHolder itemController = (ListHeaderViewHolder) holder;
itemController.refferalItem = item;
itemController.header_title.setText(item.mainTitle.title);
if (item.invisibleChildren == null) {
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
} else {
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
}
itemController.layoutItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
if(!skillsAApp.isDrawer){
if (item.invisibleChildren == null) {
item.invisibleChildren = new ArrayList<Item>();
int count = 0;
int pos = titleData.indexOf(itemController.refferalItem);
while (titleData.size() > pos + 1 && titleData.get(pos + 1).type == CHILD) {
item.invisibleChildren.add(titleData.remove(pos + 1));
count++;
}
notifyItemRangeRemoved(pos + 1, count);
notifyDataSetChanged();
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
} else {
int pos = titleData.indexOf(itemController.refferalItem);
int index = pos + 1;
for (Item i : item.invisibleChildren) {
titleData.add(index, i);
index++;
}
notifyItemRangeInserted(pos + 1, index - pos - 1);
notifyDataSetChanged();
itemController.btn_expand_toggle.setImageResource(R.drawable.down_arrow);
item.invisibleChildren = null;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
});
break;
case CHILD:
View itemTextView = (View) holder.itemView;
TextView view = (TextView) itemTextView.findViewById(R.id.header_title);
view.setText(titleData.get(position).subtitle.title);
final int pos = position;
itemTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try{
if(!skillsUSAApp.isDrawer){
TextView text = (TextView) view.findViewById(R.id.header_title);
FlurryAgent.logEvent("Sub Category Item");
replaceContentFragment(text.getText().toString(), titleData.get(pos).subtitle.subtitleId, titleData.get(pos).subtitle.bookMarked);
}
}catch (Exception e){
e.printStackTrace();
}
}
});
break;
}
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public int getItemViewType(int position) {
return titleData.get(position).type;
}
#Override
public int getItemCount() {
return titleData.size();
}
#Override
public long getItemId(int position) {
return position;
}
private static class ListHeaderViewHolder extends RecyclerView.ViewHolder {
public TextView header_title;
public ImageView btn_expand_toggle;
public Item refferalItem;
public RelativeLayout layoutItem;
public ListHeaderViewHolder(View itemView) {
super(itemView);
try{
header_title = (TextView) itemView.findViewById(R.id.header_title);
btn_expand_toggle = (ImageView) itemView.findViewById(R.id.btn_expand_toggle);
layoutItem = (RelativeLayout) itemView.findViewById(R.id.ll_title);
}catch (Exception e){
e.printStackTrace();
}
}
}
public static class Item {
public int type;
public String text;
public ContentTitle mainTitle;
public ContentSubTitle subtitle;
public List<Item> invisibleChildren;
public Item(int type, String text, List<Item> children) {
this.type = type;
this.text = text;
this.invisibleChildren = children;
}
public Item(int type, ContentTitle title,ContentSubTitle stitle) {
this.type = type;
this.mainTitle = title;
this.subtitle=stitle;
}
public Item(int type, String text) {
this.type = type;
this.text = text;
}
}
}
Here is a calling adapter from tab fragment
recyclerview = (RecyclerView) v.findViewById(R.id.recyclerview);
recyclerview.setLayoutManager(new LinearLayoutManager(v.getContext(), LinearLayoutManager.VERTICAL, false));
// recyclerview.setLayoutManager(new LinearLayoutManager(v.getContext()));
ExpandableListAdapter adapter = new ExpandableListAdapter(items);
recyclerview.setAdapter(adapter);
adapter.notifyDataSetChanged();
could you please advice me what is an issue? I didn't get any console error message.Could you please help me anyone here
I want to populate a ListView with different layouts for odd and even rows. It should look like this:
I use two objects "OddListItem" and "EvenListItem" to store/access the data. I do not know how to pass both objects to my custom listview adapter and get the correct view.
My object classes:
public class OddListItem {
private String time_start;
private String time_end;
private String location;
public OddListItem(String time_start, String time_end, String location) {
super();
this.time_start = time_start;
this.time_end = time_end;
this.location = location;
}
// getters and setters
void setTimeStart(String time_start) {
this.time_start = time_start;
}
void setTimeEnd(String time_end) {
this.time_end = time_end;
}
void setLocation(String location) {
this.location = location;
}
public String getTimeStart() {
return time_start;
}
public String getTimeEnd() {
return time_end;
}
public String getLocation() {
return location;
}
}
public class EvenListItem {
private String image;
private String location;
public EvenListItem (String image, String location) {
super();
this.image = image;
this.location = location;
}
// getters and setters
void setImage(String image) {
this.image = image;
}
void setLocation(String location) {
this.location = location;
}
public String getImage() {
return image;
}
public String getLocation() {
return location;
}
}
MyCustomAdapter:
public class MyCustomAdapter extends BaseAdapter {
// Tag for Logging
private static final String TAG = "MyCustomAdapter";
int type;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<OddListItem> mData = new ArrayList<OddListItem>();
private LayoutInflater mInflater;
//private TreeSet mSeparatorsSet = new TreeSet();
private Context context;
public MyCustomAdapter(Context context) {
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
}
public void addItem(final OddListItem item) {
mData.add(item);
//The notification is not necessary since the items are not added dynamically
//notifyDataSetChanged();
}
public void addSeparatorItem(final OddListItem item) {
mData.add(item);
//The notification is not necessary since the items are not added dynamically
//notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
/*if ((position%2) == 0){
type = TYPE_ITEM;
} else {
type = TYPE_SEPARATOR;
}
return type;*/
return position%2;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public OddListItem getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
Log.d(TAG, "getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
//inflate the new layout
convertView = mInflater.inflate(R.layout.detail_list_row_odd, parent, false);
holder.tv_time_from = (TextView) convertView.findViewById(R.id.tv_time_from);
holder.tv_time_to = (TextView) convertView.findViewById(R.id.tv_time_to);
holder.tv_current_location_odd = (TextView) convertView.findViewById(R.id.tv_current_location_odd);
//fill the layout with values
/*holder.tv_time_from.setText("12:34");
holder.tv_time_to.setText("12:37");
holder.tv_current_location_odd.setText("Aktueller Standort");*/
holder.tv_time_from.setText(mData.get(position).getTimeStart());
holder.tv_time_to.setText(mData.get(position).getTimeEnd());
holder.tv_current_location_odd.setText(mData.get(position).getLocation());
break;
case TYPE_SEPARATOR:
//inflate the new layout
convertView = mInflater.inflate(R.layout.detail_list_row_even, parent, false);
holder.tv_current_location_even = (TextView) convertView.findViewById(R.id.tv_current_location_even);
holder.img_transport = (ImageView) convertView.findViewById(R.id.img_transport);
//fill the layout with values
holder.tv_current_location_even.setText("Hauptbahnhof");
holder.img_transport.setImageDrawable(context.getResources().getDrawable(R.drawable.rollator));
break;
default:
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private static class ViewHolder {
public TextView tv_time_from;
public TextView tv_time_to;
public TextView tv_current_location_odd;
public TextView tv_current_location_even;
public ImageView img_transport;
}
}
Here I generate the data and call the adapter:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_connection);
generateData();
//fill ListView with custom content from MyCustomAdapter class
mAdapter = new MyCustomAdapter(getApplicationContext());
for (int i = 1; i < odd_items.size(); i++) {
mAdapter.addItem(odd_items.get(i));
if (i % 1 == 0) {
mAdapter.addSeparatorItem(odd_items.get(i));
}
}
setListAdapter(mAdapter);
//set duration text
tv_duration = (TextView)findViewById(R.id.tv_duration);
tv_duration.setText("Dauer: 22 Minuten");
}
private void generateData() {
odd_items = new ArrayList<OddListItem>();
odd_items.add(new OddListItem("12:34", "", "Aktueller Standort"));
odd_items.add(new OddListItem("12:37", "12:37", "TUM"));
odd_items.add(new OddListItem("12:42", "12:42", "Hauptbahnhof Nord"));
odd_items.add(new OddListItem("12:48", "12:48", "Hauptbahnhof"));
even_items = new ArrayList<EvenListItem>();
even_items.add(new EvenListItem("R.drawable.rollator", "3 Minuten Fußweg"));
even_items.add(new EvenListItem("R.drawable.bus", "Richtung Hauptbahnhof Nord"));
even_items.add(new EvenListItem("R.drawable.rollator", "6 Minuten Fußweg"));
mData = new Data(odd_items, even_items);
}
Any help would be great. Maybe there is also a better approach then please let me know.
I would create a Single list of Items
public class Items {
private String time_start;
private String time_end;
private String location;
private int image;
private String locationeven;
private int oddoreven;
public String getTime_start() {
return time_start;
}
public void setTime_start(String time_start) {
this.time_start = time_start;
}
public String getTime_end() {
return time_end;
}
public void setTime_end(String time_end) {
this.time_end = time_end;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public String getLocationeven() {
return locationeven;
}
public void setLocationeven(String locationeven) {
this.locationeven = locationeven;
}
public int getOddoreven() {
return oddoreven;
}
public void setOddoreven(int oddoreven) {
this.oddoreven = oddoreven;
}
}
In onCreate of Activity call
generateData() ;
Then
ArrayList<Items> oddorevenlist = new ArrayList<Items>();
private void generateData() {
Items item1 = new Items();
item1.setTime_start("12:34");
item1.setTime_end("");
item1.setLocation("Aktueller Standort");
item1.setOddoreven(0);
oddorevenlist.add(item1);
Items item2 = new Items();
item2.setImage(R.drawable.ic_launcher);
item2.setLocationeven("3 Minuten Fußweg");
item2.setOddoreven(1);
oddorevenlist.add(item2);
Items item3 = new Items();
item3.setTime_start("12:37");
item3.setTime_end("12:37");
item3.setLocation("Tum");
item3.setOddoreven(0);
oddorevenlist.add(item3);
Items item4 = new Items();
item4.setImage(R.drawable.ic_launcher);
item4.setLocationeven("Richtung Hauptbahnhof Nord");
item4.setOddoreven(1);
oddorevenlist.add(item4);
Items item5 = new Items();
item5.setTime_start("12:42");
item5.setTime_end("12:42");
item5.setLocation("Hauptbahnhof Nord");
item5.setOddoreven(0);
oddorevenlist.add(item5);
Items item6 = new Items();
item6.setImage(R.drawable.ic_launcher);
item6.setLocationeven("R6 Minuten Fußweg");
item6.setOddoreven(1);
oddorevenlist.add(item6);
Items item7 = new Items();
item7.setTime_start("12:48");
item7.setTime_end("12:48");
item7.setLocation("HHauptbahnhof");
item7.setOddoreven(0);
oddorevenlist.add(item7);
MyCustomAdapter mAdapter = new MyCustomAdapter(this,oddorevenlist);
setListAdapter(mAdapter);
}
Adapter code
public class MyCustomAdapter extends BaseAdapter {
// Tag for Logging
private static final String TAG = "MyCustomAdapter";
int type;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<Items> oddorevenlist ;
private LayoutInflater mInflater;
private Context context;
public MyCustomAdapter(Context context, ArrayList<Items> oddorevenlist) {
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
this.oddorevenlist = oddorevenlist;
}
#Override
public int getItemViewType(int position) {
if (oddorevenlist.get(position).getOddoreven()==0){
type = TYPE_ITEM;
} else if (oddorevenlist.get(position).getOddoreven()==1) {
type = TYPE_SEPARATOR;
}
return type;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return oddorevenlist.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
Log.d(TAG, "getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
//inflate the new layout
convertView = mInflater.inflate(R.layout.row_odd, parent, false);
holder.tv_time_from = (TextView) convertView.findViewById(R.id.tv_time_from);
holder.tv_time_to = (TextView) convertView.findViewById(R.id.tv_time_to);
holder.tv_current_location_odd = (TextView) convertView.findViewById(R.id.tv_current_location_odd);
holder.tv_time_from.setText(oddorevenlist.get(position).getTime_start());
holder.tv_time_to.setText(oddorevenlist.get(position).getTime_end());
holder.tv_current_location_odd.setText(oddorevenlist.get(position).getLocation());
break;
case TYPE_SEPARATOR:
//inflate the new layout
convertView = mInflater.inflate(R.layout.row_even, parent, false);
holder.tv_current_location_even = (TextView) convertView.findViewById(R.id.tv_current_location_even);
holder.img_transport = (ImageView) convertView.findViewById(R.id.img_transport);
//fill the layout with values
holder.tv_current_location_even.setText(oddorevenlist.get(position).getLocationeven());
holder.img_transport.setImageResource(R.drawable.ic_launcher);
break;
default:
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private static class ViewHolder {
public TextView tv_time_from;
public TextView tv_time_to;
public TextView tv_current_location_odd;
public TextView tv_current_location_even;
public ImageView img_transport;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
}
Snap
My List View is like this (4 TextViews in every Row):
When i clicked B1 and D3 they turned grey (that's fine !).
But when I scrolled I found two other TextViews that turned gray too although I didn't click them.
My custom Adapter is:
public class MyAdapter extends BaseAdapter {
private Context cont;
private int count;
public MyAdapter (Context c, int numberOfRow) {
this.cont = c;
this.count = numberOfRow;
}
#Override
public int getCount() {
return count;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#SuppressLint("NewApi")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) cont.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.single_row, null);
ViewHolder hold = new ViewHolder();
hold.tv1 = (TextView) v.findViewById(R.id.radio1);
hold.tv2 = (TextView) v.findViewById(R.id.radio2);
hold.tv3 = (TextView) v.findViewById(R.id.radio3);
hold.tv4 = (TextView) v.findViewById(R.id.radio4);
v.setTag(hold);
}
final ViewHolder holder = (ViewHolder) v.getTag();
holder.tv1.setText("A " + position);
holder.tv2.setText("B " + position);
holder.tv3.setText("C " + position);
holder.tv4.setText("D " + position);
OnClickListener ocl = new OnClickListener() {
#Override
public void onClick(View v) {
//Transparent background
Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);
//Grey background
Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);
//Set Transparent background to all
holder.tv1.setBackground(dr1);
holder.tv2.setBackground(dr1);
holder.tv3.setBackground(dr1);
holder.tv4.setBackground(dr1);
//Set Grey background only to the TextView which is clicked
switch (v.getId()) {
case R.id.radio1:
holder.tv1.setBackground(dr2);
break;
case R.id.radio2:
holder.tv2.setBackground(dr2);
break;
case R.id.radio3:
holder.tv3.setBackground(dr2);
break;
case R.id.radio4:
holder.tv4.setBackground(dr2);
break;
}
}
};
holder.tv1.setOnClickListener(ocl);
holder.tv2.setOnClickListener(ocl);
holder.tv3.setOnClickListener(ocl);
holder.tv4.setOnClickListener(ocl);
return v;
}
static class ViewHolder {
public TextView tv1;
public TextView tv2;
public TextView tv3;
public TextView tv4;
}
}
Please do let me know if other code is needed.
EDIT: The final solution:
Adapter Class
public class MyAdapter extends BaseAdapter {
static class ViewHolder {
public TextView tv1;
public TextView tv2;
public TextView tv3;
public TextView tv4;
}
private Context cont;
private int count;
private Problem[] problem;
public MyAdapter (Context c, Problem[] pr) {
this.cont = c;
this.problem = pr;
this.count = pr.length;
}
#Override
public int getCount() {
return count;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#SuppressLint("NewApi")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) cont.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.single_row, null);
holder = new ViewHolder();
holder.tv1 = (TextView) v.findViewById(R.id.radio1);
holder.tv2 = (TextView) v.findViewById(R.id.radio2);
holder.tv3 = (TextView) v.findViewById(R.id.radio3);
holder.tv4 = (TextView) v.findViewById(R.id.radio4);
final int POS = position;
OnClickListener ocl = new OnClickListener() {
#Override
public void onClick(View v) {
TextView tv = (TextView) v;
Problem prb = (Problem) tv.getTag();
Log.d("onClick", String.valueOf(prb.getPos()));
Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);
Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);
holder.tv1.setBackground(dr1);
holder.tv2.setBackground(dr1);
holder.tv3.setBackground(dr1);
holder.tv4.setBackground(dr1);
switch (v.getId()) {
case R.id.radio1:
prb.setClicked(1);
holder.tv1.setBackground(dr2);
break;
case R.id.radio2:
prb.setClicked(2);
holder.tv2.setBackground(dr2);
break;
case R.id.radio3:
prb.setClicked(3);
holder.tv3.setBackground(dr2);
break;
case R.id.radio4:
prb.setClicked(4);
holder.tv4.setBackground(dr2);
break;
}
Log.d("onClick", String.valueOf(prb.getClicked()));
}
};
holder.tv1.setOnClickListener(ocl);
holder.tv2.setOnClickListener(ocl);
holder.tv3.setOnClickListener(ocl);
holder.tv4.setOnClickListener(ocl);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);
Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);
Problem pal = problem[position];
holder.tv1.setText(pal.getA());
holder.tv2.setText(pal.getB());
holder.tv3.setText(pal.getC());
holder.tv4.setText(pal.getD());
holder.tv1.setBackground(dr1);
holder.tv2.setBackground(dr1);
holder.tv3.setBackground(dr1);
holder.tv4.setBackground(dr1);
Log.d("log", "pos = " + position + " clicked = " + pal.getClicked());
switch (pal.getClicked()) {
case 1:
holder.tv1.setBackground(dr2);
break;
case 2:
holder.tv2.setBackground(dr2);
break;
case 3:
holder.tv3.setBackground(dr2);
break;
case 4:
holder.tv4.setBackground(dr2);
break;
default:
break;
}
holder.tv1.setTag(pal);
holder.tv2.setTag(pal);
holder.tv3.setTag(pal);
holder.tv4.setTag(pal);
return v;
}
}
Problem Class :
public class Problem {
private String A;
private String B;
private String C;
private String D;
private int pos;
private int clicked;
public Problem(int n) {
this.pos = n;
this.A = "A " + n;
this.B = "B " + n;
this.C = "C " + n;
this.D = "D " + n;
this.clicked = -1;
}
public int getClicked() {
return clicked;
}
public void setClicked(int clicked) {
this.clicked = clicked;
}
public String getA() {
return A;
}
public void setA(String a) {
A = a;
}
public String getB() {
return B;
}
public void setB(String b) {
B = b;
}
public String getC() {
return C;
}
public void setC(String c) {
C = c;
}
public String getD() {
return D;
}
public void setD(String d) {
D = d;
}
public int getPos() {
return pos;
}
public void setPos(int pos) {
this.pos = pos;
}
}
This happens due to recycling of the views ! Tagging should solve your problem. This is a very common problem, have a look at :
http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html
listview checkbox trouble in android
ListView Checkbox problem in CustomAdapter
http://lalit3686.blogspot.in/2012/06/today-i-am-going-to-show-how-to-deal.html
Hope this helps !
You will need one variable to keep track of the TextView which is to be highlighted within a list item.
You can add that variable to either your Holder object or use something like a SparseIntArray to store the position as key and 0, 1, 2, 3, 4 as values to identify which TextView is selected. 0 means no selection. Initially your variable or entry in SparseIntArray for that position will be 0.
Next, in the getView() lookup the value for position as key in SparseIntArray and based on that set the background of the TextView to mark selection, if any.
This way when you scroll the ListView, it will only show selections for List Items which you select and not for others.