0

I'm using Realm in my mobile application to store line items for my list view. I'm extending the RealmBaseAdapter which is working fine. Problem is that if I make a query to the database to filter my items, my adapter is not picking up the changed list and causing the out of bound index error.

This is where I set my adapter with the initial values,

results = realm.where(BillingLineItem.class).findAll();   
adapter = new BillingListAdapter(getActivity(), results);

And this is the part that I'm doing the filtering based on the spec number,

results = realm.where(BillingLineItem.class)
            .equalTo("SpecNumber", spec)
            .findAll();
adapter.notifyDataSetChanged();

And like I said before After that query results will be updated but adapter doesn't pick up the changes.

EDIT: My adapter for the list view

public class BillingListAdapter extends RealmBaseAdapter<BillingLineItem> {

private LayoutInflater inflater = null;

private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
private boolean isActionMode;

public BillingListAdapter(Context mContext, RealmResults<BillingLineItem> lineItems) {
    super(mContext,lineItems);
    inflater = (LayoutInflater) mContext.
            getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.isActionMode = false;
}
// I commented out this part because RealmBaseAdapter automaticly implements this methods in the super class
/*@Override
public int getCount() {
    return lineItems.size();
}

@Override
public Object getItem(int position) {
    return lineItems.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}*/

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View vi = convertView;
    ViewHolder holder;

    if (convertView == null) {

        /****** Inflate billing_foreground_item.xml file for each row ( Defined below ) *******/
        vi = inflater.inflate(R.layout.billing_foreground_item, null);

        /****** View Holder Object to contain billing_foreground_item.xml file elements ******/

        holder = new ViewHolder();
        holder.SubOper = (TextView) vi.findViewById(R.id.tvSubOper);
        holder.Spec = (TextView) vi.findViewById(R.id.tvSpec);
        holder.Address = (TextView) vi.findViewById(R.id.tvAddress);
        holder.SKU = (TextView) vi.findViewById(R.id.tvSku);
        holder.SKUDesc = (TextView) vi.findViewById(R.id.tvSkuDesc);
        holder.Quantity = (TextView) vi.findViewById(R.id.tvQuantity);
        holder.Unit = (TextView) vi.findViewById(R.id.tvUnit);
        holder.BilledQty = (TextView) vi.findViewById(R.id.tvBBilledQty);
        holder.RemainingQty = (TextView) vi.findViewById(R.id.tvRemainingQty);
        holder.ivLineIcon = (ImageView) vi.findViewById(R.id.ivLineIcon);
        holder.rlItem = (RelativeLayout) vi.findViewById(R.id.rlItem);
        holder.ErrorMessage = (TextView) vi.findViewById(R.id.txtErrorDisplay);
        /************  Set holder with LayoutInflater ************/
        vi.setTag(holder);
    } else {
        holder = (ViewHolder) vi.getTag();
    }

    /************  Set Model values in Holder elements ***********/
    if (adapterData.get(position).getFinalFlag()) {
        holder.ivLineIcon.setImageResource(R.drawable.finalflagblue);

        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 255));

        if (adapterData.get(position).getCompleted()) {
            holder.rlItem.setBackgroundColor(Color.rgb(223, 235, 245));
        }
        if (adapterData.get(position).getErrorFlag()){
            holder.rlItem.setBackgroundColor(Color.rgb(231, 25, 57));
            holder.ErrorMessage.setVisibility(View.VISIBLE);
            holder.ErrorMessage.setText(adapterData.get(position).getErrorMessage());
        }

    } else if (adapterData.get(position).getDeleteFlag()) {
        holder.ivLineIcon.setImageResource(R.drawable.trashiconred);

        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 255));
        if (adapterData.get(position).getErrorFlag()){
            holder.rlItem.setBackgroundColor(Color.rgb(231, 25, 57));
            holder.ErrorMessage.setVisibility(View.VISIBLE);
            holder.ErrorMessage.setText(adapterData.get(position).getErrorMessage());
        }
    } else if (adapterData.get(position).getChanged()) {
        holder.ivLineIcon.setImageResource(R.drawable.changedicongreen);

        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 255));
        if (adapterData.get(position).getErrorFlag()){
            holder.rlItem.setBackgroundColor(Color.rgb(231, 25, 57));
            holder.ErrorMessage.setVisibility(View.VISIBLE);
            holder.ErrorMessage.setText(adapterData.get(position).getErrorMessage());
        }
    } else if (adapterData.get(position).getNewLine()) {
        holder.ivLineIcon.setImageResource(R.drawable.newlineicon);

        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 255));

        if (adapterData.get(position).getErrorFlag()){
            holder.rlItem.setBackgroundColor(Color.rgb(231, 25, 57));
            holder.ErrorMessage.setVisibility(View.VISIBLE);
            holder.ErrorMessage.setText(adapterData.get(position).getErrorMessage());
        }
    } else {
        holder.ivLineIcon.setImageResource(R.drawable.linesiconblack);

        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 255));
        holder.ErrorMessage.setVisibility(View.GONE);
    }

    if (mSelection.get(position) != null) {
        //Log.d(TAG, "Item Selected");
        holder.rlItem.setBackgroundColor(Color.rgb(255, 255, 192));// this is a selected position so make it hilighted
    }

    holder.SubOper.setText(adapterData.get(position).getSubOper());
    holder.Spec.setText(adapterData.get(position).getSpecNumber());
    holder.Address.setText(adapterData.get(position).getAddress());
    holder.SKU.setText(adapterData.get(position).getSKUNumber());
    holder.SKUDesc.setText(adapterData.get(position).getSKUDesc());
    holder.Quantity.setText(adapterData.get(position).getQuantity());
    holder.Unit.setText(adapterData.get(position).getUnit());
    holder.BilledQty.setText(adapterData.get(position).getBilledQty());
    holder.RemainingQty.setText(adapterData.get(position).getRemainingQty());

    return vi;
}


public void setNewSelection(int position, boolean value) {
    mSelection.put(position, value);
    notifyDataSetChanged();
}

public boolean isPositionChecked(int position) {
    Boolean result = mSelection.get(position);
    return result == null ? false : result;
}

public Set<Integer> getCurrentCheckedPosition() {
    return mSelection.keySet();
}

public void removeSelection(int position) {
    mSelection.remove(position);
    notifyDataSetChanged();
}

public void clearSelection() {
    mSelection = new HashMap<Integer, Boolean>();
    notifyDataSetChanged();
}

public void setActionMode(boolean isActionMode)
{
    this.isActionMode = isActionMode;
}

@Override
public boolean isEnabled(int position)
{
    final BillingLineItem item = (BillingLineItem) getItem(position);
    if (!item.getDeleteFlag().equals("true"))
    {
        //only enable items that are not inside the basket
        return true;
    }
    //all other items are disabled during actionmode
    return false;
}

public static class ViewHolder {
    public TextView SubOper;
    public TextView Spec;
    public TextView Address;
    public TextView SKU;
    public TextView SKUDesc;
    public TextView Quantity;
    public TextView Unit;
    public TextView BilledQty;
    public TextView RemainingQty;
    public ImageView ivLineIcon;
    public RelativeLayout rlItem;
    public TextView ErrorMessage;
}

}

Esat IBIS
  • 381
  • 1
  • 5
  • 19

1 Answers1

1

Some information to point out here:

Android is based on java thus it's variables are passed by reference value (More Info). It means that if you have an object:

RealmResults<BillingLineItem> results;

And you pass this variable as a parameter to the Adapter constructor:

adapter = new BillingListAdapter(getActivity(), results);

The list which you have outside the adapter and the variable inside the adapter are actually the same objects (two variables pointing to the same reference).

After you make your second query:

results = realm.where(BillingLineItem.class)
            .equalTo("SpecNumber", spec)
            .findAll();

You are making a new reference and storing it in the result object thus the list outside the adapter and the list which you passed earlier to the adapter are literally different objects so the adapter will not be able to sense the change and you get the error. You can fix it like this:

results.clear();
//adapter.notifyDataSetChanged() if you want to show the change before data fetched...
results.addAll(realm.where(BillingLineItem.class)
            .equalTo("SpecNumber", spec)
            .findAll());
adapter.notifyDataSetChanged();
Community
  • 1
  • 1
Saeed Entezari
  • 3,685
  • 2
  • 19
  • 40
  • `clear()` and `addAll()` functions are deprecated in RealmResults and I couldn't find some other method to replace that functions. I was aware of that reference problem I just couldn't find a way to work around with it. – Esat IBIS Jul 25 '16 at 16:06
  • @EsatIBIS just use RealmList then. add the results to the list and use that list instead. https://github.com/realm/realm-java/blob/master/realm/realm-library/src/main/java/io/realm/RealmList.java – Saeed Entezari Jul 25 '16 at 16:13
  • The thing is though if I change to RealmList, I can't do the changes to the items that I'm doing right now. In that case I need to have 2 lists , one will be the RealmResults for data changes and RealmList for the display purposes. I thinks it's not efficient way to do things. – Esat IBIS Jul 25 '16 at 16:27
  • @EsatIBIS In the RealmResults Class there is a method where()... Can you use that method to reuse your list and change the query on the result? Instead of making new query? – Saeed Entezari Jul 25 '16 at 16:41
  • The where method still creates a new RealmResults object and returns that, You can see it in the documentation here https://realm.io/docs/java/1.1.0/api/io/realm/RealmResults.html – Esat IBIS Jul 25 '16 at 16:47
  • @EsatIBIS Have a look at: https://github.com/realm/realm-android-adapters/blob/master/adapters/src/main/java/io/realm/RealmBaseAdapter.java#L142 – Saeed Entezari Jul 25 '16 at 16:58
  • 1
    `updateData(results)` worked thanks for your help :) – Esat IBIS Jul 25 '16 at 17:07