0

when using Normal string array as data source for gridview just direct modification of array and calling notifydatachange is working but when data is custom adapter then gridview is not updating.
I know modifying current cell's textview is doable but I want to change two GridView when one cell's value is changed where two adapter has the same String object and according to huge comments in Is Java "pass-by-reference" or "pass-by-value"? object in java is passed via reference and both adapter should be changed but in my case none of them are changing.

Grid cell custom class

public class GridCell {
private static final String TAG = "GridCell";
private String cell_value;

public GridCell(String cell_value) {
    this.cell_value = cell_value;
}

public String getcell_value() {
    return cell_value;
}
public void setcell_value(String c) {
    this.cell_value = c;
}
}

Adapter code

public class GridCellAdapter extends ArrayAdapter<GridCell> {
public GridCellAdapter(Context context, int textViewId, ArrayList<GridCell> cells) {
    super(context, textViewId, cells);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Get the data item for this position
    GridCell cell = getItem(position);
    // Check if an existing view is being reused, otherwise inflate the view
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.gv_item_fixedline, parent, false);
        // following code is moved out of if block AFTER Ben's answer  below. so to avoid other user might suggest same solution
        //TextView tv = (TextView) convertView.findViewById(R.id.cellval);
        //tv.setText(cell.getcell_value());
    }
    TextView tv = (TextView) convertView.findViewById(R.id.cellval);
    tv.setText(cell.getcell_value());
// save the object so that this object can be modified by setOnItemClickListener

    convertView.setTag(cell);
    return convertView;
}

@Override
public int getCount() {
    return super.getCount();
}
}

Main activity

public class MainActivity extends AppCompatActivity {

GridView gridView1;
GridView gridView2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // init gridview

    // Construct the data source for GridView1
    ArrayList<GridCell> arrayOfCells1 = new ArrayList<GridCell>();
    // Create the adapter to convert the array to views
    final GridCellAdapter gcAdapter1 = new GridCellAdapter(this, R.layout.gv_item_fixedline, arrayOfCells1);
    gridView1 = (GridView) findViewById(R.id.gridView1);
    gridView1.setAdapter(gcAdapter1);


    // Construct the data source for GridView2
    ArrayList<GridCell> arrayOfCells2 = new ArrayList<GridCell>();
    // Create the adapter to convert the array to views
    final GridCellAdapter gcAdapter2 = new GridCellAdapter(this, R.layout.gv_item_fixedline, arrayOfCells2);
    gridView2 = (GridView) findViewById(R.id.gridView2);
    gridView2.setAdapter(gcAdapter2);

    for (int i = 1; i <= 3; i++) {
        // both adapter now has same object reference. am I right here?
        GridCell tmp = new GridCell("U");
        gcAdapter1.add(tmp);
        gcAdapter2.add(tmp);
    }


    gridView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // this object is shared by both adapter 
            GridCell cell = (GridCell) view.getTag();
            Log.d(TAG, "onItemClick: " + cell.getcell_value());
            cell.setcell_value("X");
            Log.d(TAG, "onItemClick: modified :" + cell.getcell_value());
            Toast.makeText(getApplicationContext(), Integer.toString(position), Toast.LENGTH_SHORT).show();
        }
    });

    gcAdapter1.notifyDataSetChanged();
    gcAdapter2.notifyDataSetChanged();

}


}
kiranking
  • 306
  • 11
  • 29
  • add your code about `setOnItemClickListener`,by the way,I guess your adapter's method `getCount` shouldn't be `super.getCount()` – aolphn Nov 03 '18 at 14:50
  • setOnItemClickListener is registered on gridview1 as I need to call notifyDataSetChanged on both gridview. As for super.getcount() I coded based on https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView 's Using a Custom ArrayAdapter method where User array is not declared as private variable inside Adapter class & I thought that is optional and just override with getCount with default definition. – kiranking Nov 03 '18 at 16:13
  • for time being used the solution at https://stackoverflow.com/a/20053133/538212 I think Ben's answer below should work but it doesn't. Is this a bug or something related to scope of GridView adapter (which is declared globally and accessible within MainActivity)? – kiranking Nov 15 '18 at 14:33

1 Answers1

0

In your getView() method, you have this code:

if (convertView == null) {
    convertView = LayoutInflater.from(getContext()).inflate(R.layout.gv_item_fixedline, parent, false);
    TextView tv = (TextView) convertView.findViewById(R.id.cellval);
    tv.setText(cell.getcell_value());
}

You should move the setText() call outside the if block:

if (convertView == null) {
    convertView = LayoutInflater.from(getContext()).inflate(R.layout.gv_item_fixedline, parent, false);
}

TextView tv = (TextView) convertView.findViewById(R.id.cellval);
tv.setText(cell.getcell_value());

Otherwise the text won't be updated when the data changes (assuming the view is recycled).

Note that calling findViewById() is somewhat expensive, which is why you are recommended to use the "view holder pattern", but you're already using the view tag for something else here.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • still gridview data not changing :(. But log show changed value for subsequent clicks that means `cell` object is sowehow modifiying but not reflecting the changes on any of the gridview. `findViewById()` might not be the problem because grid has limited cell like just less than seven cells and not even scroll is neccessary. – kiranking Nov 03 '18 at 16:31
  • also tried `gcAdapter1.getItem(position).setcell_value("Y");` inside `gridView1.setOnItemClickListener` but still gridview not updating BUT when I added same code outside just before `gcAdapter1.notifyDataSetChanged();` with position like `gcAdapter1.getItem(0).setcell_value("Y");` then gridiview1 is updating.(ie. onCreate of MainActivity without any click event trigger ). Is that mean whatever modification is made inside `setOnItemClickListener` has scope to that method? – kiranking Nov 05 '18 at 08:52