标题说明了一切,我有RecyclerView
用于动态存储值,但一次只能存储一个项目。该项目包含3个TextViews
当我正常添加所有项目时,它可以工作,但是当我添加x项目,然后删除最后一项,然后点击“提交”,应用程序崩溃。
我在查看器中执行removeAt(getAdapterPosition()
,其中`removeAt(int)是:
private void removeAt(int removePosition){
grosirList.product_grosir_list.remove(removePosition);
notifyItemRemoved(removePosition);
}
并提交按钮:
promoConfirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Gson gson = new Gson();
if (postProductPromoAdapter.getGrosirList() == null){
} else {
String grosirAddJson = gson.toJson(postProductPromoAdapter.getGrosirList());
Intent intent = new Intent();
intent.putExtra("grosirPromoPrice", grosirAddJson);
intent.putExtra("promoPrice", promoPriceET.getText().toString());
setResult(RESULT_OK, intent);
finish();
}
}
});
getGrosirList()
是
public GrosirAddList getGrosirList(){
if (mAwesomeValidation.validate()){
return this.grosirList;
} else {
return null;
}
}
基本上,提交按钮会验证TextViews
,如果已经验证,则返回true。
这是错误发生的地方:
minRangeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if(!s.toString().equals("")){
grosirList.product_grosir_list.get(getAdapterPosition()).grosir_min = String.valueOf(s);
} else {
grosirList.product_grosir_list.get(getAdapterPosition()).grosir_min = null; // Error happens here
}
}
});
我将用户的输入保存到适配器内的对象,以便稍后通过TextWatcher
这是错误日志:
java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1
at java.util.ArrayList.get(ArrayList.java:310)
at xx.PostProductPromoAdapter$FiturPromoHolder$1.afterTextChanged(PostProductPromoAdapter.java:236)
at android.widget.TextView.sendAfterTextChanged(TextView.java:7563)
at android.widget.TextView.setText(TextView.java:3920)
at android.widget.TextView.setText(TextView.java:3769)
at android.widget.EditText.setText(EditText.java:84)
at android.widget.TextView.setText(TextView.java:3744)
at com.basgeekball.awesomevalidation.helper.SpanHelper.setColor(SpanHelper.java:22)
at com.basgeekball.awesomevalidation.validators.ColorationValidator$1.execute(ColorationValidator.java:34)
at com.basgeekball.awesomevalidation.validators.Validator.checkFields(Validator.java:76)
at com.basgeekball.awesomevalidation.validators.ColorationValidator.trigger(ColorationValidator.java:25)
at com.basgeekball.awesomevalidation.AwesomeValidation.validate(AwesomeValidation.java:81)
at xx.getGrosirList(PostProductPromoAdapter.java:76)
at xx$3.onClick(PostProductPromoActivityRecycler.java:164)
更新:
我用它来检查项目是否有效:
public boolean filledCheck(int itemNumber){
return this.grosirList.product_grosir_list.size() > 0
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_price != null
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_max != null
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_min != null;
}
这样就可以将值添加到EditText
。值使用TextWatcher
if(grosirList.product_grosir_list.get(position).grosir_min == null) {
((FiturPromoHolder)holder).minRangeET.setText("");
} else {
((FiturPromoHolder)holder).minRangeET.setText(grosirList.product_grosir_list.get(position).grosir_min);
}
if(grosirList.product_grosir_list.get(position).grosir_max == null) {
((FiturPromoHolder)holder).maxRangeET.setText("");
} else {
((FiturPromoHolder)holder).maxRangeET.setText(grosirList.product_grosir_list.get(position).grosir_max);
}
if(grosirList.product_grosir_list.get(position).grosir_price == null) {
((FiturPromoHolder)holder).grossPriceET.setText("");
} else {
((FiturPromoHolder)holder).grossPriceET.setText(grosirList.product_grosir_list.get(position).grosir_price);
}
更新,这是整个适配器代码:
public boolean uploadProductLoading = true;
private Context context;
private AwesomeValidation mAwesomeValidation;
public GrosirAddList grosirList = new GrosirAddList();
private SharedPreferencesList sharedPreferencesList;
private SharedPreferenceUtilities sharedPreferenceUtilities;
private Utilities utilities;
private UtilityUriHelper utilityUriHelper;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
// User information
private String userIdString;
private String userAliasString;
private String userEmailString;
private String loginSharedPrefsString;
private String userId;
private String userAlias;
public PostProductPromoAdapter(Context context) {
this.sharedPreferencesList = new SharedPreferencesList();
this.sharedPreferenceUtilities = new SharedPreferenceUtilities();
this.context = context;
this.userIdString = sharedPreferencesList.userIDString;
this.userAliasString = sharedPreferencesList.userAliasString;
this.loginSharedPrefsString = sharedPreferencesList.loginSharedPreference;
this.utilities = new Utilities();
this.utilityUriHelper = new UtilityUriHelper();
this.userId = sharedPreferenceUtilities.getValue(context, loginSharedPrefsString, userIdString);
this.userAlias = sharedPreferenceUtilities.getValue(context, loginSharedPrefsString, userAliasString);
this.mAwesomeValidation = new AwesomeValidation(ValidationStyle.COLORATION);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View productView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.activity_marketplace_upload_produk_fitur_promo_card, parent, false);
return new FiturPromoHolder(productView);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
// Animation, disabled for now
// setAnimation(holder.itemView, position);
/*((FiturPromoHolder)holder).grossPriceDeleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// notifyItemRangeChanged(position, grosirList.product_grosir_list.size());
// notifyDataSetChanged();
// notifyItemRemoved(position);
// notifyItemRangeChanged(position, grosirList.product_grosir_list.size());
}
});*/
/*((FiturPromoHolder)holder).minRangeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if(!s.toString().equals("")){
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_min = String.valueOf(s);
}
} else {
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_min = null;
}
}
}
});
((FiturPromoHolder)holder).maxRangeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!s.toString().equals("")) {
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_max = String.valueOf(s);
}
} else {
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_max = null;
}
}
}
});
((FiturPromoHolder)holder).grossPriceET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!s.toString().equals("")) {
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_price = String.valueOf(s);
}
} else {
if (grosirList.product_grosir_list.size() != 0){
grosirList.product_grosir_list.get(position).grosir_price = null;
}
}
}
});*/
int x = holder.getLayoutPosition();
if(grosirList.product_grosir_list.get(x).grosir_min != null) {
((FiturPromoHolder)holder).minRangeET.setText(grosirList.product_grosir_list.get(x).grosir_min);
} else {
((FiturPromoHolder)holder).minRangeET.setText(null);
}
if(grosirList.product_grosir_list.get(x).grosir_max != null) {
((FiturPromoHolder)holder).maxRangeET.setText(grosirList.product_grosir_list.get(x).grosir_max);
} else {
((FiturPromoHolder)holder).maxRangeET.setText(null);
}
if(grosirList.product_grosir_list.get(x).grosir_price != null) {
((FiturPromoHolder)holder).grossPriceET.setText(grosirList.product_grosir_list.get(x).grosir_price);
} else {
((FiturPromoHolder)holder).grossPriceET.setText(null);
}
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
viewToAnimate.clearAnimation();
// Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
Animation animation = AnimationUtils.loadAnimation(context, R.anim.fade_in);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public boolean filledCheck(int itemNumber){
return this.grosirList.product_grosir_list.size() > 0
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_price.trim().length() > 0
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_max.trim().length() > 0
&& this.grosirList.product_grosir_list.get(itemNumber - 1).grosir_min.trim().length() > 0;
}
private void removeAt(int removePosition){
grosirList.product_grosir_list.remove(removePosition);
// notifyItemRemoved(removePosition);
// notifyItemRangeChanged(removePosition, grosirList.product_grosir_list.size());
// notifyDataSetChanged();
notifyItemRemoved(removePosition);
notifyDataSetChanged();
// notifyItemRangeRemoved(removePosition, grosirList.product_grosir_list.size());
// notifyItemRangeChanged(removePosition, grosirList.product_grosir_list.size());
}
private void removeRange(int removePosition){
int tempSize = grosirList.product_grosir_list.size();
for (int i = removePosition; i < tempSize; i++){
grosirList.product_grosir_list.remove(removePosition);
// notifyItemRemoved(i);
}
notifyDataSetChanged();
// notifyItemRangeRemoved(removePosition, grosirList.product_grosir_list.size());
// notifyItemRangeChanged(0, this.grosirList.product_grosir_list.size());
}
private void clearAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
viewToAnimate.clearAnimation();
}
public void addGrosirList(GrosirAddList dataset){
this.grosirList.product_grosir_list.addAll(dataset.product_grosir_list);
notifyDataSetChanged();
// notifyItemInserted(grosirList.product_grosir_list.size() - 1);
// this.grosirList.add(grosirList.size(), dataset.product_grosir_list.get());
// notifyItemInserted(grosirList.size() - 1);
}
public GrosirAddList getGrosirList(){
if (mAwesomeValidation.validate()){
return this.grosirList;
} else {
return null;
}
// return this.grosirList;
}
@Override
public int getItemCount() {
return grosirList.product_grosir_list.size();
}
public class FiturPromoHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
Handler handler;
RelativeLayout minRangeWrapper;
OpenSansEditText minRangeET;
RelativeLayout maxRangeWrapper;
OpenSansEditText maxRangeET;
RelativeLayout grossPriceWrapper;
OpenSansEditText grossPriceET;
OpenSansButton grossPriceDeleteBtn;
public FiturPromoHolder(View promoView) {
super(promoView);
minRangeWrapper = (RelativeLayout)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_minRangeWrapper);
minRangeWrapper.setOnClickListener(this);
minRangeET = (OpenSansEditText)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_minRangeET);
maxRangeWrapper = (RelativeLayout)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_maxRangeWrapper);
maxRangeWrapper.setOnClickListener(this);
maxRangeET = (OpenSansEditText)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_maxRangeET);
grossPriceWrapper = (RelativeLayout)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_grossPriceWrapper);
grossPriceWrapper.setOnClickListener(this);
grossPriceET = (OpenSansEditText)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_grossPriceET);
grossPriceDeleteBtn = (OpenSansButton)promoView.findViewById(R.id.fragment_marketplace_upload_produk_fitur_promo_card_grossPriceDeleteBtn);
grossPriceDeleteBtn.setOnClickListener(this);
this.setIsRecyclable(false);
handler = new Handler();
minRangeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
grosirList.product_grosir_list.get(getLayoutPosition()).grosir_min = String.valueOf(s);
}
}, 200);
}
@Override
public void afterTextChanged(Editable s) {
}
});
maxRangeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
grosirList.product_grosir_list.get(getLayoutPosition()).grosir_max = String.valueOf(s);
}
}, 200);
}
@Override
public void afterTextChanged(Editable s) {
}
});
grossPriceET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
grosirList.product_grosir_list.get(getLayoutPosition()).grosir_price = String.valueOf(s);
}
}, 200);
}
@Override
public void afterTextChanged(Editable s) {
}
});
grossPriceET.addTextChangedListener(new NumberTextWatcher(grossPriceET));
mAwesomeValidation.addValidation(minRangeET, RegexTemplate.NOT_EMPTY, "Jumlah minimum tidak boleh kosong");
mAwesomeValidation.addValidation(maxRangeET, RegexTemplate.NOT_EMPTY, "Jumlah maximum tidak boleh kosong");
mAwesomeValidation.addValidation(grossPriceET, RegexTemplate.NOT_EMPTY, "Harga tidak boleh kosong");
}
@Override
public void onClick(View v) {
if (v.equals(grossPriceDeleteBtn)) {
int removePosition = getAdapterPosition();
try {
grosirList.product_grosir_list.remove(removePosition);
notifyItemRemoved(removePosition);
notifyDataSetChanged();
minRangeET.setError(null);
maxRangeET.setError(null);
grossPriceET.setError(null);
//
mAwesomeValidation.addValidation(minRangeET, RegexTemplate.NOT_EMPTY, "Jumlah minimum tidak boleh kosong");
mAwesomeValidation.addValidation(maxRangeET, RegexTemplate.NOT_EMPTY, "Jumlah maximum tidak boleh kosong");
mAwesomeValidation.addValidation(grossPriceET, RegexTemplate.NOT_EMPTY, "Harga tidak boleh kosong");
}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}
} else if(v.equals(minRangeWrapper)) {
minRangeET.requestFocusFromTouch();
} else if(v.equals(maxRangeWrapper)) {
maxRangeET.requestFocusFromTouch();
} else if(v.equals(grossPriceWrapper)) {
grossPriceET.requestFocusFromTouch();
}
}
}
希望错误不是那么愚蠢......
答案 0 :(得分:1)
可能是因为我们使用notifyItemRemoved()
时的动画。因此,在动画延迟期间,如果我们立即调用getAdapterPosition()
方法,则它会返回-1
。我有同样的问题,而我立即反复删除多个项目,我得到了这个例外。
可能的解决方案: 您可以先查看位置,如下面的代码所示:
private void removeAt(int removePosition){
if(removePosition == -1)
return;
grosirList.product_grosir_list.remove(removePosition);
notifyItemRemoved(removePosition);
}
这是一个迟到的答案,但希望有所帮助! :)
答案 1 :(得分:0)
这可能有几个原因。首先,检查适配器中的getItemCount()
,确保它返回堆栈的大小。其次,而不是notifyItemRemoved()
通知您的适配器堆栈已随notifyDataSetChanged()
如果上面那些没有解决您的问题,请发布您的适配器代码,以及您使用堆栈处理的每个代码。问题应该从其中一个点上升。
最佳, RENC。