issue in change row in recyclerview - java

I am working on a shopping Android app, I have a CartActivity. In my CartActivity I put RecyclerView and each row in this RecyclerView have 2 buttons, one (+) button to increase the quantity for this item in the cart and other (-) button to delete 1 from the quantity of this item in the row.
Now when I have a single item in my cart, everything is ok. but when I have multi-item in cart (multi-row in RV) I have the issue which is: When I press (+) or (-) button on any item in RecyclerView the effect of quantity changing shown on the last item in this list (last row) and there is no changing on my selected row!
this is my adapter code:
package com.example.souqsenae.adapters;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.souqsenae.API_Utility.IApi;
import com.example.souqsenae.API_Utility.RetrofitBuilder;
import com.example.souqsenae.R;
import com.example.souqsenae.activities.cartActivity;
import com.example.souqsenae.models.AddToCart;
import com.example.souqsenae.models.CartInfo;
import com.example.souqsenae.models.Parts;
import com.example.souqsenae.models.RemoveProduct;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class CartAdapter extends
RecyclerView.Adapter<CartAdapter.CartAdapterViewHolder> {
private Context context;
private ArrayList<CartInfo.Item> mItem;
private ItemOnClickHandler mItemOnClickHandler;
RetrofitBuilder rB = new RetrofitBuilder();
IApi service = rB.retrofit.create(IApi.class);
int totalQty =0; int subTotal = 0;
TextView tv1, tv4;
private static SharedPreferences pref;
String cookie;
public CartAdapter(ItemOnClickHandler cartAdapterOnClickHandler, Context _context) {
mItemOnClickHandler = cartAdapterOnClickHandler;
pref = _context.getSharedPreferences("log", Context.MODE_PRIVATE);
}
public void setProductsData(ArrayList<CartInfo.Item> item) {
mItem = item;
notifyDataSetChanged();
}
public void addAll(ArrayList<CartInfo.Item> newList) {
int lastIndex = getItemCount();
mItem.addAll(newList);
notifyItemRangeInserted(lastIndex, newList.size());
}
public void clear() {
int size = mItem.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
mItem.remove(0);
}
notifyItemRangeRemoved(0, size);
}
}
#Override
public CartAdapter.CartAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.row_cart, parent, false);
// Return a new holder instance
CartAdapterViewHolder viewHolder = new CartAdapterViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(CartAdapter.CartAdapterViewHolder viewHolder, int position) {
// viewHolder.iv.setAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_transition_animation));
viewHolder.container.setAnimation(AnimationUtils.loadAnimation(context,R.anim.fade_transition_animation));
final CartInfo.Item cartInfo = mItem.get(position);
tv1 = viewHolder.qty;
TextView tv2 = viewHolder.tvItemName;
TextView tv3 = viewHolder.tvItemDesc;
tv4 = viewHolder.tvSubTotal;
Button button = viewHolder.btnMin;
Button button1 = viewHolder.btnPlus;
totalQty = cartInfo.getQty();
tv1.setText(String.valueOf(totalQty));
tv2.setText(cartInfo.getName());
tv4.setText(String.valueOf(cartInfo.getSubtotal()));
cookie = pref.getString("cookie", "");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if((totalQty -1) >0){
totalQty = totalQty -1;
tv1.setText(String.valueOf(totalQty));
subTotal = totalQty * (cartInfo.getPrice());
tv4.setText(String.valueOf(subTotal));
}
if((totalQty - 1) == 0){
// remove from cart:
String row = cartInfo.getRowid();
String product_id = cartInfo.getId();
Call<RemoveProduct> call = service.updateCartQty( cookie,product_id,totalQty);
call.enqueue(new Callback<RemoveProduct>() {
#Override
public void onResponse(Call<RemoveProduct> call, Response<RemoveProduct> response) {
if(response.isSuccessful()){
notifyDataSetChanged();
Intent intent = new Intent(context, cartActivity.class);
context.startActivity(intent);
}
}
#Override
public void onFailure(Call<RemoveProduct> call, Throwable t) {
}
});
}
}
});
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int vendor = Integer.parseInt(cartInfo.getVendor());
int product_id = Integer.parseInt(cartInfo.getId());
Call<AddToCart> call = service.addToCart(cookie,product_id,vendor,1);
call.enqueue(new Callback<AddToCart>() {
#Override
public void onResponse(Call<AddToCart> call, Response<AddToCart> response) {
if(response.isSuccessful()){
totalQty = totalQty +1;
tv1.setText(String.valueOf(totalQty));
subTotal = totalQty * (cartInfo.getPrice());
tv4.setText(String.valueOf(subTotal));
}
}
#Override
public void onFailure(Call<AddToCart> call, Throwable t) {
}
});
}
});
}
// Returns the total count of items in the list
#Override
public int getItemCount() {
if(mItem == null) {
return 0;
}
return mItem.size();
}
public class CartAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final Button btnPlus;
public final Button btnMin;
public final TextView qty;
public final TextView tvItemName;
public final TextView tvItemDesc;
public final TextView tvSubTotal;
public final LinearLayout container;
public CartAdapterViewHolder(View view) {
super(view);
qty = (TextView) view.findViewById(R.id.partCount);
tvItemName = (TextView) view.findViewById(R.id.tv_item_name);
tvItemDesc = (TextView) view.findViewById(R.id.tv_item_description);
tvSubTotal = (TextView) view.findViewById(R.id.tvSubTotal);
btnMin = (Button) view.findViewById(R.id.btnMin);
btnPlus = (Button) view.findViewById(R.id.btnPlus);
container = (LinearLayout) view.findViewById(R.id.layout_part_item);
view.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int position = getAdapterPosition();
CartInfo.Item selectedProduct = mItem.get(position);
mItemOnClickHandler.onClickItem(selectedProduct);
}
}
public interface ItemOnClickHandler {
void onClickItem(CartInfo.Item cartInfo);
}
}
I don't know what the wrong :(
Thanks

Better to use interface to perform click operations.
Whenever button clicked, update the quantity for a specific item and call adapter.notifyDataSetChanged();.

You have to made change for quantity in your model when click + or - button. So you have to add cartInfo.setQty(totalQty); inside your button clicks
Don't use global variables if you are using variable inside onBind()
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if((totalQty -1) >0){
cartInfo.setQty(cartInfo.getQty() -1);
tv1.setText(String.valueOf(cartInfo.getQty()));
tv4.setText(String.valueOf(cartInfo.getQty() * (cartInfo.getPrice())));
}
if((totalQty - 1) == 0){
// remove from cart:
String row = cartInfo.getRowid();
String product_id = cartInfo.getId();
mItem.remove(cartInfo);
Call<RemoveProduct> call = service.updateCartQty( cookie,product_id,totalQty);
call.enqueue(new Callback<RemoveProduct>() {
#Override
public void onResponse(Call<RemoveProduct> call, Response<RemoveProduct> response) {
if(response.isSuccessful()){
notifyDataSetChanged();
Intent intent = new Intent(context, cartActivity.class);
context.startActivity(intent);
}
}
#Override
public void onFailure(Call<RemoveProduct> call, Throwable t) {
}
});
notifyDataSetChanged();
}
}
});
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int vendor = Integer.parseInt(cartInfo.getVendor());
int product_id = Integer.parseInt(cartInfo.getId());
cartInfo.setQty(cartInfo.getQty()+1);
cartInfo.setQty(cartInfo.getQty()+1);
tv1.setText(String.valueOf(cartInfo.getQty()));
tv4.setText(String.valueOf(cartInfo.getQty() * (cartInfo.getPrice())));
Call<AddToCart> call = service.addToCart(cookie,product_id,vendor,1);
call.enqueue(new Callback<AddToCart>() {
#Override
public void onResponse(Call<AddToCart> call, Response<AddToCart> response) {
if(response.isSuccessful()){
}
}
#Override
public void onFailure(Call<AddToCart> call, Throwable t) {
}
});
}
});

Related

Why my recyclerview isn't showing any item?

I just created my recyclerview to show a cardview when I just filling the required data on AddNewTimerFragment.java. But somehow it wont show the card that contains the data that I've fill in before. I've tried to changes something, but doesn't work.
Code :
MainActivity.java
package com.mobprog.ius.dwasu;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.LinkedList;
public class MainActivity extends AppCompatActivity {
private ArrayList<MyListDataTimer> mintervalTimeList = new ArrayList();
private RecyclerView mRecyclerView;
private alarmListAdapter mAdapter;
public boolean isFragmentAddNewAlarmDisplayed = false;
static final String STATE_FRAGMENT = "state_of_fragment";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((TextView) findViewById(R.id.textUserName)).setText("Hello " + getSharedPreferences("Dwasu", 0).getString("user", ""));
if (getSharedPreferences("Dwasu", 0) == null || !getSharedPreferences("Dwasu", 0).contains("user")) {
startActivity(new Intent(MainActivity.this, LoginActivity.class));
finish();
}
// Create recycler view.
mRecyclerView = findViewById(R.id.recyclerView);
// Create an adapter and supply the data to be displayed.
mAdapter = new alarmListAdapter(getApplicationContext(), mintervalTimeList);
// Connect the adapter with the recycler view.
mRecyclerView.setAdapter(mAdapter);
// Give the recycler view a default layout manager.
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
if (savedInstanceState != null)
isFragmentAddNewAlarmDisplayed = savedInstanceState.getBoolean(STATE_FRAGMENT);
Button mnewReminderButton = findViewById(R.id.newReminder);
mnewReminderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(MainActivity.class.getSimpleName(),"Button Clicked");
displayFragment();
}
});
ImageButton mlogOutButton = findViewById(R.id.logOutButton);
findViewById(R.id.logOutButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSharedPreferences("Dwasu", 0).edit().clear().apply();
startActivity(new Intent(MainActivity.this, MainActivity.class));
finish();
}
});
// // Get the Drawable custom_progressbar
// Drawable draw = ResourcesCompat.getDrawable(getResources(), R.drawable.progress_bar, null);
// // set the drawable as progress drawable
// ProgressBar.setProgressDrawable(draw);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the state of the fragment (true=open, false=closed).
savedInstanceState.putBoolean(STATE_FRAGMENT, isFragmentAddNewAlarmDisplayed);
super.onSaveInstanceState(savedInstanceState);
}
public void closeFragment(){
// Get the FragmentManager.
FragmentManager fragmentManager = getSupportFragmentManager();
// Check to see if the fragment is already showing.
AddNewTimerFragment simpleFragment = (AddNewTimerFragment) fragmentManager
.findFragmentById(R.id.FragmentContainer_AddNewAlarm);
if (simpleFragment != null) {
// Create and commit the transaction to remove the fragment.
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.remove(simpleFragment).commit();
}
// Set boolean flag to indicate fragment is closed.
isFragmentAddNewAlarmDisplayed = false;
}
public void displayFragment(){
AddNewTimerFragment simpleFragment = AddNewTimerFragment.newInstance();
// Get the FragmentManager and start a transaction.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
// Add the SimpleFragment.
fragmentTransaction.add(R.id.FragmentContainer_AddNewAlarm,
simpleFragment).addToBackStack(null).commit();
// Set boolean flag to indicate fragment is open.
isFragmentAddNewAlarmDisplayed = true;
}
}
AddNewTimerFragment.java
package com.mobprog.ius.dwasu;
import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TimePicker;
import android.widget.Toast;
import org.apache.http.entity.mime.content.StringBody;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import static android.content.Context.MODE_PRIVATE;
public class AddNewTimerFragment extends Fragment {
Button startTime;
Button endTime;
Button meditConfirm_button;
int startHour;
int startMinute;
int endHour;
int endMinute;
int position = 1;
long totalSize = 0;
String value;
ProgressDialog progDailog;
View rootview;
private SharedPreferences mPreferences;
private String sharedPrefFile =
"com.mobprog.ius.dwasu";
public AddNewTimerFragment() {
// Required empty public constructor
}
public static AddNewTimerFragment newInstance() {
return new AddNewTimerFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_add_new_alarm,
container, false);
rootview = rootView;
/*Shared Pref*/
mPreferences = this.getActivity().getSharedPreferences(sharedPrefFile, MODE_PRIVATE);
SharedPreferences.Editor mPreferencesEditor = mPreferences.edit();
ImageButton mbtnCloseFragment = rootView.findViewById(R.id.btnCloseFragment);
mbtnCloseFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity) getActivity()).closeFragment();
}
});
// initiate the edit text
startTime = rootView.findViewById(R.id.startTimePick);
startTime.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
// perform click event listener on edit text
startTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
startHour = mcurrentTime.get(Calendar.HOUR);
startMinute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mStartTimePicker;
mStartTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int selectedStartHour, int selectedStartMinute) {
if (selectedStartMinute == 0) {
startTime.setText(selectedStartHour + ":00");
} else if (selectedStartMinute < 10) {
if (selectedStartHour < 10) {
startTime.setText("0" + selectedStartHour + ":0" + selectedStartMinute);
}
} else {
startTime.setText(selectedStartHour + ":" + selectedStartMinute);
}
startHour = selectedStartHour;
}
}, startHour, startMinute, true);//Yes 24 hour time
mStartTimePicker.show();
}
});
endTime = rootView.findViewById(R.id.endTimePick);
endTime.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
// perform click event listener on edit text
endTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
endHour = mcurrentTime.get(Calendar.HOUR);
endMinute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mEndTimePicker;
mEndTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int selectedEndHour, int selectedEndMinute) {
if (selectedEndMinute == 0) {
endTime.setText(selectedEndHour + ":00");
} else if (selectedEndMinute < 10) {
if (selectedEndHour < 10) {
endTime.setText("0" + selectedEndHour + ":0" + selectedEndMinute);
}
} else {
endTime.setText(selectedEndHour + ":" + selectedEndMinute);
}
endHour = selectedEndHour;
}
}, endHour, endMinute, true);//Yes 24 hour time
mEndTimePicker.show();
}
});
Spinner spinner = (Spinner) rootView.findViewById(R.id.timeIntervalPick);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.listtimer, R.layout.spinner_support);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(R.layout.spinner_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
// your code here
String[] valueListTimer = getResources().getStringArray(R.array.valueListTimer);
value = valueListTimer[position];
Log.e("Value of Spinner", value);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
meditConfirm_button = rootView.findViewById(R.id.editConfirm_button);
meditConfirm_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String.valueOf(startHour);
String.valueOf(endHour);
String.valueOf(value);
new MyListDataTimer(String.valueOf(startHour),String.valueOf(endHour),String.valueOf(value),String.valueOf(position));
new UploadAlarmDataToServer().execute();
position++;
}
});
// Inflate the layout for this fragment
return rootView;
}
private class UploadAlarmDataToServer extends AsyncTask<Void, Integer, String> {
#Override
protected void onPreExecute() {
progDailog = new ProgressDialog(getContext());
progDailog.setMessage("Menyimpan...");
progDailog.setIndeterminate(false);
progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDailog.setCancelable(false);
progDailog.setCanceledOnTouchOutside(false);
progDailog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
String data = null;
try {
data = sendDataTimer();
} catch (Exception e) {
e.printStackTrace();
data = "Gagal";
}
return data;
}
public String sendDataTimer() throws Exception {
URL url = new URL("https://ius.mobile.indoserver.web.id/alarmData.php");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
new AndroidMultiPartEntity.ProgressListener() {
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
entity.addPart("startHour", new StringBody(startHour + ""));
entity.addPart("endHour", new StringBody(endHour + ""));
entity.addPart("intervalWaktu", new StringBody(value + ""));
totalSize = entity.getContentLength();
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.addRequestProperty("Content-length", totalSize + "");
con.addRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
OutputStream os = con.getOutputStream();
entity.writeTo(con.getOutputStream());
os.close();
con.connect();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
#Override
protected void onPostExecute(String result) {
progDailog.dismiss();
if (result != null) {
Log.e("UPLOAD", result);
if (result.equalsIgnoreCase("OK")) {
Toast.makeText(getContext(), "Data Alarm tersimpan", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getContext(), MainActivity.class));
}
}
super.onPostExecute(result);
}
}
}
alarmListAdapter.java
package com.mobprog.ius.dwasu;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.LinkedList;
public class alarmListAdapter extends RecyclerView.Adapter<alarmListAdapter.alarmListHolder>{
private final ArrayList<MyListDataTimer> mintervalTimeList;
private LayoutInflater mInflater;
public alarmListAdapter(Context context, ArrayList<MyListDataTimer> mintervalTimeList) {
mInflater = LayoutInflater.from(context);
this.mintervalTimeList = mintervalTimeList;
}
#Override
public alarmListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mItemView = mInflater.inflate(R.layout.alarm_item,
parent, false);
return new alarmListHolder(mItemView, this);
}
#Override
public void onBindViewHolder(alarmListAdapter.alarmListHolder holder, int position) {
final MyListDataTimer myListData = mintervalTimeList.get(position);
holder.mintervalTime.setText(myListData.getIntervalWaktu());
holder.mtimeWork.setText(myListData.getStartHour() +":00 - " + myListData.getEndHour() +":00");
}
#Override
public int getItemCount() {
return mintervalTimeList.size();
}
public class alarmListHolder extends RecyclerView.ViewHolder {
public TextView mintervalTime;
public TextView mtimeWork;
final alarmListAdapter mAdapter;
public alarmListHolder(View itemView, alarmListAdapter adapter) {
super(itemView);
mintervalTime = itemView.findViewById(R.id.intervalTime);
mtimeWork = itemView.findViewById(R.id.timeWork);
this.mAdapter = adapter;
}
}
}
**MyListDataTimer.java**
package com.mobprog.ius.dwasu;
public class MyListDataTimer {
private String startHour;
private String endHour;
private String intervalWaktu;
private String position;
public MyListDataTimer(String startHour, String endHour, String intervalWaktu, String position) {
this.startHour = startHour;
this.endHour = endHour;
this.intervalWaktu = intervalWaktu;
this.position = position;
}
public String getStartHour() {
return startHour;
}
public void setStartHour(String startHour) {
this.startHour = startHour;
}
public String getEndHour() {
return endHour;
}
public void setEndHour(String endHour) {
this.endHour = endHour;
}
public String getIntervalWaktu() {
return intervalWaktu;
}
public void setIntervalWaktu(String intervalWaktu) {
this.intervalWaktu = intervalWaktu;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}

Button inside RecyclerView

I have a problem with my android app.
I have a RecyclerView and a click handler for it. When you click on a list item, one of the class fields is displayed on the screen. Also inside there is a button, by clicking on which another class field should be displayed. But the program throws a NullPointerException. I understand why this is happening, but I cannot understand how to modify my code, please help.
here is my Adapeter
package com.skorbr.stock_yandextest;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class TickerAdapter extends RecyclerView.Adapter<TickerAdapter.TickerViewHolder> {
private List<Ticker> tickers;
private Context context;
// listener
private final Listener onTickerClickListener;
// constructor
public TickerAdapter(List<Ticker> tickers, Listener onTickerClickListener) {
this.tickers = tickers;
this.onTickerClickListener = onTickerClickListener;
}
#NonNull
#Override
public TickerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View view = LayoutInflater.from(context).inflate(R.layout.recycler_stock_item, parent, false);
// click on RecyclerView
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onTickerClickListener.onTickerClick((Ticker) v.getTag());
}
});
// click on button
view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
}
});
return new TickerViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TickerViewHolder holder, int position) {
Ticker ticker = tickers.get(position);
holder.bind(ticker);
holder.itemView.setTag(ticker);
}
#Override
public int getItemCount() {
return tickers.size();
}
class TickerViewHolder extends RecyclerView.ViewHolder {
private TextView ticker;
private TextView tickerFull;
private TextView price;
private TextView priceChange;
private ImageView tickerLogo;
private Button favouriteButton;
public TickerViewHolder(#NonNull final View itemView) {
super(itemView);
ticker = itemView.findViewById(R.id.ticker);
tickerFull = itemView.findViewById(R.id.ticker_full);
price = itemView.findViewById(R.id.price);
priceChange = itemView.findViewById(R.id.price_change);
tickerLogo = itemView.findViewById(R.id.ticker_image);
favouriteButton = itemView.findViewById(R.id.button_favourite);
}
// заполнение элемента RecyclerView данными
void bind(Ticker ticker) {
double priceNow = ticker.getPrice();
double priceDayAgo = ticker.getPriceDayAgo();
String sign = "";
this.ticker.setText(ticker.getTicker());
this.tickerFull.setText(ticker.getTickerFull());
this.price.setText("$" + priceNow);
// check price
if (priceNow < priceDayAgo) {
sign = "-";
this.priceChange.setTextColor(context.getResources().getColor(R.color.colorRedDm));
} else if (priceNow > priceDayAgo) {
sign = "+";
this.priceChange.setTextColor(context.getResources().getColor(R.color.colorGreenDm));
}
// check favourites
if (ticker.isFavourite()) {
this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_on));
} else {
this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_off));
}
this.priceChange.setText(String.format("%s$%.2f (%.2f%%)", sign, Math.abs(priceNow-priceDayAgo), Math.abs(priceNow/priceDayAgo*100-100)));
this.tickerLogo.setImageResource(ticker.getTickerLogo());
}
}
interface Listener {
void onTickerClick(Ticker ticker);
void onFavouriteClick(Ticker ticker);
}
}
Here is my Main Activity
package com.skorbr.stock_yandextest;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class ActivityMain extends Activity {
private RecyclerView tickerList;
private TickerAdapter tickerAdapter;
private List<Ticker> tickerListList;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tickerListList = tickerList();
tickerList = findViewById(R.id.tickers_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
tickerList.setLayoutManager(layoutManager);
tickerAdapter = new TickerAdapter(tickerListList, new TickerAdapter.Listener() {
#Override
public void onTickerClick(Ticker ticker) {
Toast.makeText(ActivityMain.this, ticker.getTickerFull(), Toast.LENGTH_SHORT);
}
#Override
public void onFavouriteClick(Ticker ticker) {
Toast.makeText(ActivityMain.this, ticker.getTicker(), Toast.LENGTH_SHORT);
}
});
tickerList.setAdapter(tickerAdapter);
}
private List<Ticker> tickerList() {
List<Ticker> tickers = new ArrayList<>();
tickers.add(new Ticker("APPL", "Apple Inc.", 138.54, 150.22, R.drawable.apple_logo, false));
tickers.add(new Ticker("TSLA", "Tesla Motors", 904.37, 753.92, R.drawable.tesla_logo, true));
tickers.add(new Ticker("GOOGL", "Alphabel Class A", 1845.90, 1845.90, R.drawable.google_logo, false));
return tickers;
}
}
Here is my class for data
package com.skorbr.stock_yandextest;
public class Ticker {
private String ticker;
private String tickerFull;
private double price;
private double priceDayAgo;
private int tickerLogo;
private boolean isFavourite;
public Ticker(String ticker, String tickerFull, double price, double priceDayAgo, int tickerLogo, boolean isFavourite) {
this.ticker = ticker;
this.tickerFull = tickerFull;
this.price = price;
this.priceDayAgo = priceDayAgo;
this.tickerLogo = tickerLogo;
this.isFavourite = isFavourite;
}
public String getTicker() {
return ticker;
}
public String getTickerFull() {
return tickerFull;
}
public double getPrice() {
return price;
}
public double getPriceDayAgo() {
return priceDayAgo;
}
public int getTickerLogo() {
return tickerLogo;
}
public boolean isFavourite() {
return isFavourite;
}
public void setFavourite(boolean favourite) {
isFavourite = favourite;
}
}
#Override
public void onBindViewHolder(#NonNull TickerViewHolder holder, int position) {
Ticker ticker = tickers.get(position);
holder.bind(ticker);
holder.itemView.setTag(ticker);
// add this line
holder.favouriteButton.setTag(ticker);
}
Or you can modify the onCreateViewHolder()
view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// instead of
onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
// use
onTickerClickListener.onFavouriteClick((Ticker) view.getTag());
}
});

How to read a specific value from each of the node in firebase?

I want to display a bunch of custom markers(IconGenerator from com.google.maps.android:android-maps-utils:0.5) in a google map. But the data to build the markers, the LatLong location are in a firebase database, each child has its own location values, how can I read the location of each child and pass it to the class that will display the markers?
package com.realty.drake.kunuk;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Keep;
import com.google.android.gms.maps.model.LatLng;
/**
* Created by drake on 5/1/18.
* This class is the model class
*/
#Keep
public class Property implements Parcelable {
private int price;
private String address;
private int numberOfBed;
private int numberOfBath;
private int numberOfCar;
private String propertyImage;
private float lotDim;
private String propertyDesc;
private float propertyDim;
private String lotTerrainType;
private String lotTerrainDimExt;
private String lotTerrainSteepness;
private LatLng location;
public Property() { } //Needed for Firebase's auto data mapping
public Property(int price, String address, int numberOfBed, int numberOfBath,
int numberOfCar, String propertyImage, float lotDim,
String propertyDesc, float propertyDim, String lotTerrainType,
String lotTerrainDimExt, String lotTerrainSteepness,
LatLng location) {
this.price = price;
this.address = address;
this.numberOfBed = numberOfBed;
this.numberOfBath = numberOfBath;
this.numberOfCar = numberOfCar;
this.propertyImage = propertyImage;
this.lotDim = lotDim;
this.propertyDesc = propertyDesc;
this.propertyDim = propertyDim;
this.lotTerrainType = lotTerrainType;
this.lotTerrainDimExt = lotTerrainDimExt;
this.lotTerrainSteepness = lotTerrainSteepness;
this.location = location;
}
protected Property(Parcel in) {
price = in.readInt();
address = in.readString();
numberOfBed=in.readInt();
numberOfBath = in.readInt();
numberOfCar = in.readInt();
propertyImage = in.readString();
lotDim = in.readFloat();
propertyDesc = in.readString();
propertyDim = in.readFloat();
lotTerrainType = in.readString();
lotTerrainDimExt = in.readString();
lotTerrainSteepness = in.readString();
location = in.readParcelable(getClass().getClassLoader());
}
public static final Creator<Property> CREATOR = new Creator<Property>() {
#Override
public Property createFromParcel(Parcel in) {
return new Property(in);
}
#Override
public Property[] newArray(int i) {
return new Property[i];
}
};
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getNumberOfBed() {
return numberOfBed;
}
public void setNumberOfBed(int numberOfBed) {
this.numberOfBed = numberOfBed;
}
public int getNumberOfBath() {
return numberOfBath;
}
public void setNumberOfBath(int numberOfBath) {
this.numberOfBath = numberOfBath;
}
public int getNumberOfCar() {
return numberOfCar;
}
public void setNumberOfCar(int numberOfCar) {
this.numberOfCar = numberOfCar;
}
public String getPropertyImage() {
return propertyImage;
}
public void setPropertyImage(String propertyImage) {
this.propertyImage = propertyImage;
}
public float getLotDim() {
return lotDim;
}
public void setLotDim(float lotDim) {
this.lotDim = lotDim;
}
public String getPropertyDesc() {
return propertyDesc;
}
public void setPropertyDesc(String propertyDesc) {
this.propertyDesc = propertyDesc;
}
public float getPropertyDim() {
return propertyDim;
}
public void setPropertyDim(float propertyDim) {
this.propertyDim = propertyDim;
}
public String getLotTerrainType() {
return lotTerrainType;
}
public void setLotTerrainType(String lotTerrainType) {
this.lotTerrainType = lotTerrainType;
}
public String getLotTerrainDimExt() {
return lotTerrainDimExt;
}
public void setLotTerrainDimExt(String lotTerrainDimExt) {
this.lotTerrainDimExt = lotTerrainDimExt;
}
public String getLotTerrainSteepness() {
return lotTerrainSteepness;
}
public void setLotTerrainSteepness(String lotTerrainSteepness) {
this.lotTerrainSteepness = lotTerrainSteepness;
}
public LatLng getLocation() {
return location;
}
public void setLocation(LatLng location) {
this.location = location;
}
#Override
public int describeContents(){
return 0;
}
#Override
public void writeToParcel( Parcel dest, int flags){
dest.writeInt(price);
dest.writeString(address);
dest.writeInt(numberOfBed);
dest.writeInt(numberOfBath);
dest.writeInt(numberOfCar);
dest.writeString(propertyImage);
dest.writeFloat(lotDim);
dest.writeString(propertyDesc);
dest.writeFloat(propertyDim);
dest.writeString(lotTerrainType);
dest.writeString(lotTerrainDimExt);
dest.writeString(lotTerrainSteepness);
dest.writeParcelable(location,flags);
}
}
The Fragment that use the model class, it takes data from firebase database, and also has anintent to a detailed view
package com.realty.drake.kunuk;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.CircularProgressDrawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.text.NumberFormat;
import java.util.Locale;
/**
* Created by drake on 4/11/18
*/
public class Tab1Buy extends Fragment {
private DatabaseReference propertyRef;
private RecyclerView mPropertyRecyclerView;
FirebaseRecyclerAdapter<Property, PropertyViewHolder> mPropertyAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.property_tab, container, false);
mPropertyRecyclerView = rootView.findViewById(R.id.property_recyclerView);
return rootView;
}
//TODO Check internet and display error msg if internet down
#Override
public void onViewCreated(final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mPropertyRecyclerView.hasFixedSize();
mPropertyRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
final ProgressBar progressBar = view.findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
propertyRef = FirebaseDatabase.getInstance()
.getReference()
.child("Buy");
propertyRef.keepSynced(true);
// keyQuery - the Firebase location containing the list of keys to be found in dataRef
//Query personQuery = propertyRef.orderByKey();
FirebaseRecyclerOptions<Property> options =
new FirebaseRecyclerOptions.Builder<Property>()
.setQuery(propertyRef, Property.class)
.build();
mPropertyAdapter = new FirebaseRecyclerAdapter<Property, PropertyViewHolder>(options) {
#Override
// Bind the Property object to the ViewHolder PropertyHolder
public void onBindViewHolder(#NonNull PropertyViewHolder holder,
final int position, #NonNull final Property model) {
holder.setPrice(model.getPrice());
holder.setAddress(model.getAddress());
holder.setNumberOfBed(model.getNumberOfBed());
holder.setNumberOfBath(model.getNumberOfBath());
holder.setNumberOfCar(model.getNumberOfCar());
holder.setPropertyImage(model.getPropertyImage());
//This Intent send Parcelable from Property to PropertyDetail
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().startActivity(new Intent(getActivity(), PropertyDetail.class)
.putExtra("Property", model));
}
});
}
#Override
public PropertyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new instance of the ViewHolder, in this case we are using a custom
// layout called R.layout.property_card for each item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.property_card, parent, false);
return new PropertyViewHolder(view);
}
#Override
public void onDataChanged() {
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
progressBar.setVisibility(View.GONE);
}
//TODO Implement onError
#Override
public void onError(#NonNull DatabaseError e) {
// Called when there is an error getting data. You may want to update
// your UI to display an error message to the user.
// ...
progressBar.setVisibility(View.GONE);
Toast.makeText(getActivity(), "DatabaseError", Toast.LENGTH_SHORT).show();
}
};
mPropertyRecyclerView.setAdapter(mPropertyAdapter);
}
#Override
public void onStart() {
super.onStart();
mPropertyAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
mPropertyAdapter.stopListening();
}
public class PropertyViewHolder extends RecyclerView.ViewHolder {
View mView;
public PropertyViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setPrice(int price) {
String currencyPrice = NumberFormat //Format the price variable in currency form
.getCurrencyInstance(Locale.US)
.format(price);
TextView Price = mView.findViewById(R.id.post_price);
Price.setText(currencyPrice);
}
public void setAddress(String address){
TextView Address = mView.findViewById(R.id.post_address);
Address.setText(String.valueOf(address));
}
public void setNumberOfBed(int numberOfBed){
TextView NumberOfBed = mView.findViewById(R.id.post_bedroom);
NumberOfBed.setText(String.valueOf(numberOfBed));
}
public void setNumberOfBath(int numberOfBath){
TextView NumberOfBath = mView.findViewById(R.id.post_bathroom);
NumberOfBath.setText(String.valueOf(numberOfBath));
}
public void setNumberOfCar(int numberOfCar) {
TextView NumberOfCar = mView.findViewById(R.id.post_garage);
NumberOfCar.setText(String.valueOf(numberOfCar));
}
public void setPropertyImage(String propertyImage){
ImageView imageView = mView.findViewById(R.id.post_propertyImage);
//take one long string containing multiple url in and parse it
String propertyImageArray[] = propertyImage.split(",");
//Loading circle for placeholder, ColorAccent has been used
CircularProgressDrawable progressDrawable =
new CircularProgressDrawable(getContext());
progressDrawable.setStrokeWidth(5f);
progressDrawable.setCenterRadius(30f);
progressDrawable.setColorSchemeColors(Color.argb(1,255,145,0));
progressDrawable.start();
// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(getContext())
.load(propertyImageArray[0])
.placeholder(progressDrawable)
.fitCenter()
.into(imageView);
}
}
}
The detailed activity which is called by an intent from Tab1Buy
package com.realty.drake.kunuk;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.MenuItem;
import android.widget.Toast;
import java.text.NumberFormat;
import java.util.Locale;
public class PropertyDetail extends AppCompatActivity implements Toolbar.OnMenuItemClickListener {
#Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.property_detail);
Toolbar myToolbar = (Toolbar) findViewById(R.id.kunuk_toolbar);
myToolbar.inflateMenu(R.menu.menu_detail);
setSupportActionBar(myToolbar);
myToolbar.setOnMenuItemClickListener(this);
//collect our intent
Intent intent = getIntent();
Property property = intent.getParcelableExtra("Property");
boolean isRent = getIntent().getBooleanExtra("isRent", false);
//collect all property values from Parcelable
int price = property.getPrice();
String address = property.getAddress();
int numberOfBed = property.getNumberOfBed();
int numberOfBath = property.getNumberOfBath();
int numberOfCar = property.getNumberOfCar();
String propertyImage = property.getPropertyImage();
float propertyDim = property.getPropertyDim();
String propertyDesc = property.getPropertyDesc();
// Get a support ActionBar corresponding to this toolbar
ActionBar ab = getSupportActionBar();
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
BottomNavigationView bottomNavigationView = (BottomNavigationView)
findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_call:
Uri callNumberUri = Uri.parse("tel:+50937438713");
Intent callIntent = new Intent(Intent.ACTION_DIAL, callNumberUri);
startActivity(callIntent);
break;
case R.id.action_sms:
Uri smsNumberUri = Uri.parse("sms:+50937438713");
Intent smsIntent = new Intent(Intent.ACTION_SENDTO, smsNumberUri);
startActivity(smsIntent);
break;
case R.id.action_email:
//TODO get a property id to use in subject email field
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("message/rfc822");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Kunuk Request");
emailIntent.putExtra(Intent.EXTRA_EMAIL,
new String[] {"drakecolinj#gmail.com"});
startActivity(emailIntent);
}
return false;
}
});
//Bind the data from the Parcelable to the Views
TextView addressDetail = findViewById(R.id.post_address);
addressDetail.setText(String.valueOf(address));
String currencyPrice = NumberFormat //Format the price variable in currency form
.getCurrencyInstance(Locale.US)
.format(price);
TextView priceDetail = findViewById(R.id.post_price);
priceDetail.setText(currencyPrice);
ImageView imageView = findViewById(R.id.post_propertyImage);
//take one long string containing multiple url and parse it
String propertyImageArray[] = propertyImage.split(",");
//TODO add loading icon for placeholder
// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(getApplication())
.load(propertyImageArray[0])
.fitCenter()
.into(imageView);
TextView bathroomDetail = findViewById(R.id.post_bathroom);
bathroomDetail.setText(String.valueOf(numberOfBath));
TextView bedroomDetail = findViewById(R.id.post_bedroom);
bedroomDetail.setText(String.valueOf(numberOfBed));
TextView garageDetail = findViewById(R.id.post_garage);
garageDetail.setText(String.valueOf(numberOfCar));
TextView propertyDimDetail = findViewById(R.id.property_dim);
propertyDimDetail.setText(String.valueOf(propertyDim));
TextView propertyDescDetail = findViewById(R.id.property_desc);
propertyDescDetail.setText(String.valueOf(propertyDesc));
if (isRent) {
final TextView rentUnit = findViewById(R.id.rent_unit_detail);
rentUnit.setVisibility(View.VISIBLE);
}
}
#Override
public boolean onMenuItemClick(MenuItem item){
switch (item.getItemId()) {
case R.id.action_share:
Toast.makeText(this, "Shared", Toast.LENGTH_SHORT).show();
return true;
}
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_detail, menu);
return true;
}
}
In Child "Buy", each of its child has its own location key and the same for Rent and Lot.
Please help, conceptual explanation and code please
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Buy");
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// Let us retrieve value of location
Log.i("Price", dataSnapshot.child("location").getValue().toString());
// In this way you can retrieve all the fileds.
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Similarly for Rent & Lot you can pass as -
DatabaseReference dbRent = FirebaseDatabase.getInstance().getReference("Rent");
DatabaseReference dbLot = FirebaseDatabase.getInstance().getReference("Lot");
I hope this will helps!

Why is getAdapterPosition() being stuck on the first view clicked every (say) 5 seconds?

I have a RecyclerView class (QuestionCardAdapter) that presents all the items of a SpanishQuestionSet as CardViews.
Everything had been working fine (for instance i could make it so when a card was clicked, 'tick' and 'cross' buttons would come up and would remove the card when clicked)
However recently I wanted the clicking of the buttons (vCross or VTick) to modify an array which is a part of the SpanishQuestionSet (i.e. the item in the array would be +1 for wrong and -1 for right so that the descending quicksort i use will cause questions answered incorrectly to be at the top).
However, whenever I say click 4 consecutive cards as wrong, instead of each card's score being increased by 1, the first card of the 4's score is increased by 4. It seems like getAdapterPosition() is delayed. Could it be affected by a time limit variable I added so that the app wouldnt crash if someone double clicked a button before the card remove animation had completed?
Any help would be appreciated and I will present below the adapter and SpanishQuestionSet classes.
The adapter class is most likely the focus.
package com.alexgower.odin_spanishpack;
import android.content.Context;
import android.graphics.Color;
import android.os.SystemClock;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.util.List;
public class QuestionCardAdapter extends RecyclerView.Adapter<QuestionCardAdapter.QuestionCardViewHolder> {
private final Context context;
protected List<QuestionCardInfo> questionCardList;
private long mLastClickTime = 0;
private SpanishQuestionSet questionSet;
private int positionClicked;
private void setPositionClicked(int i){
this.positionClicked =i;
}
private int getPositionClicked(){
return this.positionClicked;
}
public QuestionCardAdapter(Context contextIn, List<QuestionCardInfo> questionCardList, SpanishQuestionSet questionSetIn) {
this.questionCardList = questionCardList;
this.context = contextIn;
this.questionSet = questionSetIn;
}
#Override
public int getItemCount() {
return questionCardList.size();
}
#Override
public void onBindViewHolder(QuestionCardViewHolder questionCardViewHolder, int i) {
QuestionCardInfo ci = questionCardList.get(i);
questionCardViewHolder.vQuestionAnswer.setText(String.valueOf(ci.score) + ci.question);
questionCardViewHolder.answer = ci.answer;
questionCardViewHolder.vTick.setVisibility(View.INVISIBLE);
questionCardViewHolder.vCross.setVisibility(View.INVISIBLE);
questionCardViewHolder.vColorTV.setBackgroundColor(questionSet.getColourForScore(context,ci.score));
}
#Override
public QuestionCardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.question_card_layout, viewGroup, false);
return new QuestionCardViewHolder(itemView);
}
public class QuestionCardViewHolder extends RecyclerView.ViewHolder {
public View view;
protected TextView vQuestionAnswer;
protected TextView vColorTV;
protected ImageView vTick;
protected ImageView vCross;
protected String answer = "Error";
public QuestionCardViewHolder(View v) {
super(v);
vColorTV = (TextView) v.findViewById(R.id.forNowColourTextView);
vQuestionAnswer = (TextView) v.findViewById(R.id.questionAnswerTextView);
vTick = (ImageView) v.findViewById(R.id.tickImage);
vCross = (ImageView) v.findViewById(R.id.crossImage);
view = v;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vQuestionAnswer.setText(answer);
vTick.setVisibility(View.VISIBLE);
vCross.setVisibility(View.VISIBLE);
setPositionClicked(getAdapterPosition());
}
});
view = vTick;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionRight(getPositionClicked(),context);
//questionSet.saveScores(context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
view = vCross;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionWrong(getPositionClicked(),context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
}
}
public void testContext(int position) {
questionSet.testFile(position, context);
//String name = questionSet.getQuestion(position);
//try {
// context.openFileOutput("a.txt", Context.MODE_PRIVATE);
// Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
//}catch(FileNotFoundException e){
// Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
//}
}
public void removeAt(int position) {
questionCardList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, questionCardList.size());
}
SpanishQuestionSet class
package com.alexgower.odin_spanishpack;
import android.content.Context;
import android.graphics.Color;
import android.os.SystemClock;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.util.List;
public class QuestionCardAdapter extends RecyclerView.Adapter<QuestionCardAdapter.QuestionCardViewHolder> {
private final Context context;
protected List<QuestionCardInfo> questionCardList;
private long mLastClickTime = 0;
private SpanishQuestionSet questionSet;
private int positionClicked;
private void setPositionClicked(int i){
this.positionClicked =i;
}
private int getPositionClicked(){
return this.positionClicked;
}
public QuestionCardAdapter(Context contextIn, List<QuestionCardInfo> questionCardList, SpanishQuestionSet questionSetIn) {
this.questionCardList = questionCardList;
this.context = contextIn;
this.questionSet = questionSetIn;
}
#Override
public int getItemCount() {
return questionCardList.size();
}
#Override
public void onBindViewHolder(QuestionCardViewHolder questionCardViewHolder, int i) {
QuestionCardInfo ci = questionCardList.get(i);
questionCardViewHolder.vQuestionAnswer.setText(String.valueOf(ci.score) + ci.question);
questionCardViewHolder.answer = ci.answer;
questionCardViewHolder.vTick.setVisibility(View.INVISIBLE);
questionCardViewHolder.vCross.setVisibility(View.INVISIBLE);
questionCardViewHolder.vColorTV.setBackgroundColor(questionSet.getColourForScore(context,ci.score));
}
#Override
public QuestionCardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.question_card_layout, viewGroup, false);
return new QuestionCardViewHolder(itemView);
}
public class QuestionCardViewHolder extends RecyclerView.ViewHolder {
public View view;
protected TextView vQuestionAnswer;
protected TextView vColorTV;
protected ImageView vTick;
protected ImageView vCross;
protected String answer = "Error";
public QuestionCardViewHolder(View v) {
super(v);
vColorTV = (TextView) v.findViewById(R.id.forNowColourTextView);
vQuestionAnswer = (TextView) v.findViewById(R.id.questionAnswerTextView);
vTick = (ImageView) v.findViewById(R.id.tickImage);
vCross = (ImageView) v.findViewById(R.id.crossImage);
view = v;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vQuestionAnswer.setText(answer);
vTick.setVisibility(View.VISIBLE);
vCross.setVisibility(View.VISIBLE);
setPositionClicked(getAdapterPosition());
}
});
view = vTick;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionRight(getPositionClicked(),context);
//questionSet.saveScores(context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
view = vCross;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionWrong(getPositionClicked(),context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
}
}
public void testContext(int position) {
questionSet.testFile(position, context);
//String name = questionSet.getQuestion(position);
//try {
// context.openFileOutput("a.txt", Context.MODE_PRIVATE);
// Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
//}catch(FileNotFoundException e){
// Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
//}
}
public void removeAt(int position) {
questionCardList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, questionCardList.size());
}
}
Turns out it is quite easy. For anyone in the future with a similar problem, note that getAdapterView() simply returns the integer of a views position in the viewholder so when a view is removed, the next view takes its position.
i.e. if you have views 1,2,3,4,5. When you remove 2, 3 becomes 2 and 4 becomes 3 etc. Alternative explanation: whichever is the 5th view on the screen will have position 5, even if 10000 other items before it have been removed (it will not be position 10005).
So it was not a problem with getAdapterPostion(). To fix the problem I used a variable for an itemID for each view in the recyclerview and did not use getAdapterPosition() except for in the removeAt() method.

Saving EditTexts on App close

on the homepage of my app i have edittexts that represent counters for each row in my list. whenever i change activity and return back to my main screen all the numbers disappear, the same happens when I close the app and open it again. How do i make the numbers stay?
My main activity where I call the row layout with the edittexts
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MyActivity extends Activity implements MyAdapterInterface{
private CustomCursorAdapter customAdapter;
public ListView list1;
//instantiating the database class
com.example.rory.dripdrop.DBAdapter db = new com.example.rory.dripdrop.DBAdapter(this);
public MyActivity mMyActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
list1 = (ListView)findViewById(R.id.data_list);
db.open();
mMyActivity = this;
//button and listener for add activity
Button addBtn = (Button)findViewById(R.id.add);
addBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MyActivity.this, Add.class);
startActivity(i);
}
});
//button and listener for delete activity
Button deleteBtn = (Button)findViewById(R.id.delete);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MyActivity.this, Delete.class);
startActivity(i);
}
});
//button and listener for update activity
Button updateBtn = (Button)findViewById(R.id.update);
updateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MyActivity.this, Update.class);
startActivity(i);
}
});
try {
String destPath = "/data/data/" + getPackageName() + "/databases/AssignmentDB";
File f = new File(destPath);
if (!f.exists()) {
CopyDB( getBaseContext().getAssets().open("mydb"),
new FileOutputStream(destPath));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//handler function for custom adapter, found example online to help with this
new Handler().post(new Runnable() {
#Override
public void run() {
customAdapter = new CustomCursorAdapter(MyActivity.this, db.getAllRecords(), mMyActivity);
list1.setAdapter(customAdapter);
}
});
}
public void onResume()
{
super.onResume();
//update list
addData();
}
//refreshes data base when main page is resumed
public void addData()
{
//handler function for custom adapter, found example online to help with this
new Handler().post(new Runnable() {
#Override
public void run() {
customAdapter = new CustomCursorAdapter(MyActivity.this, db.getAllRecords(), mMyActivity);
list1.setAdapter(customAdapter);
}
});
}
//chaning the running total
public void updateLitres(int value)
{
EditText editLitres = (EditText)findViewById(R.id.edit1);
//EditText myEditText2 = (EditText)findViewById(R.id.edit2);
editLitres.setText(String.valueOf(value));
//myEditText2.setText(String.valueOf(value));
}
public void updateCost(double value)
{
EditText editCost = (EditText)findViewById(R.id.edit2);
String.format("%.2f", value);
editCost.setText("€" + String.valueOf(value));
}
private class DBAdapter extends BaseAdapter {
private LayoutInflater mInflater;
//private ArrayList<>
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
return null;
}
}
public void CopyDB(InputStream inputStream, OutputStream outputStream)
throws IOException {
//---copy 1K bytes at a time---
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
}
My custom adapter for the rows
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomCursorAdapter extends CursorAdapter {
//public int counter = 0;
public ArrayList<Integer> counter;
public ArrayList<Integer> counter2;
private MyAdapterInterface mMyInterface;
public CustomCursorAdapter(Context context, Cursor cursor, MyAdapterInterface myInterface) {
//instantiating the values
super(context, cursor);
this.context = context;
this.mMyInterface = myInterface;
//array to sort each value per row
counter = new ArrayList<Integer>();
counter2 = new ArrayList<Integer>();
//default all counters to 0
for(int i=0; i<cursor.getCount(); i++)
{
counter.add(0);
counter2.add(0);
}
}
Context context;
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// when the view will be created for first time,
// we need to tell the adapters, how each item will look
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View retView = inflater.inflate(R.layout.row, parent, false);
return retView;
}
public void bindView(View view, Context context, final Cursor cursor) {
//getting the first value for the custom row (the item name)
TextView textViewItemName = (TextView) view.findViewById(R.id.item1);
textViewItemName.setText(cursor.getString(cursor.getColumnIndex(cursor.getColumnName(1))));
final int litres = Integer.parseInt(cursor.getString(cursor.getColumnIndex(cursor.getColumnName(2))));
//editText for custom row
final EditText runningTotal = (EditText) view.findViewById(R.id.runningTotal);
//setting up the plus button
final Button plusButton = (Button)view.findViewById(R.id.plusButton);
plusButton.setOnClickListener(new View.OnClickListener() {
private int counterPos;
private int counter2;
public void onClick(View v) {
//code to change the value of the editText and the array, not working
//cursor.getPosition() returns the position in the list
counterPos = counter.get(cursor.getPosition());
//increments the number at counterPos
counterPos = counterPos + litres;
//incrementing the edittext
//counter2 = counter.get(cursor.getPosition());
counter2++;
//set the new value to the array position
counter.set(cursor.getPosition(), counterPos);
//changes the editText in middle of row
runningTotal.setText(Integer.toString(counter2));
//sends counterPos to the interface for the running total
mMyInterface.updateLitres(counterPos);
mMyInterface.updateCost(counterPos * 0.00488);
}
});
//setting up the minus button
final Button minusButton = (Button)view.findViewById(R.id.minusButton);
minusButton.setOnClickListener(new View.OnClickListener() {
private int counterPos = 0;
private int counter2;
public void onClick(View v) {
//code to change the value of the editText and the array, not working
counterPos = counter.get(cursor.getPosition());
//increments the number at counterPos
counterPos = counterPos + litres;
//incrementing the edittext
//counter2 = counter.get(cursor.getPosition());
counter2--;
//set the new value to the array position
counter.set(cursor.getPosition(), counterPos);
//changes the editText in middle of row
runningTotal.setText(Integer.toString(counter2));
//sends counterPos to the interface for the running total
mMyInterface.updateLitres(counterPos);
mMyInterface.updateCost(counterPos * 0.00488);
}
});
}
}
You should have a look here You should take a look at the shared preferences, http://developer.android.com/reference/android/content/SharedPreferences.html, I used this and helped me get through it, You need to save each edit text that you want to save. and as for each row I would suggest making an array or loop for saving the edit boxes in the rows
didn't read your code bro, but answering in concern to your question title :
override onStop and save the data to Shared Preferences, its very easy to use:
//To save your data
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("name", "Elena");
editor.putInt("idName", 12);
editor.commit();
//to extract your data in onCreate or whenever you feel like:
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String restoredText = prefs.getString("text", null);
You will want to look into SharedPreferences, once you do you will basically be saving your values in SharedPreferences in an onPause() / onDestroy() method, and then in your onResume() / onCreate() methods you will retrieve the previously stored data
Edit: You can retrieve a string from an EditText in the following way
String toStore = EditText.getText().toString();
and then store it
getSharedPreferences("PREFERENCE",MODE_PRIVATE).edit().putString("KEY", toStore);
so...
public void onPause(){
super.onPause();
String toStore = EditText.getText().toString();
getSharedPreferences("PREFERENCE",MODE_PRIVATE).edit().putString("KEY", toStore);
}
public void onResume(){
super.onResume();
String toStore = PreferenceManager.getDefaultSharedPreferences(context).getString("KEY", "defaultStringIfNothingFound");
EditText.setText(toStore);
}
You may use onSavedInstanceState and onRestoreInstanceState methods of activity !
So in onSavedInstanceState (called before your activity pauses) you may save your `EditText' values to the bundle,
And restore them back in onRestoreInstance state.
You can use the link by #Kaique for more reference,
and also this answer https://stackoverflow.com/a/16769864/826657 and all related answers here.
You should take a look at the shared preferences, http://developer.android.com/reference/android/content/SharedPreferences.html

Categories