notifyDataSetHasChanged() 在 RecyclerView 中的 TextWatcher.onTextChanged() 中使用时抛出错误
notifyDataSetHasChanged() throws an error when used inside TextWatcher.onTextChanged() inside a RecyclerView
我正在构建一个允许用户对数字进行实时基础转换的应用程序。用户在编辑文本中输入他们的号码,然后使用加号和减号按钮选择基数。到目前为止我遇到的问题是提供实时转换。 recycler 视图中的所有 editText 都将它们的文本设置为一个 BigInteger,可以根据它们的基数进行转换。
我的想法是在用户输入新数字时更新 BigInteger。因此,每次用户输入一个数字时,我应该能够更新 BigInteger,通知回收器视图数据已更改,然后编辑文本视图应自动更新。这是我的 ConvertViewHolder
public ConvertViewHolder(final View itemView) {
super(itemView);
mBaseTextView = (TextView) itemView.findViewById(R.id.baseLabel);
mEditText = (EditText) itemView.findViewById(R.id.numberEditText);
mMinusButton = (Button) itemView.findViewById(R.id.minusButton);
mPlusButton = (Button) itemView.findViewById(R.id.plusButton);
mRemoveButton = (ImageButton)itemView.findViewById(R.id.removeButton);
mMinusButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRoot.get(getPosition()) > MIN_BASE) {
mRoot.set(getPosition(), (mRoot.get(getPosition()) - 1));
notifyDataSetChanged();
}
}
});
mPlusButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRoot.get(getPosition()) < MAX_BASE){
mRoot.set(getPosition(), (mRoot.get( getPosition() ) +1));
notifyDataSetChanged();
}
}
});
mRemoveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRoot.remove(getPosition());
notifyDataSetChanged();
}
});
mEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if(editable.toString().length() > 0) {
// change Big Integer
mNumber.setDecimalNumber(editable.toString(), mRoot.get( getPosition() ) );
// notify change
notifyDataSetChanged();
}
}
});
// TODO: convert numbers at the same time
}
public void bindConverter(final int root){
mBaseTextView.setText(String.format("%02d", root));
// String containing all the allowed digits depending on base
String digits = mNumber.getScaleFromBase(root);
if (root < 11) {
// filter input
mEditText.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_TEXT_FLAG_MULTI_LINE);
mEditText.setKeyListener(DigitsKeyListener.getInstance(digits));
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
} else {
mEditText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
// TODO: filter input for base higher than 10
}
// set editText to BigInteger displaying it in the correct base
// i.e. if the BigInteger is "8" it will be displayed as 8 if the base is 10
// and as 1000 if the base is 2
mEditText.setText(mNumber.getDecimalNumber(mRoot.get( getPosition() )));
}
}
但显然我不允许在 TextWatcher.onTextChanged() 中调用 notifySetDataHasChanged,因为编译器会向我抛出此错误:
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
这是不言自明的,但不幸的是我还没有找到可能的解决方法。
view.post(
new Runnable() {
public void run() { notifyDatasetChanged(); };
}
);
不言自明:
在 RecyclerView 计算布局或滚动(在下一个循环中)后调用此方法
更多解释:
- 一个线程=代码流同步
- 主线程 = looper
- looper = message que = 运行nable = loop
其他可能的解决方案 ??
退出回收器视图方法后调用
ps.
再提示一下,如果这段“代码”将 运行 更多,然后将 运行nable 拉到更高的堆栈存在位置(在 RecyclerView 的 GC 范围内)以减少资源使用和计算时间:)
private Runnable r = new Runnable {
public void run() { notifyDatasetChanged(); }
}
...
view.post(r);
...
或者对于使用接口
的通用解决方案拉入方法
public Runnable postNotify(ListAdapter la) {
return = new Runnable {
public void run() { la.notifyDatasetChanged(); }
};
}
...
private Runnable changed = postNotify(adapter);
...
view.pos(changed);
我正在构建一个允许用户对数字进行实时基础转换的应用程序。用户在编辑文本中输入他们的号码,然后使用加号和减号按钮选择基数。到目前为止我遇到的问题是提供实时转换。 recycler 视图中的所有 editText 都将它们的文本设置为一个 BigInteger,可以根据它们的基数进行转换。
我的想法是在用户输入新数字时更新 BigInteger。因此,每次用户输入一个数字时,我应该能够更新 BigInteger,通知回收器视图数据已更改,然后编辑文本视图应自动更新。这是我的 ConvertViewHolder
public ConvertViewHolder(final View itemView) {
super(itemView);
mBaseTextView = (TextView) itemView.findViewById(R.id.baseLabel);
mEditText = (EditText) itemView.findViewById(R.id.numberEditText);
mMinusButton = (Button) itemView.findViewById(R.id.minusButton);
mPlusButton = (Button) itemView.findViewById(R.id.plusButton);
mRemoveButton = (ImageButton)itemView.findViewById(R.id.removeButton);
mMinusButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRoot.get(getPosition()) > MIN_BASE) {
mRoot.set(getPosition(), (mRoot.get(getPosition()) - 1));
notifyDataSetChanged();
}
}
});
mPlusButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRoot.get(getPosition()) < MAX_BASE){
mRoot.set(getPosition(), (mRoot.get( getPosition() ) +1));
notifyDataSetChanged();
}
}
});
mRemoveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRoot.remove(getPosition());
notifyDataSetChanged();
}
});
mEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if(editable.toString().length() > 0) {
// change Big Integer
mNumber.setDecimalNumber(editable.toString(), mRoot.get( getPosition() ) );
// notify change
notifyDataSetChanged();
}
}
});
// TODO: convert numbers at the same time
}
public void bindConverter(final int root){
mBaseTextView.setText(String.format("%02d", root));
// String containing all the allowed digits depending on base
String digits = mNumber.getScaleFromBase(root);
if (root < 11) {
// filter input
mEditText.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_TEXT_FLAG_MULTI_LINE);
mEditText.setKeyListener(DigitsKeyListener.getInstance(digits));
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
} else {
mEditText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
// TODO: filter input for base higher than 10
}
// set editText to BigInteger displaying it in the correct base
// i.e. if the BigInteger is "8" it will be displayed as 8 if the base is 10
// and as 1000 if the base is 2
mEditText.setText(mNumber.getDecimalNumber(mRoot.get( getPosition() )));
}
}
但显然我不允许在 TextWatcher.onTextChanged() 中调用 notifySetDataHasChanged,因为编译器会向我抛出此错误:
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
这是不言自明的,但不幸的是我还没有找到可能的解决方法。
view.post(
new Runnable() {
public void run() { notifyDatasetChanged(); };
}
);
不言自明:
在 RecyclerView 计算布局或滚动(在下一个循环中)后调用此方法
更多解释:
- 一个线程=代码流同步
- 主线程 = looper
- looper = message que = 运行nable = loop
其他可能的解决方案 ??
退出回收器视图方法后调用
ps.
再提示一下,如果这段“代码”将 运行 更多,然后将 运行nable 拉到更高的堆栈存在位置(在 RecyclerView 的 GC 范围内)以减少资源使用和计算时间:)
private Runnable r = new Runnable {
public void run() { notifyDatasetChanged(); }
}
...
view.post(r);
...
或者对于使用接口
的通用解决方案拉入方法public Runnable postNotify(ListAdapter la) {
return = new Runnable {
public void run() { la.notifyDatasetChanged(); }
};
}
...
private Runnable changed = postNotify(adapter);
...
view.pos(changed);