I am using jd-alexander/LikeButton https://github.com/jd-alexander/LikeButton instead of normal buttons in the android app. The code works fine while enabling and disabling switches. But I want to save the state of the like button. Suppose I enable the like button and swap the list the background code will run fine but the like button state will change to unliked.
Every time when I swap the list the like button state becomes unliked. Is there any way to save the like button State??
Activity codes:
public class CollectorListAdapter extends ArrayAdapter<Collector> {
private static final String TAG = "CollectorListAdapter";
private Context mContext;
private int mResource;
public CollectorListAdapter(Context context, int resource, ArrayList<Collector> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
public View getView(final int position, View convertView, ViewGroup parent) {
//Get the Shop information
String Shopname = getItem(position).getName();
String Specialoffers = getItem(position).getSpecialoffers();
int Price = getItem(position).getPrice();
final Double startLatitude = getItem(position).getLatitude();
final Double startLongitude = getItem(position).getLongitude();
final String user_id = String.valueOf(getItem(position).getUserid());
final String shop_id = String.valueOf(getItem(position).getShopid());
final String product_id = String.valueOf(getItem(position).getProductid());
//create the view result for showing the animation
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
TextView sname = (TextView) convertView.findViewById(R.id.textView);
TextView tvname = (TextView) convertView.findViewById(R.id.textView7);
TextView Location = (TextView) convertView.findViewById(R.id.textView9);
TextView tvdescription = (TextView) convertView.findViewById(R.id.textView10);
sname.setText(Shopname);
tvdescription.setText(Specialoffers);
tvname.setText(CurrencyFormatting(Integer.toString(Price)) + " EGP");
Location.setText(format(results[0]) + " km");
LikeButton heart;
heart = convertView.findViewById(R.id.favBtn);
heart.setOnLikeListener(new OnLikeListener() {
// Add Data to the Saved Shop Table by like
#Override
public void liked(LikeButton likeButton) {
StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_SAVED_SHOPS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Register Response: " + response.toString());
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error) {
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Registration Error: " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("user_id", user_id);
params.put("shop_id", shop_id);
params.put("product_id", product_id);
return params;
}
};
Volley.newRequestQueue(getContext()).add(strReq);
Toast.makeText(getContext(),
"Shop Saved Successfully", Toast.LENGTH_LONG).show();
}
// Delete Data to the Saved Shop Table by Unlike
#Override
public void unLiked(LikeButton likeButton) {
StringRequest strReq10 = new StringRequest(Request.Method.POST, AppConfig.URL_Delete_SAVED_SHOPS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Register Response: " + response.toString());
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error) {
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Registration Error: " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("user_id", user_id);
params.put("shop_id", shop_id);
params.put("product_id", product_id);
return params;
}
};
Volley.newRequestQueue(getContext()).add(strReq10);
Toast.makeText(getContext(),
"Shop Saved Deleted Successfully", Toast.LENGTH_LONG).show();
}
});
return convertView;
}
}
Collector Class:
public class Collector implements java.io.Serializable {
private String specialoffers, name;
private Double latitude, longitude;
private int price,userid,shopid,productid;
public Collector() {
}
//Sorting by Price method
public static Comparator<Collector> PriceSort = new Comparator<Collector>() {
public int compare(Collector s1, Collector s2) {
int rollno1 = s1.getPrice();
int rollno2 = s2.getPrice();
/*For ascending order*/
return rollno1 - rollno2;
/*For descending order*/
//rollno2-rollno1;
}
};
//Sorting by Distance method
public static Comparator<Collector> DistanceSort = new Comparator<Collector>() {
public int compare(Collector s1, Collector s2) {
float[] results1 = new float[3];
Location.distanceBetween(
LocationActivity.currentLocation.getLatitude(),
LocationActivity.currentLocation.getLongitude(),s1.getLatitude(),
s1.getLongitude(),
results1);
float[] results2 = new float[3];
Location.distanceBetween(
LocationActivity.currentLocation.getLatitude(),
LocationActivity.currentLocation.getLongitude(),s2.getLatitude(),
s2.getLongitude(),
results2);
/*For ascending order*/
return Float.compare(results1[0], results2[0]);
/*For descending order*/
//rollno2-rollno1;
}
};
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public int getShopid() {
return shopid;
}
public void setShopid(int shopid) {
this.shopid = shopid;
}
public int getProductid() {
return productid;
}
public void setProductid(int productid) {
this.productid = productid;
}
public String toString() {
return ("Shop Name:" + getName() +
" Price : " + getPrice() +
" SpecialOffers : " + getSpecialoffers() +
" latitude : " + getLatitude()) +
" longitude : " + getLongitude();
}
public String getSpecialoffers() {
return specialoffers;
}
public void setSpecialoffers(String specialoffers) {
this.specialoffers = specialoffers;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
This is the normal behaviour in ArrayAdapter, the whole list gets recreated again so you lose the state of the button. You should save the boolean of the button in the local list variable.
Add a field like isLiked = true/false in the Collector class and update the value at the particular position every time user click like/unlike buttons.
Related
I'm really confused about, How can I get the ID of the specific cardView when I click the check button , I want to get or Toast the id from database it already shown in the image I just want to get that id , but currently when I click the button in first row only the last id return which is the last number 12 instead of 2 need help
RecycleAdapterPending.java
#Override
public void onBindViewHolder(#NonNull MyViewHolderPending holder, #SuppressLint("RecyclerView") int position) {
final AppointmentPending appointment = appointments.get(position);
int id = 0;
int userId =0;
id = Integer.parseInt(appointment.getIdd());
userId = Integer.parseInt(appointment.getUserId());
finalId = id;
int finalUserId = userId;
btnDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String idd = String.valueOf(finalId);
//button to be clickeddd but it the output always `12`
Toast.makeText(mContext.getApplicationContext(), "click me" + idd ,Toast.LENGTH_SHORT).show();
}
});
holder.aptCategory.setText(appointment.getIdd());
holder.aptSubCat.setText(appointment.getSub_cat());
String schedule = appointment.getSchedule();
holder.aptDate.setText(schedule);
}
AppointmentPending.java
package com.example.clinicsys.Appointment.pending;
public class AppointmentPending {
private String idd,userId,category_name, sub_cat, schedule;
public AppointmentPending(String idd,String userId, String category_name, String sub_cat, String schedule){
this.idd = idd;
this.userId = userId;
this.category_name = category_name;
this.sub_cat = sub_cat;
this.schedule = schedule;
}
public String getIdd() {
return idd;
}
public void setIdd(String idd) {
this.idd = idd;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getCategory() {
return category_name;
}
public void setCategory(String category_name) {
this.category_name = category_name;
}
public String getSub_cat() {
return sub_cat;
}
public void setSub_cat(String sub_cat) {
this.sub_cat = sub_cat;
}
public String getSchedule() {
return schedule;
}
public void setSchedule(String schedule) {
this.schedule = schedule;
}
}
Home.java Get data from mysql
StringRequest stringRequest = new StringRequest(Request.Method.GET, BASE_URL+Urltype,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressBar.setVisibility(View.GONE);
try {
JSONArray array = new JSONArray(response);
for (int i = 0; i<array.length(); i++){
JSONObject object = array.getJSONObject(i);
String idd = object.getString("id");
String categoryName = object.getString("category");
String subCat = object.getString("subCategory");
String schedule = object.getString("schedule");
String userId = useridd;
AppointmentPending appointment = new AppointmentPending(idd,userId,categoryName,subCat,schedule);
appointments.add(appointment);
}
}catch (Exception e){
Toast.makeText(getApplicationContext(), "catch error " + e, Toast.LENGTH_SHORT).show();
}
mAdapter = new RecyclerAdapterPending(HomePending.this,appointments);
recyclerView.setAdapter(mAdapter);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressBar.setVisibility(View.GONE);
Toast.makeText(HomePending.this, "Database connection failed " + error.toString(),Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(HomePending.this).add(stringRequest);
I am making an attendance system where I take the attendance using RadioGroup with two options. When I select some radio button and scroll down some other radio button gets auto-selected. If I change them upper ones also get changed.
Main class
public class TeacherAttendanceActivity extends AppCompatActivity implements AttendanceAdapter.AttendanceAdapterListner {
public static TeacherAttendanceActivity teacherAttendanceActivity;
private static final String TAG = TeacherAttendanceActivity.class.getSimpleName();
List<AttendanceModel> listItems;
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private AttendanceAdapter attendanceAdapter;
ProgressDialog progressDialog;
private SQLiteHandler db;
private SessionManager session;
private SearchView searchView;
Button btnSubmit;
JSONObject mainObj = new JSONObject();
// date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentDateandTime = sdf.format(new Date());
String class_id,title;
Boolean Error;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teacher_attendance);
//get data from intent
class_id = super.getIntent().getExtras().getString("id"); //class_id
title = super.getIntent().getExtras().getString("title");
getSupportActionBar().setTitle("Class: "+title+", Date: "+currentDateandTime );
// SqLite database handler
db = new SQLiteHandler(getApplicationContext());
// session manager
session = new SessionManager(getApplicationContext());
btnSubmit=findViewById(R.id.buttonAttendanceSubmit);
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Error=false;
Gson gson=new Gson();
final String newDataArray=gson.toJson(listItems); // dataarray is list aaray
for (int i = 0; i < AttendanceAdapter.listItems.size(); i++){
if(AttendanceAdapter.listItems.get(i).getAttendance()==null){
Toast.makeText(TeacherAttendanceActivity.this, "Check attendance at roll:"+AttendanceAdapter.listItems.get(i).getRoll(), Toast.LENGTH_SHORT).show();
Error =true;
break;
}
}
if (!Error){
request(class_id,currentDateandTime,newDataArray);
}
}
});
listItems = new ArrayList<>();
attendanceAdapter = new AttendanceAdapter(listItems, this, (AttendanceAdapter.AttendanceAdapterListner) this);
recyclerView = (RecyclerView) findViewById(R.id.list_attendance);
recyclerView.setLayoutManager(new LinearLayoutManager(TeacherAttendanceActivity.this));
progressDialog = new ProgressDialog(this);
teacherAttendanceActivity = this;
//refresh_list(class_id);
}
#Override
protected void onStart() {
refresh_list(class_id);
super.onStart();
}
#Override
public void onAttendanceAdapterSelected(AttendanceModel model) {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.refresh, menu);
getMenuInflater().inflate(R.menu.tool_bar, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.action_settings:
Toast.makeText(getApplicationContext(),"Sittings",Toast.LENGTH_LONG).show();
return true;
case R.id.action_logout:
logoutUser();
return true;
case R.id.action_about:
Toast.makeText(getApplicationContext(),"About",Toast.LENGTH_LONG).show();
return true;
case R.id.action_devinfo:
Toast.makeText(getApplicationContext(),"Dev info",Toast.LENGTH_LONG).show();
return true;
case R.id.refresh:
refresh_list(class_id);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
void logoutUser() {
session.setLogin(false);
db.deleteUsers();
// Launching the login activity
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
// refresh list
public void refresh_list(String id) {
// this method refresh list and get the json data
listItems.clear();
// adapter = new MyAdapter(listItems,getApplicationContext());
recyclerView.setAdapter(attendanceAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
progressDialog.setMessage("Loading");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.GET, ApiConfig.URL_TEACHER_ATTENDANCE+id, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
progressDialog.hide();
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("Data"); // finding data
Log.d(TAG, String.valueOf(jsonObject));
int len = jsonArray.length();
for (int i = 0; i < len; i++) {
JSONObject o = jsonArray.getJSONObject(i);
AttendanceModel item = new AttendanceModel(
o.getString("id"),
o.getString("name"),
o.getString("roll"),
o.getString("class_id"),
o.getString("status"),
null
);
listItems.add(item);
//adapter = new MyAdapter(listItems,getApplicationContext());
recyclerView.setAdapter(attendanceAdapter); // setting them in list view
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.hide();
Toast.makeText(TeacherAttendanceActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
}) {
/** Passing some request headers* */
#Override
public Map getHeaders() throws AuthFailureError {
SQLiteHandler db = new SQLiteHandler(getApplicationContext());
HashMap<String,String> userDetail= db.getUserDetails();
String userToken = userDetail.get("token");
Log.d(TAG, String.valueOf(userToken));
HashMap headers = new HashMap();
headers.put("Accept", "application/json");
headers.put("Authorization", "Bearer "+userToken);
return headers;
}
};
stringRequest.setShouldCache(false);
VolleyRequest.getInstance(TeacherAttendanceActivity.this).addToRequestQueue(stringRequest);
}
// take attendance
private void request( final String classId,final String date,final String data ) {
progressDialog.setMessage("Taking attendance");
showDialog();
StringRequest strReq = new StringRequest(Request.Method.POST,
ApiConfig.URL_TEACHER_ATTENDANCE_STORE, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response);
hideDialog();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
String attendance = jObj.getString("Attendance");
Toast.makeText(TeacherAttendanceActivity.this, attendance, Toast.LENGTH_LONG).show();
finish();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("message");
Toast.makeText(TeacherAttendanceActivity.this,
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(TeacherAttendanceActivity.this, "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(TeacherAttendanceActivity.this,
error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
}
}) {
/** Passing some request headers* */
#Override
public Map getHeaders() throws AuthFailureError {
SQLiteHandler db = new SQLiteHandler(TeacherAttendanceActivity.this);
HashMap<String,String> userDetail= db.getUserDetails();
String userToken = userDetail.get("token");
Log.d(TAG, String.valueOf(userToken));
HashMap headers = new HashMap();
headers.put("Accept", "application/json");
headers.put("Authorization", "Bearer "+userToken);
return headers;
}
#Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("class_id", classId);
params.put("date", date);
params.put("data", data);
return params;
}
};
strReq.setShouldCache(false);
// Adding request to request queue
VolleyRequest.getInstance(TeacherAttendanceActivity.this).addToRequestQueue(strReq);
}
private void showDialog() {
if (!progressDialog.isShowing())
progressDialog.show();
}
private void hideDialog() {
if (progressDialog.isShowing())
progressDialog.dismiss();
}
}
Model class
'model class for convenient '
public class AttendanceModel {
String id,name,roll,classId,previousAttendance,attendance;
public AttendanceModel(String id, String name,String roll, String classId,String previousAttendance,String attedance ){
this.id = id;
this.name = name;
this.classId =classId;
this.roll=roll;
this.attendance=attedance;
this.previousAttendance=previousAttendance;
}
public String getAttendance() {
return attendance;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getRoll() {
return roll;
}
public String getClassId() {
return classId;
}
public String getPreviousAttendance(){return previousAttendance;}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setRoll(String roll) {
this.roll = roll;
}
public void setClassId(String classId) {
this.classId = classId;
}
public void setPreviousAttendance(String previousAttendance) {
this.previousAttendance = previousAttendance;
}
public void setAttendance(String attendance) {
this.attendance = attendance;
}
}
Adapter class
' adapter class '
public class AttendanceAdapter extends RecyclerView.Adapter<AttendanceAdapter.ViewHolder> implements Filterable
{
// date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentDateandTime = sdf.format(new Date());
private static final String TAG = AttendanceAdapter.class.getSimpleName();
public static List<AttendanceModel> listItems;
private List<AttendanceModel> listItemsFiltered;
private Context context;
private ProgressDialog dialog;
private AttendanceAdapter.AttendanceAdapterListner listner;
private ProgressDialog pDialog;
private SQLiteHandler db;
public static JSONObject jo = new JSONObject();
public static JSONArray ja = new JSONArray();
public AttendanceAdapter(List<AttendanceModel> listItems, Context context, AttendanceAdapter.AttendanceAdapterListner listner) {
this.listItems = listItems;
this.listner=listner;
this.context = context;
this.listItemsFiltered =listItems;
// SqLite database handler
db = new SQLiteHandler(context);
// Progress dialog
pDialog = new ProgressDialog(context);
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
listItemsFiltered = listItems;
} else {
List<AttendanceModel> filteredList = new ArrayList<>();
for (AttendanceModel row : listItems) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getName().toUpperCase().contains(charSequence.toString().toUpperCase())||row.getName().toLowerCase().contains(charSequence.toString().toLowerCase())) {
filteredList.add(row);
}
}
listItemsFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = listItemsFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
listItemsFiltered = (ArrayList<AttendanceModel>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView roll;
public TextView previous;
RadioGroup radioAttendance;
RadioButton radioAttendancePresent,radioAttendanceAbsent;
public CardView card_view;
public ViewHolder(View itemView) {
super(itemView);
name= (TextView) itemView.findViewById(R.id.textViewAttendanceStudentName);
roll = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentRoll);
previous = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentPreviousStatus);
radioAttendance = itemView.findViewById(R.id.radioAttendance);
radioAttendancePresent =itemView.findViewById(R.id.radioAttendancePresent);
radioAttendanceAbsent =itemView.findViewById(R.id.radioAttendanceAbsent);
//card_view = (CardView) itemView.findViewById(R.id.class_card_view); // card view for on click method
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick( View view) {
// send selected contact in callback
listner.onAttendanceAdapterSelected(listItemsFiltered.get(getAdapterPosition())); // selecting cardview and position (model)
}
});
radioAttendance.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
//Toast.makeText(TeacherAttendanceActivity.this, toString(i), Toast.LENGTH_SHORT).show();
// Toast.makeText(context,"clicked at position"+i+" "+id+""+name,Toast.LENGTH_SHORT).show();
if(radioAttendancePresent.isChecked())
{
listItems.get(getAdapterPosition()).setAttendance("present");
}
else {
listItems.get(getAdapterPosition()).setAttendance("absent");
}
}
});
}
}
#Override
public AttendanceAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.attendance_list, parent, false);
return new AttendanceAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder (final AttendanceAdapter.ViewHolder holder, final int position) {
final AttendanceModel listItem = listItemsFiltered.get(position);
holder.name.setText(listItem.getName());
holder.roll.setText(listItem.getRoll());
holder.previous.setText(listItem.getPreviousAttendance());
}
public interface AttendanceAdapterListner {
void onAttendanceAdapterSelected(AttendanceModel model); // sending cardview to say the dialoge and model for sending context
}
#Override
public int getItemCount() {
return listItemsFiltered.size();
}
private void showDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
}
Your problem would be solved by making small changes to your Recycler view adapter, please do not disable recyclable property, this makes your recycler view a glorified list view.
I can see you tried using a sparse boolean array to hold the state of the radio buttons, that is good but you do not need that too. The idea behind using a Sparse boolean array is to keep the state of each item in the recycler view so that when they are recycled you still have a reference to what the state of each item is.
In your adapter you already have something that we can use to know the state, that is the attendance property of your model, in that case, you can set the state of your checkboxes by checking if the attendance property is present or absent.
One more thing about your code is that you are using the onCheckChangedListener as a click event handler for your radio button, you should not use this because it responds to all check changed events, even if it is triggered from code and not from user action, so when you bind your view and you set any of your radio buttons as checked or unchecked, it calls this callback.
Here is a modified version of your ViewHolder class that solves this issue by applying the solution above.
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView roll;
public TextView previous;
RadioGroup radioAttendance;
RadioButton radioAttendancePresent, radioAttendanceAbsent;
public CardView card_view;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentName);
roll = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentRoll);
previous = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentPreviousStatus);
radioAttendance = itemView.findViewById(R.id.radioAttendance);
radioAttendancePresent = itemView.findViewById(R.id.radioAttendancePresent);
radioAttendanceAbsent = itemView.findViewById(R.id.radioAttendanceAbsent);
radioAttendancePresent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
radioAttendancePresent.setChecked(true);
listItems.get(getAdapterPosition()).setAttendance("present");
}
});
radioAttendanceAbsent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
radioAttendanceAbsent.setChecked(true);
listItems.get(getAdapterPosition()).setAttendance("absent");
}
});
}
void bind(int position) {
// use the sparse boolean array to check
if (listItems.get(position).getAttendance() != null) {
if (listItems.get(position).getAttendance().equals("present")) {
radioAttendancePresent.setChecked(true);
} else if (listItems.get(position).getAttendance().equals("absent")) {
radioAttendanceAbsent.setChecked(true);
}
} else {
radioAttendance.clearCheck();
}
name.setText(listItems.get(position).getName());
roll.setText(listItems.get(position).getRoll());
previous.setText(listItems.get(position).getPreviousAttendance());
}
}
Notice that we have separate click listener for each radio button and set the state in the list of items and just check that state when we are binding, also we have removed the onCheckChangedListener and the sparse boolean array, one last thing is that we made sure that when there is not state set for the attendance property, we just clear the radio buttons so that no one is selected the code is much simpler and works correctly now.
You have to initialize your RadioButton based on model state like below:
#Override
public void onBindViewHolder (final AttendanceAdapter.ViewHolder holder, final int position) {
final AttendanceModel listItem = listItemsFiltered.get(position);
holder.name.setText(listItem.getName());
holder.roll.setText(listItem.getRoll());
holder.previous.setText(listItem.getPreviousAttendance());
final String id =listItem.getId();
final String class_id =listItem.getClassId();
holder.radioAttendance.setOnCheckedChangeListener(null);
if(listItem.getAttendance().equalsIgnoreCase("present")) {
radioAttendancePresent.setChecked(true);
} else {
radioAttendancePresent.setChecked(false);
}
//Add listener here and remove from holder
holder.radioAttendance.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if(holder.radioAttendancePresent.isChecked()) {
listItemsFiltered.get(position).setAttendance("present");
} else {
listItemsFiltered.get(position).setAttendance("absent");
}
notifyDataSetChanged();
}
});
}
The above image is a simple design that I want to develop.
I have four type of different data with different view type like the below image enter image description here. but that is not a problem. problem is the data will come from different API with lazy loading like when user scroll the list from recycle view it will grab the data from the server. My question is how to combine them in a single adapter because I need to use lazy loading .so I can't load whole data at a time so I need to call the different type of API like goal-list API, appraisal API, post API etc. When user scroll. anyone can give me an idea with example. How can I handle that? Also when user will scroll it will call another api likeCount and comment count also. Currently, In my, I am calling single API and show that in the single recycle view. Currently, I am using android architecture component LiveData
Fragment :
public class NewsFeedFragment extends FcaFragment {
private View view;
private RecyclerView postRecyclerView;
private PostsAdapter postsAdapter;
private List<Post> posts;
private TimelineViewModel timelineViewModel;
private ImageView addPostView;
private View addPostPanel;
private long lastApiCallTime;
private SwipyRefreshLayout swipeRefresh;
private long lastScroolItemInPost= 0;
public NewsFeedFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(lastScroolItemInPost < 1) {
initViewModel(1 , 0 , true);
lastScroolItemInPost = 1;
}else {
initViewModel(((int) lastScroolItemInPost + 5), lastScroolItemInPost , true);
lastScroolItemInPost += 5;
}
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ownerActivity);
view = inflater.inflate(R.layout.fragment_news_feed, container, false);
postRecyclerView = (RecyclerView) view.findViewById(R.id.postRecyclerView);
postRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView postRecyclerView, int dx, int dy) {
super.onScrolled(postRecyclerView, dx, dy);
int lastVisiableItemInPostList = linearLayoutManager.findLastVisibleItemPosition();
if(lastScroolItemInPost < lastVisiableItemInPostList)
{
if(lastScroolItemInPost == 1)
{
initViewModel((int) (lastScroolItemInPost + 2), ( lastScroolItemInPost - 2 ) , false);
lastScroolItemInPost += 2;
}else{
initViewModel((int) (lastScroolItemInPost + 2), ( lastScroolItemInPost - 2 ) , false );
lastScroolItemInPost += 2;
}
}
}
});
posts = new ArrayList<>();
postRecyclerView.setLayoutManager(linearLayoutManager);
postsAdapter = new PostsAdapter(ownerActivity,posts,timelineViewModel);
postRecyclerView.setAdapter(postsAdapter);
swipeRefresh = (SwipyRefreshLayout) view.findViewById(R.id.swipeRefresh);
swipeRefresh.setOnRefreshListener(new SwipyRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh(SwipyRefreshLayoutDirection direction) {
if(direction == SwipyRefreshLayoutDirection.TOP){
timelineViewModel.fetchPosts2();
}
if(direction == SwipyRefreshLayoutDirection.BOTTOM){
timelineViewModel.fetchPosts();
}
}
});
return view;
}
private void initViewModel(int lastVisiableItemInPostList , long lastScroolItemInPost , boolean isFirstTimeOpenFeedFragment) {
TimelineViewModel.Factory factory = new TimelineViewModel.Factory(UserPreferences.getToken(ownerActivity), TaskUtils.getMySelfContact(ownerActivity));
timelineViewModel = ViewModelProviders.of(this,factory).get(TimelineViewModel.class);
timelineViewModel.getPostList().observe(this, new Observer<List<Post>>() {
#Override
public void onChanged(#Nullable List<Post> posts) {
postsAdapter.setPostList(posts);
swipeRefresh.setRefreshing(false);
}
});
timelineViewModel.getPostDeleted().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(#Nullable Boolean aBoolean) {
if(aBoolean){
postsAdapter.setPostList(Post.getAll());
}
}
});
timelineViewModel.init( lastVisiableItemInPostList , lastScroolItemInPost ,isFirstTimeOpenFeedFragment);
}
}
ViewModel :
public class TimelineViewModel extends FCViewModel implements PostDetailsDownloadManager.PostDetailDownloadedListener,OnContactReceivedListner{
public TimelineViewModel(String token,Contact user){
super(token);
this.user = user;
post = new MutableLiveData<>();
postDeleted = new MutableLiveData<>();
}
public void init(int lastVisiableItemInPostList , long lastScroolItemInPost , boolean isFirstTimeOpenFeedFragment){
repository =
//postDetailsDownloadManager = ServiceLocator.getServiceLocator().postDetailsDownloadManager;
likePostDownloadManager = ServiceLocator.getServiceLocator().likePostDownloadManager;
likePostDownloadManager.setPostDetailDownloadedListener(new DataDownloadManager.DataDownloadedListener<LikePostTouple>() {
#Override
public void onDataDownloaded(List<LikePostTouple> dataTouple) {
TimelineViewModel.this.post.setValue(Post.getAll());
}
#Override
public void onSingleDataDownloaded(LikePostTouple dataTouple) {
}
});
postDetailDownloadManager = ServiceLocator.getServiceLocator().postDetailDownloadManager;
postDetailDownloadManager.setPostDetailDownloadedListener(new DataDownloadManager.DataDownloadedListener<PostTouple>() {
#Override
public void onDataDownloaded(List<PostTouple> dataTouple) {
TimelineViewModel.this.post.setValue(Post.getAll());
}
#Override
public void onSingleDataDownloaded(PostTouple dataTouple) {
}
});
post.setValue(Post.getAll());
if(isFirstTimeOpenFeedFragment)
{
fetchPosts2();
}
try {
if(Post.getAll().size() > 0)
{
List<Post> tempPosts = Post.getAll();
List<Post> passList = tempPosts.subList( (int) lastScroolItemInPost ,lastVisiableItemInPostList);
fetchLikesOfPosts(passList);
}else{
fetchLikesOfPosts(Post.getAll());
}
} catch (Exception e) {
e.printStackTrace();
}
Log.d("Testing Injecting", repository.toString());
}
public LiveData<List<Post>> getPostList() {
return post;
}
public MutableLiveData<Boolean> getPostDeleted() {
return postDeleted;
}
boolean isContactFetched = false;
public void fetchPosts(){
if(Contact.getAll().size() < 1){
fetchContacts();
return;
}
Map<String,Object> requestData = new HashMap<>();
requestData.put("type",1);
requestData.put("cpid",Post.getLastPid());
isDataLoading = true;
repository.getData(new Repository.DataFetchedListener<List<Post>>() {
#Override
public void onDataFetched(List<Post> posts) {
isDataLoading = false;
Log.d("fetched posts",""+posts.size());
post.setValue(Post.getAll());
fetchPostDetails(posts);
if(posts.size() > 0){
fetchLikesOfPosts(posts);
}
}
},requestData);
}
private boolean isDataLoading = false;
public void fetchPosts2(){
if(Contact.getAll().size() < 1){
fetchContacts();
return;
}
Map<String,Object> requestData = new HashMap<>();
requestData.put("type",2);
requestData.put("cpid", Post.getFirstPid()); // cpid means cursor pid
isDataLoading = true;
repository.getData(new Repository.DataFetchedListener<List<Post>>() {
#Override
public void onDataFetched(List<Post> posts) {
isDataLoading = false;
Log.d("fetched posts",""+posts.size());
post.setValue(Post.getAll());
fetchPostDetails(posts);
if(posts.size() > 0){
fetchLikesOfPosts(posts);
}
}
},requestData);
}
public boolean isDataLoading() {
return isDataLoading;
}
private void fetchContacts() {
contactRepository.getData(new Repository.DataFetchedListener<List<Contact>>() {
#Override
public void onDataFetched(List<Contact> data) {
if(data.size()>0 && !isContactFetched) {
fetchPosts2();
isContactFetched = true;
}
}
},null);
}
#NonNull
private PostTouple getPostToubleFromPost(Post post) throws JSONException {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String json = gson.toJson(post);
JSONObject postJson = new JSONObject(json);
return new PostTouple(postJson,post.getPid());
}
#NonNull
private LikePostTouple getLkePostToupleFromPost(Post post) throws JSONException {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String json = gson.toJson(post);
JSONObject postJson = new JSONObject(json);
return new LikePostTouple(postJson,post.getPid());
}
public void giveLike(String token, final long pid){
Map<String,Object> requestData = new HashMap<>();
requestData.put("token",token);
requestData.put("pid",Long.toString(pid));
likeRepository.postData(new Repository.DataFetchedListener<Post>() {
#Override
public void onDataFetched(Post data) {
Log.d("Like post", data.toString());
Post post = getPostById(pid);
post.setLikes(data.getLikes());
post.setComments(data.getComments());
TimelineViewModel.this.post.setValue(TimelineViewModel.this.post.getValue());
fetchLikesOfLikedPost(data);
}
},requestData);
}
private void fetchLikesOfLikedPost(Post data) {
try {
likePostDownloadManager.addItemInQueue(getLkePostToupleFromPost(data));
likePostDownloadManager.startDownload();
} catch (JSONException e) {
e.printStackTrace();
}
}
private Post getPostById(long pid){
List<Post> posts = post.getValue();
for(Post post : posts){
if(post.getPid()==pid){
return post;
}
}
return null;
}
public Contact getSenderContactFromComment(Post post) {
if(post.getPqrc().equals(user.getUserId())){
return user;
}
Contact contact = Contact.getByUserId(post.getPqrc());
return contact;
}
public String getDescriptionForType5(Post post,String message){
try {
PostDetail postDetail = PostDetail.getByPostId(post.getPid());
if(postDetail!=null) {
String qrc = JSonUtils.qrcFromCntOfPostDetails(postDetail.getContent());
int sid = JSonUtils.skillidFromCntOfPostDetails(postDetail.getContent());
if (qrc == null || sid == 0) {
return "";
}
SkillDb skill = SkillDb.getBySId(Integer.toString(sid));
Contact contact = getPosterContact(post.getPqrc());
return contact.getName() + " " + message + " " + skill.getSkillName() + ".";
}
return "";
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public String getDescriptionForPost(Post post, String message){
if(post.getCtype()==1){
return post.getDescr();
}
if(post.getCtype() == 2){
String postDetail = getContent(post);
if (postDetail != null) return Html.fromHtml(""+postDetail+"").toString();
}
if(post.getCtype()==5){
return getDescriptionForType5(post, message);
}
return "";
}
#Nullable
public String getContent(Post post) {
PostDetail postDetail = PostDetail.getByPostId(post.getPid());
if(postDetail!=null){
return postDetail.getContent();
}
return null;
}
public Contact getPosterContact(String qrc){
try {
String userqrc = user.getUserId();
if (userqrc.equals(qrc)) {
return user;
}
}catch (Exception e){
e.printStackTrace();
}
try {
return Contact.getByUserId(qrc);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public void fetchUrlPreview(String url, final UrlMetaDataFetchListener metaDataFetchListener){
String modifiedUrl = !url.contains("http://")&&!url.contains("https://")? "http://"+url : url;
TextCrawler textCrawler = new TextCrawler();
LinkPreviewCallback linkPreviewCallback = new LinkPreviewCallback() {
#Override
public void onPre() {
}
#Override
public void onPos(SourceContent sourceContent, boolean b) {
String imageUrl = sourceContent.getImages().isEmpty()? "" : sourceContent.getImages().get(0);
metaDataFetchListener.onMetaDataFetched(sourceContent.getTitle(),sourceContent.getDescription(), imageUrl);
}
};
textCrawler.makePreview(linkPreviewCallback, modifiedUrl,1);
}
public interface UrlMetaDataFetchListener{
void onMetaDataFetched(String title, String description, String imageUrl);
}
#Override
public void onPostDownloaded(PostTouple postTouple) {
this.post.setValue(Post.getAll());
}
#Override
public void onContactsReceived() {
fetchPosts();
}
public void deletePost(long pid) {
Map<String, Object> requestData = new HashMap<>();
requestData.put("token",token);
requestData.put("pid",pid);
repository.postData(new Repository.DataFetchedListener<Post>() {
#Override
public void onDataFetched(Post data) {
postDeleted.setValue(data!=null);
}
},requestData);
}
public boolean isMyPost(Post post){
return user.getUserId().equals(post.getPqrc());
}
public static class Factory extends ViewModelProvider.NewInstanceFactory {
private String token;
private Contact user;
public Factory(String token,Contact user) {
this.token = token;
this.user = user;
}
#Override
public <T extends ViewModel> T create(Class<T> modelClass) {
return (T) new TimelineViewModel(token,user);
}
}
}
Adapter :
public class PostsAdapter extends RecyclerView.Adapter {
private Context context;
private List<Post> postList;
private int[] badges = {R.drawable.badge1, R.drawable.badge2, R.drawable.badge3};
private List<Integer> randomNumbers = Utils.getRandomNumberList(2,true);
private ArrayDeque<Integer> randomQueue = new ArrayDeque<>(randomNumbers);
private static Map<Long,URLPreview> urlPreviewMap = new HashMap<>();
private TimelineViewModel timelineViewModel;
public PostsAdapter(Context context, List<Post> postList, TimelineViewModel timelineViewModel){
super();
this.context = context;
this.postList = postList;
this.timelineViewModel = timelineViewModel;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.post_item_layout, null);
PostViewHolder postViewHolder = new PostViewHolder(view);
postViewHolder.setIsRecyclable(false);
return postViewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final Post post = postList.get(position);
final PostViewHolder postViewHolder = (PostViewHolder) holder;
final String postDetail = timelineViewModel.getDescriptionForPost(post,context.getResources().getString(R.string.postType5message));
setPostDescription(post, postViewHolder, postDetail);
handlePreviewVisibility(post, postViewHolder);
postViewHolder.setLikes(""+post.getLikes()+" Likes");
postViewHolder.setCommentCount("" + post.getComments() + " Comments");
postViewHolder.setSupDescription("Posted By System");
int randomNumber = getRandomNumber();
postViewHolder.setBadgeIcon(badges[randomNumber]);
setPostLikedIndicator(post, postViewHolder);
postViewHolder.getLikeButtonWrapper().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
giveLikeToPost(post);
if(post.getIsLiked() == 0) {
post.setLikes(post.getLikes() + 1);
postViewHolder.setLikes("" + post.getLikes() + " Likes");
post.setIsLiked(1);
setPostLikedIndicator(post, postViewHolder);
}
}
});
postViewHolder.getCommentPanel().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommentPostFragment fragment = CommentPostFragment.GetInstance(post.getPid());
ViewUtils.launchFragmentKeepingInBackStack(context,fragment);
}
});
Contact contact = timelineViewModel.getPosterContact(post.getPqrc());
if(contact!=null && TaskUtils.isNotEmpty(contact.getImageToken())){
Utils.setImageToImageView(postViewHolder.getPosterImage(),timelineViewModel.getToken(),contact.getImageToken());
postViewHolder.getPosterNameTextView().setText(contact.getName());
}
postViewHolder.getPostingDate().setText(Utils.getDateFromMilliseconds(post.getdC()));
if(post.getCtype() != 3)
{
postViewHolder.contentImage.setVisibility(View.GONE);
postViewHolder.fullScreenIndicatorIcon.setVisibility(View.GONE);
}
if(post.getCtype() == 3){
setContentOfType3(post, postViewHolder);
}
}
#Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
PostViewHolder viewHolder = (PostViewHolder) holder;
viewHolder.pTitle.setText("");
viewHolder.pDescription.setText("");
viewHolder.pImage.setImageDrawable(null);
}
private void handlePreviewVisibility(Post post, PostViewHolder postViewHolder) {
if(post.getCtype()==2){
postViewHolder.preview.setVisibility(View.VISIBLE);
}else{
postViewHolder.preview.setVisibility(View.GONE);
}
}
private void handleShowingOptionsIcon(Post post, PostViewHolder postViewHolder) {
if(post.getCtype()!=5 && timelineViewModel.isMyPost(post)){
postViewHolder.options.setVisibility(View.VISIBLE);
}else{
postViewHolder.options.setVisibility(View.GONE);
}
}
private void giveLikeToPost(Post post) {
post.setLikes(post.getLikes()+1);
post.setIsLiked(1);
//notifyDataSetChanged();
timelineViewModel.giveLike(UserPreferences.getToken(context),post.getPid());
}
private void setPostLikedIndicator(Post post, PostViewHolder postViewHolder) {
if(post.getIsLiked()==1) {
postViewHolder.getLikeButton().setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_like_red, null));
}else{
postViewHolder.getLikeButton().setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_like_filled, null));
}
}
private void setPostDescription(final Post post, final PostViewHolder postViewHolder, final String postDetail) {
if(post.getCtype()==2){
String postDescription = "<p>"+ post.getDescr()+"</p>";
postViewHolder.description.setText( Html.fromHtml(postDescription +""+postDetail+"") );
postViewHolder.descriptionContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String url = !postDetail.contains("http://")&&!postDetail.contains("https://")? "http://"+postDetail : postDetail;
Uri uri = Uri.parse(url);
context.startActivity(new Intent(Intent.ACTION_VIEW,uri));
}
});
URLPreview urlPreview = null;
if((urlPreview=urlPreviewMap.get(post.getPid()))==null) {
timelineViewModel.fetchUrlPreview(postDetail, new TimelineViewModel.UrlMetaDataFetchListener() {
#Override
public void onMetaDataFetched(String title, String description, String imageUrl) {
showURLPreview(title, description, imageUrl, postViewHolder);
urlPreviewMap.put(post.getPid(),new URLPreview(title,description,imageUrl));
}
});
}else {
showURLPreview(urlPreview.getTitle(),urlPreview.getDescription(),urlPreview.getImageUrl(),postViewHolder);
}
}else if(post.getCtype() == 3)
{
String postDescription = post.getDescr();
postViewHolder.description.setText(postDescription);
}
else {
postViewHolder.setDescription(postDetail);
}
}
private void initImageClickListener(final ImageView imageView, final String pictureLink) {
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
List<String> pictureLinks = new ArrayList<String>();
pictureLinks.add(pictureLink);
int[] screenLocation = new int[2];
imageView.getLocationOnScreen(screenLocation);
ImagePagerFragment imagePagerFragment = ImagePagerFragment.newInstance(pictureLinks, 0, screenLocation, imageView.getWidth(), imageView.getHeight());
ViewUtils.launchPopUpFragmentUpdated(context, imagePagerFragment);
}
});
}
private void showURLPreview(String title, String description, String imageUrl, PostViewHolder postViewHolder) {
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(!TaskUtils.isEmpty(imageUrl)) {
Picasso.with(context)
.load(imageUrl)
.into(postViewHolder.pImage);
}
view.findViewById(R.id.description);
postViewHolder.pTitle.setText(title);
postViewHolder.pDescription.setText(description);
}
#Override
public int getItemCount() {
return postList.size();
}
private int getRandomNumber(){
if(!randomQueue.isEmpty()){
return randomQueue.poll();
}
randomQueue = new ArrayDeque<>(randomNumbers);
return randomQueue.poll();
}
public void setPostList(List<Post> postList) {
this.postList = postList;
notifyDataSetChanged();
Log.d("Data rec", postList.size()+"");
}
class PostViewHolder extends RecyclerView.ViewHolder implements PopupMenu.OnMenuItemClickListener {
}
public void setLikes(String likes) {
this.likes.setText(likes);
}
public void setCommentCount(String commentCount)
{
this.commentCount.setText(commentCount);
}
public void setDescription(String description){
this.description.setText(description);
}
public void setSupDescription(String subDescription){
this.supDescription.setText(subDescription);
}
public void setBadgeIcon(int resID){
Utils.setImageViewFromResource(badgeIcon,resID);
}
public ImageView getLikeButton() {
return likeButton;
}
public RelativeLayout getLikeButtonWrapper()
{
return likeButtonWrapper;
}
public ImageView getCommentButton() {
return commentButton;
}
public ImageView getPosterImage() {
return posterImage;
}
public TextView getPosterNameTextView() {
return posterNameTextView;
}
public TextView getPostingDate() {
return postingDate;
}
public RelativeLayout getCommentPanel() {
return commentPanel;
}
#Override
public boolean onMenuItemClick(MenuItem item) {
timelineViewModel.deletePost(postList.get(getAdapterPosition()).getPid());
return false;
}
}
}
I take https://jsonplaceholder.typicode.com/users with asynctask but i take to use pojo object .
What should I add code between ? What line should I write and how should i write ?
DataRetriever.java
public DataRetriever(Activity activity) {
activityWeakReference = new WeakReference<>(activity);
current_activity = activityWeakReference.get();
}
#Override
protected void onPreExecute() {
imageView = (ImageView) current_activity.findViewById(R.id.imageView);
if (current_activity != null) {
recyclerView = (RecyclerView) current_activity.findViewById(R.id.recyclerView);
swipeRefreshLayout = (SwipeRefreshLayout) current_activity.findViewById(R.id.swipe_container);
swipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
recyclerView.setHasFixedSize(true);
} else {
Log.d(TAG, "unable to get current activity");
Toast.makeText(current_activity, "unable to get current activity", Toast.LENGTH_SHORT).show();
}
super.onPreExecute();
progressDialog = new ProgressDialog(current_activity);
progressDialog.setMessage("Loading...");
progressDialog.show();
}
#SafeVarargs
#Override
protected final Integer doInBackground(List<String>... integers) {
HttpURLConnection httpURLConnection = null;
URL url;
List<String> local_list = integers[0];
type = Integer.parseInt(local_list.get(0));
String jsonString, jsonData;
return_status = 0;
switch (type) {
case 1:
url_string = "https://jsonplaceholder.typicode.com/users";
break;
case 2:
url_string = "https://jsonplaceholder.typicode.com/albums";
recieved_id = Integer.parseInt(local_list.get(1));
title = local_list.get(2);
break;
case 3:
url_string = "https://jsonplaceholder.typicode.com/photos";
recieved_id = Integer.parseInt(local_list.get(1));
title = local_list.get(2);
break;
}
try {
url = new URL(url_string);
httpURLConnection = (HttpURLConnection) url.openConnection();
int statusCode = httpURLConnection.getResponseCode();
if (statusCode == 200) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
while ((jsonData = bufferedReader.readLine()) != null) {
stringBuilder.append(jsonData);
}
jsonString = stringBuilder.toString();
jsonParser(jsonString);
return_status = 1;
} else {
Log.d(TAG, "Some error occurred could'nt fetch data");
Toast.makeText(current_activity, "Some error occurred could'nt fetch data", Toast.LENGTH_SHORT).show();
return_status = 0;
}
publishProgress(local_list);
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
return return_status;
}
private void jsonParser(String jsonString) {
int names_count, id;
String name;
try {
JSONArray jsonArray = new JSONArray(jsonString);
names_count = jsonArray.length();
if (!listValues.isEmpty())
listValues.clear();
if (!pictureValues.isEmpty())
pictureValues.clear();
for (int i = 0; i < names_count; i++) {
JSONObject array_items = jsonArray.getJSONObject(i);
ListValues jsonValues, pictureValue;
switch (type) {
case 1:
id = array_items.optInt("id");
name = array_items.optString("name");
jsonValues = new ListValues(id, name);
listValues.add(jsonValues);
break;
case 2:
id = array_items.optInt("userId");
name = array_items.optString("title");
if (id == recieved_id) {
jsonValues = new ListValues(id, name);
listValues.add(jsonValues);
}
break;
case 3:
id = array_items.optInt("albumId");
name = array_items.optString("title");
String pictureURL = array_items.getString("url");
if (id == recieved_id) {
jsonValues = new ListValues(id, name);
pictureValue = new ListValues(id, pictureURL);
listValues.add(jsonValues);
pictureValues.add(pictureValue);
}
break;
}
}
} catch (JSONException e) {
Log.d(TAG, e.getLocalizedMessage());
}
}
#Override
protected void onProgressUpdate(final List<String>... values) {
List<String> progressList = values[0];
Log.d(TAG, progressList.get(0));
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
switch (type) {
case 1:
new DataRetriever(current_activity).execute(values[0]);
case 2:
new DataRetriever(current_activity).execute(values[0]);
case 3:
new DataRetriever(current_activity).execute(values[0]);
}
}
});
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(final Integer integer) {
if (integer != 0) {
recyclerAdapter = new RecyclerAdapter(listValues);
recyclerView.addItemDecoration(new ListItemDecorator(current_activity.getApplicationContext()));
recyclerView.setAdapter(recyclerAdapter);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(current_activity);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
if (swipeRefreshLayout.isRefreshing())
swipeRefreshLayout.setRefreshing(false);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(current_activity.getApplicationContext(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
String pictureURL = null;
ListValues feed = listValues.get(position);
if (!pictureValues.isEmpty()) {
ListValues feed2 = pictureValues.get(position);
pictureURL = feed2.getValue();
}
String value = feed.getValue();
switch (type) {
case 1:
intent = new Intent(current_activity, AlbumActivity.class);
intent.putExtra("id", (position + 1));
intent.putExtra("value", value);
current_activity.startActivity(intent);
break;
case 2:
intent = new Intent(current_activity, PhotosActivity.class);
intent.putExtra("id", (position + 1));
intent.putExtra("value", value);
current_activity.startActivity(intent);
break;
case 3:
intent = new Intent(current_activity, ImageDisplay.class);
intent.putExtra("imageUrl", pictureURL);
current_activity.startActivity(intent);
break;
}
}
#Override
public void onLongClick(View view, int position) {
}
}));
} else {
// Log.d(TAG, "unable to get data");
if (swipeRefreshLayout.isRefreshing()) {
Toast.makeText(current_activity, "Unable to refresh data! Try opening application again", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(current_activity, "Failed to fetch data! try again", Toast.LENGTH_SHORT).show();
}
}
super.onPostExecute(integer);
progressDialog.dismiss();
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
Post.java
public class Post implements Serializable {
#SerializedName("userId")
private int userId;
#SerializedName("name")
#Expose
public String name;
#SerializedName("id")
private int id;
#SerializedName("title")
private String title;
#SerializedName("body")
private String body;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
Your important advice for me
Thank you!
You can easily do that with GSON and POJO
first.. you need to create several model
Post.java
public class Post
{
private String id;
private String phone;
private String username;
private String website;
private Address address;
private String email;
private Company company;
private String name;
//setter and getter
}
Company.java
public class Company
{
private String catchPhrase;
private String name;
private String bs;
//setter and getter
}
Address.java
public class Address
{
private Geo geo;
private String zipcode;
private String street;
private String suite;
private String city;
//setter and getter
}
Geo.java
public class Geo
{
private String lng;
private String lat;
//setter and getter
}
After that, json string you get from the API. parse it using Gson..
List<Post> post = new Gson().fromJson(YOUR_JSON_STRING,new TypeToken<List<Post>>() {}.getType());
I'm creating an Android map app by getting venue from Foursquare and using Google Map.
I have set my MainActivity to get the venue results, a MapFragmentClass and a VenueModel.
I keep all the JSON result from Foursquare into a List venueModelList in the MainActivity.
What I want to do is to add markers in the MapFragmentClass based on the coordinates received from Foursquare.
However, I am stuck trying to pass the venueModelList to the MapFragmentClass.
Any help is appreciated. Thanks.
MainActivity.java
public class MainActivity extends AppCompatActivity implements LocationListener{
private final String VENUE_URL = "https://api.foursquare.com/v2/venues/search?ll=";
private final int LIMIT = 40;
private final double RADIUS = 50000;
private String MOSQUE_URL;
private String RES_URL;
public static final String CLIENT_ID = "";
public static final String CLIENT_SECRET = "";
private static final long MIN_TIME_BW_UPDATES = 20000;
private static final float MIN_DISTANCE_CHANGE_FOR_UPDATES = 1;
private LocationManager locationManager;
private Location lastLocation;
private Location location;
private boolean receivedLocation = false;
private double lt;
private double lg;
private boolean canGetLocation;
private boolean isGPSEnabled;
private boolean isNetworkEnabled;
private boolean updateSettings = false;
private String TAG = "TAG";
private ListView lvVenues;
private Bundle bundle;
private ArrayList<VenueModel> venueModelList;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvVenues = (ListView) findViewById(R.id.lvVenues);
String t = timeMilisToString(System.currentTimeMillis());
Bundle extras = getIntent().getExtras();
if (extras != null)
{
lt = extras.getDouble("LATITUDE");
lg = extras.getDouble("LONGITUDE");
receivedLocation = true;
}
else
{
receivedLocation = false;
}
location = getLocation();
if (location != null)
{
if(receivedLocation)
{
location.setLatitude(lt);
location.setLongitude(lg);
}
else
{
lt = location.getLatitude();
lg = location.getLongitude();
Log.d("LAT", "Latitude: " + lt);
Log.d("LONG", "Longitude: " + lg);
}
}
double lt = 3.142182;
double lg = 101.710602;
MOSQUE_URL = VENUE_URL + lt + "," + lg
+ "&client_id=" + CLIENT_ID
+ "&client_secret=" + CLIENT_SECRET
+ "&v=" + t
+ "&categoryId=4bf58dd8d48988d138941735"
+ "&radius=" + RADIUS
+ "&limit=" + LIMIT;
RES_URL = VENUE_URL + lt + "," + lg
+ "&client_id=" + CLIENT_ID
+ "&client_secret=" + CLIENT_SECRET
+ "&v=" + t
+ "&categoryId=52e81612bcbc57f1066b79ff"
+ "&radius=" + RADIUS
+ "&limit=" + LIMIT;
}
public class JSONTask extends AsyncTask<String, String, List<VenueModel>>
{
#Override
public List<VenueModel> doInBackground(String... params)
{
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONObject secondObject = parentObject.getJSONObject("response");
JSONArray parentArray = secondObject.getJSONArray("venues");
venueModelList = new ArrayList<>();
for (int i = 0; i < parentArray.length(); i++)
{
JSONObject finalObject = parentArray.getJSONObject(i);
JSONObject thirdObject = finalObject.getJSONObject("location");
try {
VenueModel venueModel = new VenueModel();
venueModel.setId(finalObject.getString("id"));
venueModel.setName(finalObject.getString("name"));
venueModel.setAddress(thirdObject.optString("address"));
venueModel.setPostalCode(thirdObject.optString("postalCode"));
venueModel.setCity(thirdObject.optString("city"));
venueModel.setState(thirdObject.optString("state"));
venueModel.setDistance(thirdObject.getInt("distance"));
venueModel.setLat(thirdObject.getDouble("lat"));
venueModel.setLng(thirdObject.getDouble("lng"));
LatLng coordinate = new LatLng(thirdObject.getDouble("lat"), thirdObject.getDouble("lng"));
venueModel.setCoordinate(coordinate);
venueModelList.add(venueModel);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Collections.sort(venueModelList);
return venueModelList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(List<VenueModel> result)
{
super.onPostExecute(result);
VenueAdapter adapter = new VenueAdapter(getApplicationContext(), R.layout.row, result);
lvVenues.setAdapter(adapter);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == R.id.action_mosque)
{
new JSONTask().execute(MOSQUE_URL);
FragmentManager fmanager = getSupportFragmentManager();
FragmentTransaction FT = fmanager.beginTransaction();
MapFragmentClass mfc = new MapFragmentClass();
FT.add(R.id.mapLayout, mfc);
FT.commit();
return true;
}
if (id == R.id.action_restaurant)
{
new JSONTask().execute(RES_URL);
FragmentManager fmanager = getSupportFragmentManager();
FragmentTransaction FT = fmanager.beginTransaction();
MapFragmentClass mfc = new MapFragmentClass();
FT.add(R.id.mapLayout, mfc);
FT.commit();
return true;
}
return super.onOptionsItemSelected(item);
}
private String timeMilisToString(long milis)
{
SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milis);
return sd.format(calendar.getTime());
}
public Location getLocation()
{
try
{
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
Log.v(TAG, "No network provider enabled");
}
else
{
this.canGetLocation = true;
if (isNetworkEnabled)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d(TAG, "Network Enabled");
if(locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
}
if (isGPSEnabled)
{
if (location == null)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d(TAG, "GPS Enabled");
if(locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onLocationChanged(Location location)
{
lastLocation = location;
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider)
{
Log.v(TAG, "onProviderEnabled");
}
#Override
public void onProviderDisabled(String provider)
{
Log.v(TAG, "onProviderDisabled");
}
public LatLng setCoordinate()
{
LatLng coordinate = new LatLng(getLocation().getLatitude(), getLocation().getLongitude());
LatLng coordinate = new LatLng(lt, lg);
return coordinate;
}
}
VenueModel.java
public class VenueModel implements Comparable<VenueModel>, Parcelable
{
private String id;
private String name;
private String address;
private String postalCode;
private String city;
private String state;
private Integer distance;
private double lat;
private double lng;
private LatLng coordinate;
private List<VenueModel> venueModelList;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void setVenueModelList(List<VenueModel> venueModelList)
{
this.venueModelList = venueModelList;
}
public List<VenueModel> getVenueModelList()
{
return venueModelList;
}
public LatLng getCoordinate() {
return coordinate;
}
public void setCoordinate(LatLng coordinate)
{
this.coordinate = coordinate;
}
#Override
public int compareTo(VenueModel venueModel) {
return this.distance.compareTo(venueModel.distance);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
dest.writeString(this.address);
dest.writeString(this.postalCode);
dest.writeString(this.city);
dest.writeString(this.state);
dest.writeValue(this.distance);
dest.writeDouble(this.lat);
dest.writeDouble(this.lng);
dest.writeParcelable(this.coordinate, flags);
dest.writeList(this.venueModelList);
}
public VenueModel() {
}
protected VenueModel(Parcel in) {
this.id = in.readString();
this.name = in.readString();
this.address = in.readString();
this.postalCode = in.readString();
this.city = in.readString();
this.state = in.readString();
this.distance = (Integer) in.readValue(Integer.class.getClassLoader());
this.lat = in.readDouble();
this.lng = in.readDouble();
this.coordinate = in.readParcelable(LatLng.class.getClassLoader());
this.venueModelList = new ArrayList<VenueModel>();
in.readList(this.venueModelList, VenueModel.class.getClassLoader());
}
public static final Parcelable.Creator<VenueModel> CREATOR = new Parcelable.Creator<VenueModel>() {
#Override
public VenueModel createFromParcel(Parcel source) {
return new VenueModel(source);
}
#Override
public VenueModel[] newArray(int size) {
return new VenueModel[size];
}
};
}
MapFragmentClass.java
public class MapFragmentClass extends Fragment implements OnMapReadyCallback
{
private MainActivity mA;
private GoogleMap gmap;
private static final LatLng coordinate = new LatLng(3.152182, 101.710602);
private LatLng coordinate2;
private ArrayList<VenueModel> venueModelList;
#Override
public void onAttach(Context context)
{
super.onAttach(context);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.activity_maps, container, false);
SupportMapFragment supportMapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
supportMapFragment.getMapAsync(this);
return v;
}
#Override
public void onMapReady(GoogleMap googleMap)
{
gmap = googleMap;
gmap.addMarker(new MarkerOptions().position(coordinate).title("Your location").draggable(true));
gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinate, 14));
}
}
Convert that Object to JSON string using GSON and then reconvert that string again to Object of list again.
MapFragment.getInstance(new Gson().toJson(venuList));
public static final getInstance(String venusStringListObj) {}
Bundle argument = new Bundle();
argument.putString("VENUES", venusStringListObj);
MapFragment fragment = new MapFragment();
fragment.setArgument(argument);
return fragment;
}
onCreate(...) {
private List<VenueModel> venueList;
Type listType = new TypeToken<ArrayList<VenueModel>>() {}.getType();
String venueStringRecvFromFragArg = getArguments().getString("VENUES");
venueList = new Gson().fromJson(venueStringRecvFromFragArg, listType);
}
MapFragmentClass mfc = new MapFragmentClass();
Bundle b = new Bundle();
b.putParcelableArrayList("Parcel", list);
mfc.setArguments(b);
FT.add(R.id.mapLayout, mfc);
FT.commit();
To access arrayList in MapFragment use this
ArrayList<VenueModel> myList = getArguments().getParcelableArrayList("Parcel");