【问题标题】:Updating adapter data and notifydatachange on setOnItemClickListener在 setOnItemClickListener 上更新适配器数据和 notifydatachange
【发布时间】:2018-11-03 14:35:47
【问题描述】:

当使用普通字符串数组作为gridview的数据源时,只需直接修改数组并调用notifydatachange即可,但是当数据是自定义适配器时,gridview不会更新。
我知道修改当前单元格的 textview 是可行的,但是当一个单元格的值发生更改时,我想更改两个 GridView,其中两个适配器具有相同的 String 对象,并且根据 java 中 Is Java "pass-by-reference" or "pass-by-value"? 对象中的巨大 cmets 通过引用传递,并且两个适配器都应该是改变了,但就我而言,它们都没有改变。

网格单元自定义类

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;
}
}

适配器代码

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();
}
}

主要活动

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();

}


}

【问题讨论】:

  • 添加你关于setOnItemClickListener的代码,顺便说一下,我猜你的适配器的方法getCount不应该是super.getCount()
  • setOnItemClickListener 已在 gridview1 上注册,因为我需要在两个 gridview 上调用 notifyDataSetChanged。至于 super.getcount() 我基于 github.com/codepath/android_guides/wiki/… 的 Using a Custom ArrayAdapter 方法进行编码,其中 User 数组未在 Adapter 类中声明为私有变量,我认为这是可选的,只需用默认定义的 getCount 覆盖。跨度>
  • 暂时使用stackoverflow.com/a/20053133/538212 的解决方案我认为Ben 下面的回答应该有效,但它没有。这是一个错误还是与 GridView 适配器的范围相关(在 MainActivity 中全局声明并可访问)?

标签: android gridview onitemclicklistener


【解决方案1】:

在您的 getView() 方法中,您有以下代码:

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());
}

您应该将setText() 调用移到if 块之外:

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());

否则数据变化时文本不会更新(假设视图被回收)。

请注意,调用findViewById() 有点贵,这就是为什么建议您使用“视图持有者模式”,但您已经在此处将视图标签用于其他用途。

【讨论】:

  • 仍然 gridview 数据没有改变 :(。但是日志显示后续点击的更改值,这意味着 cell 对象正在修改但不反映任何 gridview 上的更改。findViewById() 可能不会问题是因为网格的单元格有限,例如少于七个单元格,甚至不需要滚动。
  • 也在gridView1.setOnItemClickListener 内部尝试了gcAdapter1.getItem(position).setcell_value("Y");,但是当我在gcAdapter1.notifyDataSetChanged(); 之前添加相同的代码时,gridview 仍然没有更新但是当我在gcAdapter1.getItem(0).setcell_value("Y"); 之前添加相同的代码时,gridiview1 正在更新。(即onCreate of MainActivity 没有任何点击事件触发)。这是否意味着在 setOnItemClickListener 内部进行的任何修改都适用于该方法?
猜你喜欢
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 2011-08-19
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多