I'm in a dire situation of finding a solution for speeding up loading data into the RecyclerView. Data load from the server database and populate the row. Each row has a few EditTexts where user enters some values. Within the OnBindViewHolder, each value entered by the user is captured using a text watcher, and then totals are calculated and displayed real-time in the footer of the parent view.(outside the RecyclerView) Also, inside the OnBindViewHolder, a method is called to update a table in the DB, with the values just entered and captured.
So, basically, when each row gets bound, both the DB and the UI get updated. When the data load is huge, loading of the recyclerView is really slow. What I have tried are moving the DB update to a separate thread, using async task to update the DB. But nothing worked. What should I do here?
Adapter's OnBindViewHolder code is displayed below.
public void onBindViewHolder(final MyViewHolder holder, #SuppressLint("RecyclerView") final int position, List<Object> payload) {
//onBindViewHolder(holder,position);
holder.ref = position;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
onBind = true;
// data passed from getAllData method aka all from TempInvoice
SalesInvoiceModel siModel = salesInvoice.get(position);
holder.code.setText(siModel.getCode());
holder.product.setText(siModel.getProduct());
holder.batchNum.setText(siModel.getBatchNumber());
try {
Date date = simpleDateFormat.parse(siModel.getExpiryDate());
holder.expiry.setText(date.toString());
} catch (Exception ex) {
holder.expiry.setText("Error");
}
holder.expiry.setText(siModel.getExpiryDate());
if (siModel.getDiscountRate() > 0) {
holder.unitprice.setText(siModel.getRetailPrice() + "");
} else {
holder.unitprice.setText(siModel.getUnitPrice() + "");
}
holder.stock.setText(siModel.getStock() + "");
holder.lineval.setText(siModel.getLineValue() + "");
if (payload == null || payload.size() == 0) {
holder.shelf.setText(siModel.getShelf() + "");
holder.request.setText(siModel.getRequest() + "");
holder.order.setText(siModel.getOrder() + "");
holder.free.setText(siModel.getFree() + "");
holder.discount.setText(siModel.getDiscountRate() + "");
} else {
for (Object editText : payload) {
//String val = (String)payload.get(0);
String val = (String) editText;
switch (val) {
case SHELF:
if (lostFocus) {
holder.shelf.setText(salesInvoice.get(position).getShelf() + "");
}
break;
case REQUEST:
if (lostFocus) {
holder.request.setText(salesInvoice.get(position).getRequest() + "");
}
break;
case ORDER:
if (lostFocus) {
holder.order.setText(salesInvoice.get(position).getOrder() + "");
}
break;
case FREE:
if (lostFocus) {
holder.free.setText(salesInvoice.get(position).getFree() + "");
}
break;
case DISCOUNT:
if (lostFocus) {
holder.discount.setText(salesInvoice.get(position).getDiscountRate() + "");
}
break;
case LINEVAL:
holder.lineval.setText(salesInvoice.get(position).getLineValue() + "");
break;
default:
onBindViewHolder(holder, position);
break;
}
}
}
//ADD TEXT WATCHERS
holder.shelf.setOnFocusChangeListener(new FocusChangeListener());
holder.shelf.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
int pos = holder.ref;
if (!onBind) {
if (!s.equals("")) {
notifyItemChanged(pos, SHELF);
Log.d(TAG, "inside text change typed shelf_" + s);
salesInvoice.get(pos).setShelf(Integer.parseInt(s + ""));
} else {
salesInvoice.get(pos).setShelf(0);
}
lastUpdatedRow = pos;
}
}
});
holder.request.setOnFocusChangeListener(new FocusChangeListener());
holder.request.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valHasChanged = false;
boolean freeHasChanged = false;
int pos = holder.ref;
if (!onBind) {
if (!(s.equals(""))) {
int val = Integer.parseInt((s));
int stock = salesInvoice.get(pos).getStock();
// if stock does not have the particular product
if (val > stock) {
val = stock;
valHasChanged = true;
}
salesInvoice.get(pos).setRequest(val);
if (!refresh) salesInvoice.get(pos).setOrder(val);
if (salesInvoice.get(pos).getFree() + salesInvoice.get(pos).getOrder() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
freeHasChanged = true;
}
} else {
salesInvoice.get(pos).setRequest(0);
}
notifyItemChanged(pos, ORDER);
if (valHasChanged) {
notifyItemChanged(pos, REQUEST);
}
if (freeHasChanged) {
notifyItemChanged(pos, FREE);
}
lastUpdatedRow = pos;
}
}
});
holder.order.setOnFocusChangeListener(new FocusChangeListener());
holder.order.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valHasChanged = false;
boolean freeHasChanged = false;
int pos = holder.ref;
if (!onBind) {
if (!(s.equals(""))) {
int val = Integer.parseInt(s);
int stock = salesInvoice.get(pos).getStock();
if (val > stock) {
val = stock;
valHasChanged = true;
}
salesInvoice.get(pos).setOrder(val);//make sure we set returnQty before
//checking the total of returnQty and free against stock
if (salesInvoice.get(pos).getOrder() + salesInvoice.get(pos).getFree() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
freeHasChanged = true;
}
} else {
salesInvoice.get(pos).setOrder(0);
}
if (valHasChanged) {
notifyItemChanged(pos, ORDER);//notify the adapter that value changed and refresh the view mentioned by the string
}
if (freeHasChanged) notifyItemChanged(pos, FREE);
notifyItemChanged(pos, LINEVAL);
lastUpdatedRow = pos;
}
}
});
holder.free.setOnFocusChangeListener(new FocusChangeListener());
holder.free.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valChanged = false;
int pos = holder.ref;
if (!onBind) {
if ((!s.equals("")) && (!(s.equals("0")))) {
int val = Integer.parseInt(s);
salesInvoice.get(pos).setFree(val);
holder.discount.setEnabled(false);
if (salesInvoice.get(pos).getOrder() + salesInvoice.get(pos).getFree() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
valChanged = true;
holder.discount.setEnabled(true);
}
} else {
salesInvoice.get(pos).setFree(0);
holder.discount.setEnabled(true);
}
notifyItemChanged(pos, LINEVAL);
if (valChanged) notifyItemChanged(pos, FREE);
holder.setCursor(FREE);
lastUpdatedRow = pos;
}
}
});
holder.discount.setOnFocusChangeListener(new FocusChangeListener());
holder.discount.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
int pos = holder.ref;
if (!(s.equals(salesInvoice.get(pos).getDiscountRate() + ""))) {
if ((!s.equals("")) && (!(s.equals("0"))) && (!(s.equals("0.0"))) && (!(s.equals("0.")))) {
Double rate = Double.parseDouble(s.toString().trim());
Log.i(" RAte ", rate + "");
salesInvoice.get(pos).setDiscountRate(rate);
holder.free.setEnabled(false);
} else {
salesInvoice.get(pos).setDiscountRate(0.0);
holder.free.setEnabled(true);
}
if (!onBind) {
notifyItemChanged(pos, LINEVAL);
lastUpdatedRow = pos;
}
}
}
});
if (position % 2 == 0) {
holder.setColor(Color.LTGRAY);
} else {
holder.setColor(Color.GRAY);
}
onBind = false;
notifyUpdate(); //calling to update the UI
Log.d("ASY", "before db call");
DBAdapterAsync dbAdapter = new DBAdapterAsync(getContextForAdapter);
dbAdapter.execute(salesInvoice.get(holder.ref));
Log.d("ASY", "after db call");
}
//async task class for DB Update
#SuppressLint("StaticFieldLeak")
private class DBAdapterAsync extends AsyncTask<SalesInvoiceModel, Void, String> {
private SQLiteDatabase db;
private DBHelper dbHelper;
DBAdapterAsync(Context context) {
this.dbHelper = new DBHelper(context);
Log.d("ASY", "inside constructor");
}
#Override
protected void onPreExecute() {
try {
db = dbHelper.getWritableDatabase();
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
dbHelper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(SalesInvoiceModel... models) {
SalesInvoiceModel model = models[0];
Log.d(TAG, "inside updateInvoiceData_");
Log.d(TAG, "shelf_" + model.getShelf());
Log.d(TAG, "order_" + model.getOrder());
Log.d(TAG, "free_" + model.getFree());
String sql = "UPDATE temp_invoice SET" +
" Shelf=" + model.getShelf() + " , Request=" + model.getRequest()
+ " , OrderQty=" + model.getOrder() + " , Free=" + model.getFree()
+ " , Disc=" + model.getDiscountRate() + " , LineVal=" + model.getLineValue()
+ ", RetailPriceLineVal=" + model.getRetailLineVal()
+ " WHERE _id=" + model.getId();
db.execSQL(sql);
Log.d(TAG, "DB method finished,");
Log.d("ASY", "after do in background");
return null;
}
}
Related
Can someone please show me how I can pause my code in onCreate() until the event listener getting data from my firebase realtime DB has completed?
I have been stuck on this for a while now, anything that does not involve me completely reformatting my code would be awesome.
My code works but when getting data from the firebase my code continues to run without waiting for the EventListener to recieve the data...
I need to be able to stop the code but I do not know how...
-Just a suggestion: is it possible to use Thread.wait() and Thread.notify()?
I don't understand how threads/tasks/runnables work that well so a good explanation would be appreciated.
public void createNullRoom() {
room.setPlayerWhoIsSpyer(0);
room.add(1);
room.add(2);
room.add(3);
room.add(4);
room.add(5);
room.add(6);
room.setRoomCode("room_0");
room.setWinner(0);
room.setScene(0);
room.setRoundHasEnded(true);
room.setSecretWord("");
this.gameRoom.add(0,room);
pref.child(room.getRoomCode()).setValue(room);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w(this.getClass().getName() + ".java/" + new Throwable().getStackTrace()[0].getLineNumber(), "Game.onCreate");
setContentView(R.layout.gameview_public);
pId = 0;
room = new Room();
AssignUser = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
gameRoom.clear();
long v = snapshot.child("gameRoom").getChildrenCount();
int count = (int) v;
for (int i = 0; i < count + 1; i++) {
Room r = new Room();
boolean temp = true;
try {
r = snapshot.child("gameRoom").child("room_" + i).getValue(Room.class);
} catch (IndexOutOfBoundsException e) {
temp = false;
}
if (temp) {
gameRoom.add(r);
}
}
Log.i(this.getClass().getName() + ".java/" + new Throwable().getStackTrace()[0].getLineNumber(), "gameRoom data retrieved");
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
};
// ---- VALUE EVENT LISTENER TO GET DATA ------
AssignUser = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
gameRoom.clear();
long v = snapshot.child("gameRoom").getChildrenCount();
int count = (int) v;
for (int i = 0; i < count + 1; i++) {
Room r = new Room();
boolean temp = true;
try {
r = snapshot.child("gameRoom").child("room_" + i).getValue(Room.class);
} catch (IndexOutOfBoundsException e) {
temp = false;
}
if (temp) {
gameRoom.add(r);
Log.i(this.getClass().getName() + ".java/" + new Throwable().getStackTrace()[0].getLineNumber(), "\tSize: " + gameRoom.size());
}
}
Log.i(this.getClass().getName() + ".java/" + new Throwable().getStackTrace()[0].getLineNumber(), "gameRoom data retrieved");
Log.e(this.getClass().getName() + ".java/" + new Throwable().getStackTrace()[0].getLineNumber(), "inside the snapshot, gamerooms.size: " + gameRoom.size() + " line 343");
assignUser();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
};
// ------------------------------------------------
ref.addListenerForSingleValueEvent(AssignUser);
createNullRoom();
// ===================================THIS NEEDS TO PAUSE HERE
int i = 0;
while(playerjoined == false) {
boolean exists = true;
Log.i(this.getClass().getName() +".java/"+ new Throwable().getStackTrace()[0].getLineNumber(), "line 431: if");
try {
this.room = this.gameRoom.get(i);
} catch (IndexOutOfBoundsException e) {
exists = false;
}
if (exists) {
this.room = gameRoom.get(i);
this.roomcode = this.room.getRoomCode();
for (int q = 1; q < 7; q++) {
if(this.getFalse() == q) {
this.room.add(q);
this.pref.child(this.roomcode).setValue(this.room);
this.pId = q;
q = 6;
playerjoined = true;
}
}
if(playerjoined == false) {
i++;
}
} else {
CreateNewPublicRoom(i);
Log.i(this.getClass().getName() +".java/"+ new Throwable().getStackTrace()[0].getLineNumber(), "Game.java/" + Thread.currentThread().getStackTrace()[1].getLineNumber() + "\tNew Public Room Made");
pref.child(this.roomcode).setValue(this.room);
Log.e(this.getClass().getName() +".java/"+ new Throwable().getStackTrace()[0].getLineNumber(),"OUTSIDE the snapshot, gamerooms.size: " + gameRoom.size() + " line 403");
Log.i(this.getClass().getName() +".java/"+ new Throwable().getStackTrace()[0].getLineNumber(), "\tThis.playerjoined == "+playerjoined);
}
}
ref.child("gameRoom").child(this.room.getRoomCode()).setValue(this.room)
etc...
I am using from bellow code for converting numbers to currency format when text changes but when I scrolled the recyclerView I lost true data. What can I do :
public class ManagePriceProductsAdapter extends RecyclerView.Adapter<ManagePriceProductsAdapter.ViewHolder> {
private List<ManagePriceProductsModel.DataValue> managePriceProductsModelList;
private Context context;
private getListDiscountInterface getListDiscountInterface;
private int vendorId = -1;
public ManagePriceProductsAdapter(Context context,
List<ManagePriceProductsModel.DataValue> managePriceProductsModelList,
getListDiscountInterface getListDiscountInterface,
int vendorId) {
this.context = context;
this.managePriceProductsModelList = managePriceProductsModelList;
this.getListDiscountInterface = getListDiscountInterface;
this.vendorId = vendorId;
}
#Override
public ManagePriceProductsAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context)
.inflate(R.layout.list_item_manage_price_products, viewGroup, false);
return new ManagePriceProductsAdapter.ViewHolder(view,
new DiscountNumberTextWatcherWithSeperator(),
new OriginalNumberTextWatcherWithSeperator());
}
public void getListDiscount() {
getListDiscountInterface.sendGetListDiscountToActivity(managePriceProductsModelList);
}
public void backButton() {
getListDiscountInterface.backButtonForListDiscount(managePriceProductsModelList);
}
public void resetAdapter() {
this.managePriceProductsModelList.clear();
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(final ManagePriceProductsAdapter.ViewHolder viewHolder, int position) {
viewHolder.discountNumberTextWatcherWithSeperator.updatePosition(viewHolder.getAdapterPosition(),
viewHolder.discountPriceEdittext,
viewHolder.originalPriceEdittext);
viewHolder.originalNumberTextWatcherWithSeperator.updatePosition(viewHolder.getAdapterPosition(),
viewHolder.originalPriceEdittext);
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle() != null) {
if (!TextUtils.isEmpty(managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle().trim())) {
String productName = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle().trim();
viewHolder.titleTextview.setText(productName);
} else {
viewHolder.titleTextview.setText("----");
}
} else {
viewHolder.titleTextview.setText("----");
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getPrice() != null) {
Long productPrice = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getPrice();
if (productPrice != null && productPrice != 0 && productPrice > 0) {
viewHolder.originalPriceEdittext.setText(String.valueOf(productPrice));
} else {
viewHolder.originalPriceEdittext.setText("");
}
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getDiscountedPrice() != null) {
Long discountPrice = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getDiscountedPrice();
if (discountPrice != null && discountPrice != 0 && discountPrice > 0) {
viewHolder.discountPriceEdittext.setText(String.valueOf(discountPrice));
} else {
viewHolder.discountPriceEdittext.setText("");
}
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
}
#Override
public int getItemCount() {
return managePriceProductsModelList.size();
}
public interface getListDiscountInterface {
void sendGetListDiscountToActivity(List<ManagePriceProductsModel.DataValue> managePriceProductsModelList);
void backButtonForListDiscount(List<ManagePriceProductsModel.DataValue> managePriceProductsModelList);
}
class ViewHolder extends RecyclerView.ViewHolder {
//region ViewBinding
#BindView(R.id.title_textview)
TextView titleTextview;
#BindView(R.id.original_price_edittext)
EditText originalPriceEdittext;
#BindView(R.id.discount_price_edittext)
EditText discountPriceEdittext;
DiscountNumberTextWatcherWithSeperator discountNumberTextWatcherWithSeperator;
OriginalNumberTextWatcherWithSeperator originalNumberTextWatcherWithSeperator;
//endregion
ViewHolder(View view,
DiscountNumberTextWatcherWithSeperator discountNumberTextWatcherWithSeperator,
OriginalNumberTextWatcherWithSeperator originalNumberTextWatcherWithSeperator) {
super(view);
ButterKnife.bind(this, itemView);
this.discountNumberTextWatcherWithSeperator = discountNumberTextWatcherWithSeperator;
this.discountPriceEdittext.addTextChangedListener(discountNumberTextWatcherWithSeperator);
this.originalNumberTextWatcherWithSeperator = originalNumberTextWatcherWithSeperator;
this.originalPriceEdittext.addTextChangedListener(originalNumberTextWatcherWithSeperator);
}
}
private class DiscountNumberTextWatcherWithSeperator implements TextWatcher {
private EditText discountEditText;
private EditText originalEditText;
private int position;
private String getDecimalFormattedString(String value) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
public void updatePosition(int position,
EditText discountEditText,
EditText originalEditText) {
this.position = position;
this.discountEditText = discountEditText;
this.originalEditText = originalEditText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (charSequence.length() > 0) {
originalEditText.setPaintFlags(originalEditText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(managePriceProductsModelList.get(position).getPrice());
dataValue.setDiscountedPrice(Long.parseLong(charSequence.toString().replace(",", "")));
managePriceProductsModelList.set(position, dataValue);
} else if (charSequence.length() == 0) {
originalEditText.setPaintFlags(originalEditText.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(managePriceProductsModelList.get(position).getPrice());
dataValue.setDiscountedPrice(null);
managePriceProductsModelList.set(position, dataValue);
}
}
#Override
public void afterTextChanged(Editable editable) {
try {
discountEditText.removeTextChangedListener(this);
String value = discountEditText.getText().toString();
if (!value.equals("")) {
if (value.startsWith(".")) {
discountEditText.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
discountEditText.setText("");
}
String str = discountEditText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
discountEditText.setText(getDecimalFormattedString(str));
discountEditText.setSelection(discountEditText.getText().toString().length());
}
discountEditText.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
discountEditText.addTextChangedListener(this);
}
}
}
private class OriginalNumberTextWatcherWithSeperator implements TextWatcher {
private EditText editText;
private int position;
private String getDecimalFormattedString(String value) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
public void updatePosition(int position,
EditText editText) {
this.position = position;
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (charSequence.length() > 0) {
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(Long.parseLong(charSequence.toString().replace(",", "")));
dataValue.setDiscountedPrice(managePriceProductsModelList.get(position).getDiscountedPrice());
managePriceProductsModelList.set(position, dataValue);
} else if (charSequence.length() == 0) {
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(null);
dataValue.setDiscountedPrice(managePriceProductsModelList.get(position).getDiscountedPrice());
managePriceProductsModelList.set(position, dataValue);
}
}
#Override
public void afterTextChanged(Editable editable) {
try {
editText.removeTextChangedListener(this);
String value = editText.getText().toString();
if (!value.equals("")) {
if (value.startsWith(".")) {
editText.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
editText.setText("");
}
String str = editText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
editText.setText(getDecimalFormattedString(str));
editText.setSelection(editText.getText().toString().length());
}
editText.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
editText.addTextChangedListener(this);
}
}
}
}
As the comments above it is not recommended to use edittext in recyclerview.
If you have to do this can you try to use
viewHolder.setIsRecyclable(false);
in your onBindViewHolder method
You can use this library to support this
Create a ViewState
new ViewState<>() {
private String savedValue; /* here will be saved a value for each item by createViewStateID() */
#Override
public void clear(#NonNull final ViewHolder<ViewFinder> holder) {
holder.getViewFinder().setText(R.id.text, "");
}
#Override
public void save(#NonNull final ViewHolder<ViewFinder> holder) {
savedValue = holder.getViewFinder().<EditText>find(R.id.text).getText().toString();
}
#Override
public void restore(#NonNull final ViewHolder<ViewFinder> holder) {
holder.getViewFinder().setText(R.id.text, savedValue);
}
};
Set that ViewState to your ViewRenderer
adapter.registerRenderer(new ViewRenderer<>(
R.layout.your_item_layout, //your layout
YourItemModel.class, //your model
(model, finder, payloads) -> finder.setText(R.id.text, model.getValue()), //your binding
getYourViewStateProvider() // here is your ViewState
));
More info you can find here
You can use the code below to keep hold of your dynamic values.
Paste this code inside your adapter. This allows to assign a unique id to your items. Just make sure the id assigned to all the items in the recyclerview must be unique.
override fun getItemViewType(position: Int) = position
override fun getItemId(position: Int) = position.toLong()
I develop an Android app which interacts with Google Firebase Cloud Firestore. To get data from Firestore, I use addOnCompleteListener with DocumentSnapshot.toObject() method. However, method toObject() seems not to work properly because it doesn't transmit data from snapshot to object.
Goal.class
#Entity
public class Goal {
// private variables
#PrimaryKey (autoGenerate = true)
private int id;
private String remoteId;
private int goalPos;
private String goalName;
private int goalCategory;
private String goalDescription;
private int goalColor;
private int goalFrequency;
private long goalFrequencyCode;
private boolean goalRewardType;
private double goalReward;
private int activated;
private boolean isSynced;
// constructor
public Goal() {
remoteId = "";
goalPos = 0;
goalName = "";
goalCategory = 15;
goalDescription = "";
goalColor = R.color.cat_Black;
goalFrequency = 0; // 0=Daily, 1=Weekly, 2=Monthly
goalFrequencyCode = 1111111111; // 1111111.111 - Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday; first of month, middle of month, last of month
goalRewardType = false; // false = standard, true = individual
activated = 1; // 0=No, 1=Yes
isSynced = false;
}
// getter and setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRemoteId() {
return remoteId;
}
public void setRemoteId(String remoteId) {
this.remoteId = remoteId;
}
public int getGoalPos() {
return goalPos;
}
public void setGoalPos(int goalPos) {
this.goalPos = goalPos;
}
public String getGoalName() {
return goalName;
}
public void setGoalName(String goalName) {
this.goalName = goalName;
}
public int getGoalCategory() {
return goalCategory;
}
public void setGoalCategory(int goalCategory) {
this.goalCategory = goalCategory;
}
public String getGoalDescription() {
return goalDescription;
}
public void setGoalDescription(String goalDescription) {
this.goalDescription = goalDescription;
}
public int getGoalColor() {
return goalColor;
}
public void setGoalColor(int goalColor) {
this.goalColor = goalColor;
}
public int getGoalFrequency() {
return goalFrequency;
}
public void setGoalFrequency(int goalFrequency) {
this.goalFrequency = goalFrequency;
}
public long getGoalFrequencyCode() {
return goalFrequencyCode;
}
public void setGoalFrequencyCode(long goalFrequencyCode) {
this.goalFrequencyCode = goalFrequencyCode;
}
public LinkedList<Integer> getGoalFrequencyCodeAsList() {
LinkedList<Integer> stack = new LinkedList<>();
long number = goalFrequencyCode;
while (number > 0) {
long longTempMod = number % 10;
int intTempMod = (int) longTempMod;
stack.push(intTempMod);
number = number / 10;
}
return stack;
}
public void setGoalFrequencyCodeFromList(LinkedList<Integer> stack) {
double number = 0;
for (int j = 0; j < stack.size(); j++) {
Log.d(String.valueOf(j), String.valueOf(stack.get(j)));
}
if (stack.size() <= 1) {
goalFrequencyCode = 1111111111;
} else {
for (int i = 0; i < stack.size(); i++) {
Log.d(String.valueOf(stack.get(i)), String.valueOf(number));
number = number + (stack.get(i) * Math.pow(10, (stack.size() - 1 - i)));
}
Log.d("Sent from Goal - number", String.valueOf(number));
goalFrequencyCode = (long) number;
Log.d("Sent from Goal - long", String.valueOf(goalFrequencyCode));
}
}
public boolean getGoalRewardType() {
return goalRewardType;
}
public void setGoalRewardType(boolean goalRewardType) {
this.goalRewardType = goalRewardType;
}
public double getGoalReward() {
return goalReward;
}
public void setGoalReward(double goalReward) {
this.goalReward = goalReward;
}
public int getActivated() {
return activated;
}
public void setActivated(int activated) {
this.activated = activated;
}
public boolean getIsSynced() {
return isSynced;
}
public void setIsSynced(boolean isSynced) {
this.isSynced = isSynced;
}
#Override
public String toString() {
return "Goal{" +
"id=" + id +
", remoteId='" + remoteId + '\'' +
", goalPos=" + goalPos +
", goalName='" + goalName + '\'' +
", goalCategory=" + goalCategory +
", goalDescription='" + goalDescription + '\'' +
", goalColor=" + goalColor +
", goalFrequency=" + goalFrequency +
", goalFrequencyCode=" + goalFrequencyCode +
", goalRewardType=" + goalRewardType +
", goalReward=" + goalReward +
", activated=" + activated +
", isSynced=" + isSynced +
'}';
}
}
FirebaseService.class
public LiveData<ApiResponse<List<Goal>>> getGoals() {
final MutableLiveData<ApiResponse<List<Goal>>> list = new MutableLiveData<>();
if (mAuth.getCurrentUser() != null) {
userId = mAuth.getCurrentUser().getUid();
colRefGoals = firestore.collection(userId).document("data").collection("goals");
colRefGoals
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Goal> goalsList = new ArrayList<Goal>();
for (DocumentSnapshot documentSnapshot : task.getResult()) {
Log.d("firebaseService", "DocumentSnapshop.getData: " + documentSnapshot.getData());
Goal goal = documentSnapshot.toObject(Goal.class);
Log.d("firebaseService", "DocumentSnapshot.toObject(Goal.class): " + goal.toString());
goalsList.add(goal);
}
ApiResponse<List<Goal>> apiResponse = new ApiResponse<List<Goal>>(goalsList);
list.setValue(apiResponse);
}
}
});
} else {
Throwable error = new Throwable("No user logged in");
ApiResponse<List<Goal>> apiResponse = new ApiResponse<List<Goal>>(error);
list.setValue(apiResponse);
return list;
}
return list;
}
Following my debug log comparison between .getData and .toObject:
12-05 19:53:42.663 11470-11470/com.benjaminsommer.dailygoals D/firebaseService: DocumentSnapshop.getData: {goals={goalRewardType=true, remoteId=10L44s0EcvTTzGajzhidgoals, id=2, goalFrequencyCode=1001111111, activated=1, goalColor=-4365347, goalCategory=8, goalDescription=Description Test, goalReward=1, goalPos=1, goalFrequency=2, goalName=Test}}
12-05 19:53:42.663 11470-11470/com.benjaminsommer.dailygoals D/firebaseService: DocumentSnapshot.toObject(Goal.class): Goal{id=0, remoteId='', goalPos=0, goalName='', goalCategory=15, goalDescription='', goalColor=2131558437, goalFrequency=0, goalFrequencyCode=1111111111, goalRewardType=false, goalReward=0.0, activated=1, isSynced=false}
.toObject doesn't transform the datasnapshot to my class. I already checked the documentation:
Important: Each custom class must have a public constructor that takes
no arguments. In addition, the class must include a public getter for
each property.
I have a constructor with no args and public getters for each property. I tried it with an empty constructor, but not working either. Is anything wrong with my getters? I use it in combination with Room, maybe there can be an issue?
Really appreciate your help and support.
Thanks, Ben
I am trying to make an android app for RFID card reader (i am not using NFC), for this i connect one high frquency RFID card reader through OTG cable and i am using EditText where card number is displaying. it is working fine, but problem is sometime it detects multiple time card number.
1- Any idea how can i resolve this (i cannot put size limit condition because card number length is not fixed)?
2- One more problem when i am using ultra high frequency card reader then card is showing different value, any idea how can i make an android app which supports both frequency card readers.
Rfid continue reading tag its not one time reading so from this repetition you have to manage to your side. Check its reading data or not if yes then ignore.Below the call Where implement Rfid methods and its reading data handle.
public class ReaderListener implements RfidEventListener {
private RfidReader reader;
private ReadInventory eventForm;
//private ItemTransfer eventFormitm;
private final ToneGenerator tg = new ToneGenerator(5, 100);
private boolean isEnabled;
private Map<String, Long> scannedItemsMap = new TreeMap<String, Long>();
public ReaderListener(ReadInventory frm, String make, String macid) throws ReaderConnectionException, LicenseExpiryException, IOException, GeneralSecurityException {
Log.d("Test1", " "+make.toString().trim()+" "+ macid.toString().trim());
reader = RfidFactory.getInstance().getRfidReader(make.toString().trim(), macid.toString().trim(),
PlatformConnector.AndroidConnector.getPlatformName());
Log.d("Test2", " "+reader+" ");
//reader.removeAllListeners();
reader.registerListener(this);
setEnabled(true);
this.eventForm = frm;
}
#Override
public void handleData(String tagid, int arg1, int arg2) {
synchronized (scannedItemsMap) {
if (!scannedItemsMap.containsKey(tagid)) {
System.out.println("got data............ :" + tagid);
scannedItemsMap.put(tagid, System.currentTimeMillis());
if (eventForm != null) {
eventForm.handleData(tagid);
//this.tg.startTone(25);
Log.d("tagid", " " + tagid + " ");
}
/*if (eventFormitm != null) {
eventFormitm.handleData(tagid);
}*/
} else if (scannedItemsMap.containsKey(tagid)) {
scannedItemsMap.put(tagid, System.currentTimeMillis());
}
}
}
#Override
public void handleError(String msg) {
if (eventForm != null) {
eventForm.handleError(msg);
}
}
#Override
public boolean isEnabled() {
return isEnabled;
}
#Override
public void setEnabled(boolean arg0) {
this.isEnabled = arg0;
}
public boolean startScan(int power,int speed) throws ReaderConnectionException {
if (reader != null && !reader.isScanning()) {
reader.setSession(RfidSession.ONE);
reader.setPower(power);
reader.setScanSpeed(speed);
reader.startScan();
}
return true;
}
public void stopScan() throws ReaderConnectionException {
if (reader.isScanning())
reader.stopScan();
}
public boolean isScanning() {
return reader.isScanning();
}
public boolean isConnected() {
return reader.isConnected();
}
public void removeAll() {
scannedItemsMap.clear();
}
public void remove(String tagid) {
scannedItemsMap.remove(tagid);
}
public int getBatteryLevel(){
try {
return reader.getBatteryLevel();
}catch (Exception e){
return 0;
}
}
#Override
public void handleReaderEvent(ReaderEvent arg0) {
// TODO Auto-generated method stub
}
}
Now Handle The data in activity ....
Show in below method.
public void handleData(final String tagid) {
// TODO Auto-generated method stub
try {
final String Code_samplecode = convertHexToString(tagid);
// Log.e("Name", "Itemcode" + Code_samplecode);
if (SampleCode.contains(Code_samplecode)&& !p_SampleCode.contains(Code_samplecode)) {
// Scann items count
tgf.startTone(25);
int ind_val = SampleCode.indexOf(Code_samplecode);
if (ind_val != -1) {
final String SampleNo1 = SampleNo.get(ind_val);
final String StyleNo1 = StyleNo.get(ind_val);
final String SampleCode1 = SampleCode.get(ind_val);
final String StyleCode1 = StyleCode.get(ind_val);
//final String CartStyleCode1 = CartStyleCode.get(ind_val);
// final String CartStyleNo1 = CartStyleNo.get(ind_val);
SampleNo.remove(ind_val);
StyleNo.remove(ind_val);
SampleCode.remove(ind_val);
StyleCode.remove(ind_val);
runOnUiThread(new Runnable() {
#Override
public void run() {
// p_Code.add(Code.get(ind_val));
p_SampleNo.add(SampleNo1);
p_StyleNo.add(StyleNo1);
p_SampleCode.add(SampleCode1);
p_StyleCode.add(StyleCode1);
//Code.remove(ind_val);
// adapter3.notifyDataSetChanged();
// adapter1.notifyDataSetChanged();
total_item.setAdapter(null);
adapter3 = new Adapter_for_Inventoryitem(ReadInventory.this,
StyleNo, SampleNo);
total_item.setAdapter(adapter3);
present_item.setAdapter(null);
adapter1 = new Adapter_for_Inventoryitem(ReadInventory.this,
p_StyleNo, p_SampleNo);
present_item.setAdapter(adapter1);
textvie.setText("Total " + p_SampleNo.size() + " Found Styles");
textvi.setText("Total " + SampleNo.size() + " Available Styles");
List<Inventory> c = db.get_all_data_INVENTARY_Query("SELECT * FROM Inventory_n WHERE SampleCode ='" + SampleCode1 + "'");
if (c.size() > 0) {
db.execute_query("INSERT INTO Inventory_p (Code, SampleNo,StyleNo,SampleCode,StyleCode,CartStyleNo,CartStyleCode) VALUES ('" + c.get(0).getCode() + "' , \"" +
c.get(0).getSampleNo() + "\" , \"" + c.get(0).getStyleNo() + "\" , '" +
c.get(0).getSampleCode() + "' , '" + c.get(0).getStyleCode() + "' , \"" +
c.get(0).getCartStyleNo() + "\" , '" + c.get(0).getCartStyleCode() + "')");
}
db.execute_query("DELETE FROM Inventory_n WHERE SampleCode ='" + SampleCode1 + "'");
}
});
}
} else {
if (!SampleCode.contains(Code_samplecode) && !p_SampleCode.contains(Code_samplecode)
&& !not_fount_items.contains(Code_samplecode)) {
tgn.startTone(20);
scanneditems_unkown = scanneditems_unkown + 1;
runOnUiThread(new Runnable() {
#Override
public void run() {
not_fount_items.add(Code_samplecode);
not_fount_items_txt.setText("Total " + not_fount_items.size() + " Unknown Styles");
}
});
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
scan_counts.setText("Total " + p_SampleNo.size() + " Scanned");
scan_counts_unknown.setText("Total " + scanneditems_unkown + " Unknown");
last_scanned_items.setText("Item : " + Code_samplecode);
}
});
} catch (Exception e) {
e.printStackTrace();
Message message = new Message();
message.what = READEREXCEPTION;
itemDetectedHandler.sendMessage(message);
}
}
You need to Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
//To get the characters (One By one)
event.getDisplayLabel();
}
And use Debounce (I'll recommend using RX Java) if the card numbers are of different length.
What debounce does is, it will wait for a particular amount of time after a keyevent happens, So you can concat the whole string and then use it.
I want to swipe between questions with viewpager
1) I'm able to use custom pages like ("text1", "text2", "text3, "text4") with this code:
in pageadapter:
protected static final String[] CONTENT = new String[] { "text1", "text2", "text3, "text4", };
1) But I couldnt get data from database to String like:
new String[] { "myquestion1", "myquestion2", ....... "my lastquestion", }
in my quiz activity:
/**
*
*/
public void initView() {
this.manageView(true);
}
/**
* updates the user interface
*
* #param start whether this is the start of the quiz
*/
#SuppressWarnings("boxing")
public void manageView(final boolean start) {
if (QuizActivity.ll.getChildCount() > 0) {
QuizActivity.ll.removeAllViews();
QuizActivity.ll.addView(QuizActivity.questionText);
}
QuizActivity.warning.setVisibility(View.INVISIBLE);
QuizActivity.warningIcon.setVisibility(View.INVISIBLE);
if (this.q.isReviewing()) {
QuizActivity.warning.setVisibility(View.VISIBLE);
QuizActivity.warningIcon.setVisibility(View.VISIBLE);
if (this.q.getCurrentQuestion().isAnsweredCorrect()) {
QuizActivity.warning.setText(R.string.correct);
QuizActivity.warning.setTextColor(Statics.goodColor);
QuizActivity.warningIcon.setImageResource(R.drawable.correct);
} else {
QuizActivity.warning.setText(R.string.wrong);
QuizActivity.warning.setTextColor(Statics.badColor);
QuizActivity.warningIcon.setImageResource(R.drawable.wrong);
}
}
QuizActivity.back.setEnabled((!start || this.q.isBackAllowed())
&& (!this.q.isFirstQuestion()));
if (this.q.isLastQuestion()) {
QuizActivity.next.setText(R.string.finish);
QuizActivity.next.setCompoundDrawablesWithIntrinsicBounds(null, null,
this.getResources().getDrawable(R.drawable.finish_quiz), null);
} else {
QuizActivity.next.setText(R.string.next);
QuizActivity.next.setCompoundDrawablesWithIntrinsicBounds(null, null,
this.getResources().getDrawable(R.drawable.arrow_right), null);
}
QuizActivity.review.setChecked(this.q.getCurrentQuestion().isMarkedForReview());
if (this.q.isReviewing()) {
QuizActivity.review.setVisibility(View.GONE);
if ((null != this.q.getCurrentQuestion().getExplanation())
&& (this.q.getCurrentQuestion().getExplanation().length() > 0)) {
QuizActivity.explain.setVisibility(View.VISIBLE);
} else {
QuizActivity.explain.setVisibility(View.GONE);
}
}
QuizActivity.progress.setText(this.getString(R.string.q_) + " "
+ this.q.getCurrentQuestionNumber() + "/"
+ this.q.getQuestionCount());
QuizActivity.title.setText(this.q.getCategory().getParentCategoryTitle() + " - "
+ this.q.getCategory().getCategoryTitle());
QuizActivity.questionText.setText(this.q.getCurrentQuestion().getQuestionText());
if (this.q.isShowAmountAnswers()) {
QuizActivity.questionText.append(" (" + this.getString(R.string.select) +
" " + this.q.getCurrentQuestion().getAmountCorrectAnswers() + ")");
}
this.userAnswers = this.q.getCurrentQuestion().getUserAnswers();
this.answers = new LinkedList<CompoundButton>();
if (!this.q.isShowAmountAnswers()
|| (this.q.getCurrentQuestion().getAmountCorrectAnswers() > 1)) {
for (final Answer ans : this.q.getCurrentQuestion().getAnswers()) {
this.answers.add(new CheckBox(this));
this.answers.getLast().setText(ans.getAnswerText());
this.answers.getLast().setId(ans.getAnswerId());
this.answers.getLast().setChecked(this.userAnswers.get(ans.getAnswerId()));
if (this.q.isReviewing()) {
this.answers.getLast().setEnabled(false);
if (ans.isAnswerCorrect()) {
this.answers.getLast().setTextColor(Statics
.goodColor);
} else {
this.answers.getLast().setTextColor(Statics
.badColor);
}
}
QuizActivity.ll.addView(this.answers.getLast());
}
} else {
final RadioGroup rg = new RadioGroup(this);
for (final Answer ans : this.q.getCurrentQuestion().getAnswers()) {
this.answers.add(new RadioButton(this));
this.answers.getLast().setText(ans.getAnswerText());
this.answers.getLast().setId(ans.getAnswerId());
this.answers.getLast().setChecked(this.userAnswers.get(ans.getAnswerId()));
if (this.q.isReviewing()) {
this.answers.getLast().setEnabled(false);
if (ans.isAnswerCorrect()) {
this.answers.getLast().setTextColor(Statics
.goodColor);
} else {
this.answers.getLast().setTextColor(Statics
.badColor);
}
}
this.answers.getLast()
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#SuppressWarnings("synthetic-access")
#Override
public void onCheckedChanged(final CompoundButton buttonView,
final boolean isChecked) {
for (final View rb : QuizActivity.this.answers)
{
((CompoundButton) rb).setChecked(false);
}
buttonView.setChecked(isChecked);
}
});
rg.addView(this.answers.getLast());
}
QuizActivity.ll.addView(rg);
}
QuizActivity.next.setOnClickListener(this);
QuizActivity.back.setOnClickListener(this);
QuizActivity.explain.setOnClickListener(this);
}
so how can I apply my question list to " new String[] {...,...,... } "