2016-04-28 43 views
0

標題說明了一切,我有一個RecyclerView它用於動態地存儲值,但一次只有一個項目。該項目包含3 TextViewsAndroid - getAdapterPosition()在刪除一個項目後返回-1

當我正常添加所有項目,它的工作原理,但是當我添加x項目,然後刪除最後一個,然後單擊「提交」,應用程序崩潰。

我在viewholder其中`RemoveAt移除(INT)做removeAt(getAdapterPosition()是:

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) 

更新:

我用這個來檢查th e項目是有效的:

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

如果您閱讀文檔,則會在調用notifyDataSetChanged或任何類似的方法時返回-1。 [來源](https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getAdapterPosition%28%29)。 – torque203

+0

哇,那麼,如何在刪除值後處理'TextWatcher'?我需要將每個EditText的值更改爲列表中的一個,但刪除一個項目後,該位置不會更新。它仍然位於位置1(移除的項目位於位置1) –

回答

1

可能是因爲動畫,而我們使用notifyItemRemoved()。所以在動畫延遲期間,如果我們立即調用getAdapterPosition()方法,那麼它將返回-1。我有同樣的問題,而我反覆刪除多個項目立即,我得到了這個例外。

可能的解決方法: 你可以首先檢查第一位置,如下面的代碼:

private void removeAt(int removePosition){ 
    if(removePosition == -1)  
     return; 
    grosirList.product_grosir_list.remove(removePosition); 
    notifyItemRemoved(removePosition); 
} 

這是一個遲到的答案,但希望幫助! :)

+0

哈哈哈確實是一個遲到的答案,但現在我得到了它的工作:D最後,我檢查'removePosition'是否在0到數據集大小-1之間。通過這樣做,我避開了錯誤,我認爲它仍然是一直工作到現在爲止lol –

+0

:D很棒!!!!!!! – Meet

+0

@KevinMurvie如果解決了您的問題,您可以將此答案標記爲已接受。 :) – Meet

0

有可能是這有幾個原因。首先,檢查您的適配器中的getItemCount(),確保它返回堆棧的大小。二,而不是notifyItemRemoved()通知你的適配器,堆棧已經改變notifyDataSetChanged()

如果上面那些沒有解決你的問題,請發佈你的適配器代碼,以及你的堆棧工作的每一個代碼。問題應該從這些點之一上升。

最好, Renç。

+0

我的'getItemCount()'返回了我的棧的大小,它是'return grosirList.product_grosir_list.size();''我已經完成了'notifyItemRemoved()'然後'notifyDataSetChanged()',以及其中之一。還有關於適配器代碼,我的堆棧工作。我認爲我已經發布了所有這些,讓我檢查和張貼任何未發佈的代碼 –

+0

我發佈了2個片段,當我將textwatcher移到'onBindViewHolder'並且需要位置需要時從參數,它說無效索引,索引是0,但大小爲0,會使條件'如果大小== 0' –

+0

Nahhh,試圖做到這一點,並得到索引1,大小1代替..我現在在虧損 –