EditText values in a RecyclerView gives same value

2019-02-18 21:21发布

问题:

I have a RecyclerView and each row has a EditText also. I am adding item to RecyclerView by searching them and then I type the quantity in the edit text. Then I send it to the server to store using json format. Item add is working perfectly. There is no edit text value swapping problem also when scrolling. I can display 5 rows in the screen.
Problem is when I send item to the server, edit text values in bottom rows get the same after 5th row. These are the rows I am adding to the recyclerview.Printed List that send to the server.

Item : 7.50-15 10PR FM CEAT               Quantity : 1
Item : 5.60-15 04PR K 511 CEAT            Quantity : 2
Item : 2.75-18 04PR SECURA F85 CEAT (F)   Quantity : 3
Item : 3.00-17 06PR SECURA ZOOM CEAT (R)  Quantity : 4
Item : 6.50-14 10PR FM CEAT               Quantity : 5
Item : 5.00-12 04PR GRIP MASTER CEAT      Quantity : 5
Item : 4.00-08 06PR AUTO RAJA RPG         Quantity : 5
Item : 9.00-20 14PR CEAT CLT LUG          Quantity : 5
Item : 8.25-20 14PR TR PLUS SUNTRAC       Quantity : 5
Item : 7.00-15 12PR FM CEAT               Quantity : 5

After the 5th position Quantity is the same. My input value is not coming.

This is my SelectItem class -

public class SelectItem extends AppCompatActivity implements SelectItemAdapter.OnItemClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.select_item);

        vollySingleton = VollySingleton.getsInstance();
        requestQueue = vollySingleton.getmRequestQueue();

        toolbar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setHomeButtonEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        myRecyclerView = (RecyclerView) findViewById(R.id.selectedItemRecyclerView);
        linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);

        spinner = (Spinner) findViewById(R.id.selectDistribChannel);
        arrayAdapter = new ArrayAdapter<String>(this, R.layout.spinner_item, YourDealerListFragment.disChannel);
        arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(arrayAdapter);
        selectedDisChannel = spinner.getSelectedItem().toString();

        sqLiteHandler = new SQLiteHandler(getApplicationContext());

        myRecyclerViewAdapter = new SelectItemAdapter(this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManager);
        myRecyclerViewAdapter.notifyDataSetChanged();

        dealerName = DealerListAdapter.getDealerName();
        dealerID = DealerListAdapter.getDealerID();
        repID = DealerListAdapter.getRepID();

        //order number
        orderId = "70000001";

        if (newOrderId == null) {
            newOrderId = orderId;
        }

        bAdd = (Button) findViewById(R.id.bAdd);

        bAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (myRecyclerViewAdapter.getItemCount() != 0) {
                    new AlertDialog.Builder(SelectItem.this)
                            .setTitle("Confirmation")
                            .setMessage("Do you want to send?")
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog, int whichButton) {
                                    checkOrderNo();
                                }
                            })
                            .setNegativeButton(android.R.string.no, null).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Empty List", Toast.LENGTH_SHORT).show();
                }
            }
        });

        //textView.setText(dealerName);
        getSupportActionBar().setTitle(dealerName);

        final AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);

        adapter = new MaterialSuggestionAdapter(getApplicationContext());
        acTextView.setAdapter(adapter);
        acTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Product result = adapter.getItem(position);
                String newName = result.getMatName().toString();
                String newQty = String.valueOf(result.getMatQuantity());
                String newPCode = result.getMatNo().toString();
                String newPlant = result.getMatPlant().toString();

                if (!newName.equals("")) {
                    if (myRecyclerViewAdapter.getItemCount() > 0) {

                        if (!isPresent(newPlant, newPCode, myRecyclerViewAdapter)) {
                            myRecyclerViewAdapter.add(1, newName, newQty, newPCode, newPlant);
                        } else {
                            Toast.makeText(getApplicationContext(), "Product Already in the List", Toast.LENGTH_SHORT).show();
                        }

                    } else {
                        myRecyclerViewAdapter.add(0, newName, newQty, newPCode, newPlant);
                    }
                } else {
                    Toast.makeText(getApplicationContext(), "Invalied Item!", Toast.LENGTH_SHORT).show();
                }
                acTextView.setText("");
            }
        });


    }

    private boolean isPresent(String newPlant, String newPCode, SelectItemAdapter myRecyclerViewAdapter) {
        boolean isPresent = false;
        for (int i = 0; i < myRecyclerViewAdapter.getItemCount(); i++) {
            if (newPCode.equalsIgnoreCase(myRecyclerViewAdapter.getItemPCode(i).toString()) && newPlant.equalsIgnoreCase(myRecyclerViewAdapter.getItemPlant(i).toString())) {
                isPresent = true;
                break;
            }
        }
        return isPresent;
    }

    //send items for one order
    private class SendItemAsync extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
        }

        @Override
        protected Void doInBackground(Void... arg0) {

            //Create JSON string start
            json_string = "{\"sending_items\":[";

            for (int i = 0; i < myRecyclerViewAdapter.getItemCount(); i++) {

               /* if (myRecyclerView.findViewHolderForLayoutPosition(i) instanceof SelectItemAdapter.ItemHolder) {
                    SelectItemAdapter.ItemHolder childHolder = (SelectItemAdapter.ItemHolder) myRecyclerView.findViewHolderForLayoutPosition(i);
                    numberPickerNumber = childHolder.getQtyNumber();
                }*/

                getNumPicNumber(i);

                //Repeat and loop this until all objects are added (and add try+catch)
                try {
                    JSONObject obj_new = new JSONObject();
                    obj_new.put("order_no", orderIdForItemTable);
                    obj_new.put("items", myRecyclerViewAdapter.getItemName(i).toString());
                    obj_new.put("items_no", myRecyclerViewAdapter.getItemPCode(i).toString());
                    obj_new.put("plant", myRecyclerViewAdapter.getItemPlant(i).toString());
                    obj_new.put("quantity", numberPickerNumber);
                    json_string = json_string + obj_new.toString() + ",";

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            //Close JSON string
            json_string = json_string.substring(0, json_string.length() - 1);
            json_string += "]}";

            HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, 3500);
            HttpConnectionParams.setSoTimeout(httpParams, 1000);
            HttpClient client = new DefaultHttpClient(httpParams);

            String url = AppConfig.URL_ITEMS_SEND;

            HttpPost request = new HttpPost(url);
            try {
                request.setEntity(new ByteArrayEntity(json_string.getBytes("UTF8")));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            request.setHeader("json", json_string);
            request.setHeader("Accept", "application/json");
            request.setHeader("Content-Type", "application/json");
            Log.i("", "excuting request");
            HttpResponse response = null;
            try {
                response = client.execute(request);
                Log.d("HTTP Response", response.getStatusLine().toString());
                try {
                    String responseBody = EntityUtils.toString(response.getEntity());
                    Log.d("Server Response", responseBody);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();

            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            finish();
            Bundle basket = new Bundle();
            basket.putString("dealerName", dealerName);
            basket.putString("orderNo", newOrderId);
            basket.putString("jsonString", json_string);
            Intent intent = new Intent(SelectItem.this, ItemCart.class);
            intent.putExtras(basket);
            startActivity(intent);
            finish();
            //Toast.makeText(getApplicationContext(), json_string, Toast.LENGTH_LONG).show();
        }
    }

    private String getNumPicNumber(int i) {
        if (myRecyclerView.findViewHolderForLayoutPosition(i) instanceof SelectItemAdapter.ItemHolder) {
            SelectItemAdapter.ItemHolder childHolder = (SelectItemAdapter.ItemHolder) myRecyclerView.findViewHolderForLayoutPosition(i);
            numberPickerNumber = childHolder.getQtyNumber();
        }
        return numberPickerNumber;
    }

    @Override
    public void onItemClick(SelectItemAdapter.ItemHolder item, int position) {
        Toast.makeText(this,
                "Remove " + position + " : " + item.getItemName(),
                Toast.LENGTH_SHORT).show();
        myRecyclerViewAdapter.remove(position);
    }

    private void checkOrderNo() {

        showDialog();

        DateFormat df = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
        final String nowDate = df.format(new Date());

        //final day of the month
        Date today = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.DATE, -1);
        Date lastDayOfMonth = calendar.getTime();
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        final String lastDate = sdf.format(lastDayOfMonth);

        Log.d("Last day ", sdf.format(lastDayOfMonth) + " // Today" + nowDate);


        // Tag used to cancel the insert
        String tag_string_req = "req_insert";

        final StringRequest strReq = new StringRequest(Request.Method.POST,
                AppConfig.URL_ITEM_DETAILS_SEND, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                hideDialog();
                try {
                    JSONObject jObj = new JSONObject(response);
                    if (jObj.names().get(0).equals("found")) {

                        newOrderId = jObj.getString("found").toString();
                        orderIdForItemTable = newOrderId;

                        new SendItemAsync().execute();

                        Log.d(TAG, "newOrderId: " + newOrderId);
                        Log.d(TAG, "New repID 2 inserted into sqlite: " + newOrderId + " " + nowDate);
                        sqLiteHandler.addItemDetails(newOrderId, repID, dealerID, nowDate, lastDate, selectedDisChannel);

                    } else {
                        Toast.makeText(getApplicationContext(), "Invalied Request", Toast.LENGTH_SHORT).show();
                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Inserting Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                // Posting params to register url
                Map<String, String> params = new HashMap<String, String>();
                params.put("order_no", orderId);
                params.put("repID", repID);
                params.put("dealerID", dealerID);
                params.put("nowDate", nowDate);
                params.put("lastDate", lastDate);
                params.put("disChannel", selectedDisChannel);

                return params;
            }
        };

        strReq.setRetryPolicy(new DefaultRetryPolicy(6000, 1,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }  
}

My Adapter class.

public class SelectItemAdapter extends RecyclerView.Adapter<SelectItemAdapter.ItemHolder> {

    private List<String> itemsName, itemsQty, itemsPCode, itemPlant;
    private OnItemClickListener onItemClickListener;
    private LayoutInflater layoutInflater;
    private RecyclerView myRecyclerview;

    public SelectItemAdapter(Context context) {
        layoutInflater = LayoutInflater.from(context);
        itemsName = new ArrayList<String>();
        itemsQty = new ArrayList<String>();
        itemsPCode = new ArrayList<String>();
        itemPlant = new ArrayList<String>();
    }

    @Override
    public SelectItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = layoutInflater.inflate(R.layout.custom_row_selected_item, parent, false);
        return new ItemHolder(itemView, this);
    }

    @Override
    public void onBindViewHolder(SelectItemAdapter.ItemHolder holder, int position) {
        holder.setItemName(itemsName.get(position));
        holder.setItemQty(itemsQty.get(position));
        holder.setItemPCode(itemsPCode.get(position));
        holder.setItemPlant(itemPlant.get(position));

    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }


    @Override
    public int getItemCount() {
        return itemsName.size();
    }

    public Object getItemName(int position) {
        return itemsName.get(position);
    }

    public Object getItemPCode(int position) {
        return itemsPCode.get(position);
    }

    public Object getItemPlant(int position) {
        return itemPlant.get(position);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        onItemClickListener = listener;
    }

    public OnItemClickListener getOnItemClickListener() {
        return onItemClickListener;
    }


    public interface OnItemClickListener {
        public void onItemClick(ItemHolder item, int position);
    }

    public void add(int location, String iName, String iQty, String iPCode, String iPlant) {
        itemsName.add(location, iName);
        itemsQty.add(location, iQty);
        itemsPCode.add(location, iPCode);
        itemPlant.add(location, iPlant);
        notifyItemInserted(location);
    }

    public void remove(int location) {
        if (location >= itemsName.size())
            return;

        itemsName.remove(location);
        notifyItemRemoved(location);
    }

    public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private SelectItemAdapter parent;
        TextView textItemName, txtPCode, txtAvailableQty, txtTempQty, txtPlant;
        Button bRemove;
        EditText numPicker;

        public ItemHolder(View itemView, SelectItemAdapter parent) {
            super(itemView);
            this.parent = parent;
            textItemName = (TextView) itemView.findViewById(R.id.txtProductName);
            txtAvailableQty = (TextView) itemView.findViewById(R.id.txtAvailbleQty);
            txtPCode = (TextView) itemView.findViewById(R.id.txtPCode);
            txtPlant = (TextView) itemView.findViewById(R.id.txtPlant);
            bRemove = (Button) itemView.findViewById(R.id.bRemove);
            numPicker = (EditText) itemView.findViewById(R.id.numberPicker);

            bRemove.setOnClickListener(this);
        }


        public void setItemName(CharSequence name) {
            textItemName.setText(name);
        }

        public void setItemQty(CharSequence name) {
            txtAvailableQty.setText(name);
        }

        public void setItemPCode(CharSequence name) {
            txtPCode.setText(name);
        }

        public void setItemPlant(CharSequence name) {
            txtPlant.setText(name);
        }

        public String getQtyNumber() {
            return numPicker.getText().toString();
        }

        public CharSequence getItemName() {
            return textItemName.getText();
        }


        public CharSequence getItemPCode() {
            return txtPCode.getText();
        }

        @Override
        public void onClick(View v) {
            final OnItemClickListener listener = parent.getOnItemClickListener();
            if (listener != null) {
                listener.onItemClick(this, getPosition());
            }
        }
    }

}

回答1:

RecyclerView creates only as many view holders as are needed to display the on-screen portion of the dynamic content, plus a few extra. As the user scrolls through the list, the RecyclerView takes the off-screen views and rebinds them to the data which is scrolling onto the screen

// Items for recycler View 
//binding data
private ArrayList<Data> Items;

//HashMap to store editText text afterTextChanged
    //each editext in RecyclerView contains Unique Key And Value
    private HashMap<String,String> sourceData=new HashMap<>();

Refer This RecyclerView Program

public class DataRecyclerView extends RecyclerView.Adapter<DataRecyclerView.DataViewHolder> {

    private Context context;
    // Items for recycler View 
    //binding data
    private ArrayList<Data> Items;
    private LayoutInflater layoutInflater;

    //HashMap to store editText text afterTextChanged
    //each editext in RecyclerView contains Unique Key And Value
    private HashMap<String,String> sourceData=new HashMap<>();

    DataRecyclerView(Context context,ArrayList<Data> Items)
    {
        this.Items=Items;
        this.context=context;
        layoutInflater=LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public DataViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    //DataBinding is used to bind Data
        DataViewHolderBinding binding= DataBindingUtil.inflate(layoutInflater, R.layout.template,parent,false);
        return new DataViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull DataViewHolder holder, int position) {
    //Pass Data pojo to  Holder
        holder.bindData(Items.get(position));
    }

    @Override
    public int getItemCount() {
        return Items.size();
    }


    class DataViewHolder extends RecyclerView.ViewHolder {




        private EditText amount;


         DataViewHolder(DataViewHolderBinding itemView) {
            super(itemView.getRoot());
            binding=itemView;
            amount=binding.PayAmount;
        }

         void bindData(Data data)//Data pojo for DataBinding
        {
            if(binding!=null) {
            // data will  automatically set to textViews In DataBinding  
            binding.setData(data);



               //every time data binds to views 
               //get text of respective edittext and assign to that current edittext

                if (sourceData.containsKey((String.valueOf(getAdapterPosition())))) {// checks current editText key  is availible or not
                      if (data.getIDNumber().equals(Items.get(getAdapterPosition()).getData.getIDNumber())) { // 
                        amount.setText(sourceData.get((String.valueOf(getAdapterPosition()))).getAmount());
                }else
                    {
                           if (data.getIDNumber().equals(Items.get(getAdapterPosition()).getData.getIDNumber())) { // 
                             amount.setText(null);
                    }



                amount.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) {


                    //when user enter text into edittext 
                    //editetext key already availible  in sourceData
                    // then update the value to hashmap sourceData
                        if (sourceData.containsKey(String.valueOf(getAdapterPosition()))) {
                            if (data.getIDNumber().equals(Items.get(getAdapterPosition()).getData.getIDNumber())) { // 
                                if (!s.toString().trim().isEmpty()) {
                                    if (!s.toString().trim().equals("0")) {
                                        sourceData.put(String.valueOf(getAdapterPosition()),s.toString().trim());

                                    } else {
                                        sourceData.put(String.valueOf(getAdapterPosition()), s.toString().trim();

                                    }
                                } else {
                                    sourceData.put(String.valueOf(getAdapterPosition()),null );
                                }
                            }

                        }
                        else {

                        //when user enter text into  edittext for the first time
                        //check for current Data pojo IDNumber with getAdapterPosition Items Data pojo IDNumber
                        //if it equal 
                        //then we  store text into hashmap for specific edittext by using adapterPosition as key

                            if (data.getIDNumber().equals(Items.get(getAdapterPosition()).getData.getIDNumber())) { // 
                                if (!s.toString().trim().isEmpty()) {
                                    if (!s.toString().trim().equals("0")) {
                                        sourceData.put(String.valueOf(getAdapterPosition()),s.toString().trim());

                                    } else {
                                        sourceData.put(String.valueOf(getAdapterPosition()), s.toString().trim();

                                    }
                                } else {
                                    sourceData.put(String.valueOf(getAdapterPosition()),null );
                                }
                            }
                        }
                    }
                });

            }
        }




    }

}

### Image Reference I can't show proper Image but Its Look Like this



回答2:

The rows in RecyclerView is reusing while scrolling. So you need to create an array for save each EditText value
Then addTextChangedListener to your EditText to save the EditText value while you input

public void onBindViewHolder(SelectItemAdapter.ItemHolder holder, int position) {
    ...
    holder.numPicker.setText(arrayForSaveEditTextValue[position]);
    holder.numPicker.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
            arrayForSaveEditTextValue[position] = arg0.toString();
        }
    });
    ...
}