What is the best trick to handle null values in Recycler-view onBindViewHolder?


What is the best trick to handle null values in Recycler-view onBindViewHolder?



I handled many exception regarding null/index-outof-bound etc. But i am thinking that this is not right way to go like if/else , so anyone can guide me How to handle all null condition in onBindViewHolder?


@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
if (holder instanceof CustDtlsHolder)
{

// >i am getting here lots of null values below


if(position < arr_custdetails.size())
{
String dateInString = arr_custdetails.get(position).getLastVisitDate();
Date date = null;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
date = formatter.parse(dateInString);
SimpleDateFormat formatter2 = new SimpleDateFormat("dd/MMM/yyyy");
update_date = formatter2.format(date);
update_date = update_date.replace("/"," ");
} catch (ParseException e) {
e.printStackTrace();
} catch (NullPointerException e){
update_date="null";
}

//> same getting null values below as mention above.

((CustDtlsHolder) holder).txt_mbr_date.setText(update_date.substring(0,2));
((CustDtlsHolder) holder).txt_mbr_year.setText(update_date.substring(3,6)+ " "+update_date.substring(7,11));
((CustDtlsHolder) holder).txt_mbr_name.setText(arr_custdetails.get(position).getFullName());
((CustDtlsHolder) holder).txt_mbr_email.setText(arr_custdetails.get(position).getEmailAddress());
((CustDtlsHolder) holder).txt_mbr_phone.setText(arr_custdetails.get(position).getMobileNumber());
((CustDtlsHolder) holder).txt_mbr_avgSize_val.setText(""+Math.round(arr_custdetails.get(position).getAvgBasketVal())+" , "+Math.round(arr_custdetails.get(position).getAvgBasketQty())+" "+"Units");
if(arr_custdetails.get(position).getLast90dayVisit() == null || arr_custdetails.get(position).getLast90dayVisit().equals(""))
{
((CustDtlsHolder) holder).txt_mbr_avgVisits_val.setText("");
}
else
{
((CustDtlsHolder) holder).txt_mbr_avgVisits_val.setText(arr_custdetails.get(position).getLast90dayVisit()+ " in Last 90 days");
}
((CustDtlsHolder) holder).txt_mbr_noofvisit.setText(arr_custdetails.get(position).getMbrVisitCount());

}
}





make one common method in Util class and pass the value of the your variable like Util.checkNull(arr_custdetails.get(position).getFullName()); it will return flag true or false if it return true then set default value for your holder item otherwise set whatever you get from the string.
– Dilip
Dec 27 '17 at 10:27





You can add function inside your ViewHolder and call it bind(), then you can manipulate your codes there and it will make your code clean.
– Lester L.
Dec 27 '17 at 10:31




4 Answers
4



you can use this way also it will be helpful for you...please try this.



model:


public class YourModelName{

private String mobileNumber="";
private String fullName="";
private String emailAddress="";
private String avgBasketVal="";
private String avgBasketQty="";
private String last90dayVisit="";

public String getMobileNumber() {
return mobileNumber;
}

public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}

public String getFullName() {
return fullName;
}

public void setFullName(String fullName) {
this.fullName = fullName;
}

public String getEmailAddress() {
return emailAddress;
}

public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}

public String getAvgBasketVal() {
return avgBasketVal;
}

public void setAvgBasketVal(String avgBasketVal) {
this.avgBasketVal = avgBasketVal;
}

public String getAvgBasketQty() {
return avgBasketQty;
}

public void setAvgBasketQty(String avgBasketQty) {
this.avgBasketQty = avgBasketQty;
}

public String getLast90dayVisit() {
return last90dayVisit;
}

public void setLast90dayVisit(String last90dayVisit) {
this.last90dayVisit = last90dayVisit;
}

}





I think this is not proper. Add null check in your setter method.
– Mitesh Vanaliya
Dec 27 '17 at 10:49





This is alternative option I have posted one more I already suggested to him in comment he can choose whatever he feel suitable.
– Dilip
Dec 27 '17 at 10:57



Edit @dilip answer:


public class YourModelName{

private String mobileNumber="";
private String fullName="";
private String emailAddress="";
private String avgBasketVal="";
private String avgBasketQty="";
private String last90dayVisit="";

public String getMobileNumber() {
return mobileNumber;
}

public void setMobileNumber(String mobileNumber) {
if(mobileNumber != null)
this.mobileNumber = mobileNumber;
}

public String getFullName() {
return fullName;
}

public void setFullName(String fullName) {
if(fullName != null)
this.fullName = fullName;
}

public String getEmailAddress() {
return emailAddress;
}

public void setEmailAddress(String emailAddress) {
if(emailAddress != null)
this.emailAddress = emailAddress;
}

public String getAvgBasketVal() {
return avgBasketVal;
}

public void setAvgBasketVal(String avgBasketVal) {
if(avgBasketVal != null)
this.avgBasketVal = avgBasketVal;
}

public String getAvgBasketQty() {
return avgBasketQty;
}

public void setAvgBasketQty(String avgBasketQty) {
if(avgBasketQty != null)
this.avgBasketQty = avgBasketQty;
}

public String getLast90dayVisit() {
return last90dayVisit;
}

public void setLast90dayVisit(String last90dayVisit) {
if(last90dayVisit != null)
this.last90dayVisit = last90dayVisit;
}

}



If your string value is null then return "".



Hope this may help you.





can i check multiple exception using this.
– chari sharma
Dec 27 '17 at 11:26





@charisharma you can change setter method what you want. like in array setter method you can check size.
– Mitesh Vanaliya
Dec 27 '17 at 11:32






actually i am using gson so i dont need to set data , i am using only get method.
– chari sharma
Dec 27 '17 at 11:39





As per your answer i have tried in get method also its working fine but one is disadvantage : if i want to check null than i have to place all condition in get method so it may be increase your model size , i am looking less code to handle this situation.
– chari sharma
Dec 27 '17 at 11:42





Just add a condition in setter method. When gson convert json to pojo then setter method execute
– Mitesh Vanaliya
Dec 27 '17 at 11:43



For string values you can use android's TextUtils, and fyi you can even set null in textView.setText() method:


CustDtlsHolder custDtlsHolder = ((CustDtlsHolder) holder);
String value = arr_custdetails.get(position).getLast90dayVisit();
if (!TextUtils.isEmpty(value) {
value += " in Last 90 days";
}
custDtlsHolder.txt_mbr_avgVisits_val.setText(value);



But as has been written, you should better create bind method for clearer code. Usually in Java projects I use ButterKnife and create some base classes like that.



BaseRecyclerAdapter:


public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {

private List<T> items;
private OnRecyclerItemClickListener<T> onRecyclerItemClickListener;

public BaseRecyclerAdapter(List<T> items) {
this.items = items;
}

@Override public void onBindViewHolder(BaseViewHolder holder, int position) {
T item = getItem(position);
holder.bind(item);
holder.itemView.setOnClickListener(v -> {
if (onRecyclerItemClickListener != null) {
onRecyclerItemClickListener.onItemClick(this, item);
}
});
}

protected final View getViewHolderView(ViewGroup parent, @LayoutRes int itemLayoutId) {
return LayoutInflater.from(parent.getContext()).inflate(itemLayoutId, parent, false);
}
// ... other base methods such as getItemCount(), setItems, etc.



BaseViewHolder:


public abstract class BaseViewHolder<T> extends RecyclerView.ViewHolder {

protected abstract void bind(T item);

public BaseViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}

public final Context getContext() {
return itemView.getContext();
}



And usage:


final class MyAdapter extends BaseRecyclerAdapter<MyItem> {
MyAdapter(List<MyItem> items) { super(items); }

@Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyViewHolder(getViewHolderView(parent, R.layout.item));
}

class MyViewHolder extends BaseViewHolder<MyItem> {
@BindView(R.id.txt_date) TextView txtDate;

MyViewHolder(View itemView) { super(itemView); }

@Override protected void bind(MyItem item) {
txtDate.setText(getContext().getString(R.string.item_created, DateTimeUtils.formatDate(item.date)));
// put your null checking here
}
}



Above answer which modifies the Model class didn't work for me.



This is what I came up with


@Override
public void onBindViewHolder(HomeViewHolder holder, int position)
{


String title;

try {

title = myList.get(position).getTitle();

} catch (NullPointerException e) {

title = "Null";

}

holder.tvTitle.setText(title);

}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask

NSwag: Generate C# Client from multiple Versions of an API