guys I'm using multiple api request with the same response and displaying it into a recycling
view
but in those response I get a user_id instead of user name but I need to display the user name into the recyclerview
this image breaks down what i need to do : https://i.stack.imgur.com/IdQ6e.png
so this is my adapter class where I tried to make a hashmap using another api request and making a hashmap with <user_id,user_name> and trying to use it in the holder class to display the user name but it didn't work :
public class FollowupAdapter extends RecyclerView.Adapter {
Map<String, String> userMap1 = new HashMap<>();
private Context Context1 ;
private List<TraitementTicketModel> followuplist;
public FollowupAdapter(Context mContext, List<TraitementTicketModel> followuplist) {
this.Context1 = mContext;
this.followuplist = followuplist;
}
#Override
public int getItemViewType(int position) {
if(followuplist.get(position).getTaskcategories_id()!=null) {
return 3;
}else if (followuplist.get(position).getSolutiontypes_id()!=null){
return 2;
}
return 1;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater layoutInflater=LayoutInflater.from(Context1);
if (viewType==1){
view = layoutInflater.inflate(R.layout.followupitem, parent,false);
return new ViewHolderFollowup(view);
}else if (viewType==2){
view = layoutInflater.inflate(R.layout.solutionitem, parent,false);
return new ViewHolderSolution(view);
}
else
view = layoutInflater.inflate(R.layout.taskitem, parent,false);
return new ViewHolderTask(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
displayusers();
if(followuplist.get(position).getTaskcategories_id()!=null) {
ViewHolderTask viewHolderTask = (ViewHolderTask) holder;
viewHolderTask.users_id.setText(userMap1.get(followuplist.get(position).getUsers_id()));
viewHolderTask.date.setText(followuplist.get(position).getDate());
viewHolderTask.content.setText(html2text(followuplist.get(position).getContent()));
}else if(followuplist.get(position).getSolutiontypes_id()!=null){
ViewHolderSolution viewHolderSolution = (ViewHolderSolution) holder;
viewHolderSolution.users_id.setText(userMap1.get(followuplist.get(position).getUsers_id()));
viewHolderSolution.date.setText(followuplist.get(position).getDate());
viewHolderSolution.content.setText(html2text(followuplist.get(position).getContent()));
}
else {
ViewHolderFollowup viewHolderFollowup = (ViewHolderFollowup) holder;
viewHolderFollowup.users_id.setText(userMap1.get(followuplist.get(position).getUsers_id()));
viewHolderFollowup.content.setText(html2text(followuplist.get(position).getContent()));
viewHolderFollowup.titre.setText(followuplist.get(position).getTitre());
viewHolderFollowup.date.setText(followuplist.get(position).getDate());
}
}
#Override
public int getItemCount() { return followuplist.size(); }
public static class ViewHolderFollowup extends RecyclerView.ViewHolder{
TextView users_id;
TextView date;
TextView content;
TextView titre;
public ViewHolderFollowup(#NonNull View itemView) {
super(itemView);
users_id=itemView.findViewById(R.id.user_id_followup);
date =itemView.findViewById(R.id.date_followup);
content=itemView.findViewById(R.id.contenu_followup);
titre=itemView.findViewById(R.id.titre_followup);
}
}
public static class ViewHolderTask extends RecyclerView.ViewHolder {
TextView users_id;
TextView date;
TextView content;
public ViewHolderTask(#NonNull View itemView) {
super(itemView);
users_id=itemView.findViewById(R.id.user_id_task);
date =itemView.findViewById(R.id.date_task);
content=itemView.findViewById(R.id.contenu_task);
}
}
public static class ViewHolderSolution extends RecyclerView.ViewHolder{
TextView users_id;
TextView date;
TextView content;
public ViewHolderSolution(#NonNull View itemView) {
super(itemView);
users_id=itemView.findViewById(R.id.user_id_solution);
date =itemView.findViewById(R.id.date_solution);
content=itemView.findViewById(R.id.contenu_solution);
}
}
public static String html2text(String html) {
return Jsoup.parse(Jsoup.parse(html).text()).text();
}
public List addToList(List<TraitementTicketModel> list) {
if(this.followuplist.addAll(list)){
Sort(followuplist);
}
notifyDataSetChanged();
return this.followuplist;
}
private List Sort (List<TraitementTicketModel> datalist){
Collections.sort(datalist, new Comparator<TraitementTicketModel>() {
#Override
public int compare(TraitementTicketModel o1, TraitementTicketModel o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return datalist;
}
private void displayusers() {
SharedPreferences sp =Context1.getApplicationContext().getSharedPreferences("tokenPref", Context.MODE_PRIVATE);
String sestoken = sp.getString("token","");
Retrofit retrofit= RetrofitInstance.getRetrofitInstance();
final Api api= retrofit.create(Api.class);
Call<List<User>> call = api.getUser(sestoken);
call.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
if (response.code() != 200){
Log.e("TAG", "onResponse: something is wrong"+response.code() );
}
List<User> users = response.body();
for (User user : users) {
if (userMap.get(user.getId()) == null)
userMap.put(user.getId(), user.getName());
}
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
}
});
}
private Map<String, String> PutMap(HashMap<String, String> userMap) {
userMap1=userMap;
return userMap1;
}
}
this hashmap I tried didn't work appreciate any solution or idea I'm really stuck in this
Your adapter's job is to adapt a data model into a series of view holders, not to transform, combine, fetch, mutate, etc. a different series of data coming from different sources.
Ask yourself this question: if you could "magically" call an object like this repository.getList() that would return a List of Something and that Something had three fields:
class Something {
String id;
String userName;
String content;
String type; //maybe useful for the Adapter to pick what type...
... anything else you need
}
So you have a List<Something>() that you can pass to your adapter, wouldn't your adapter suddenly be super simple?
That's what you need to do; remove all the logic that does not belong in the adapter (I expect only to have a onCreateViewHolder onBindViewHolder getItemViewType and that's it).
You're making a big problem into your adapter, which already has a lot of other responsibilities to carry. This data problem (putting the user + id + content) in a single object is a problem of your data source/repository, and not the adapter of a recycler view.
Transform your data before you pass it to your adapter. Your life, your fellow developers, and the future you, will be grateful.
Related
I'm using RecyclerView to display some data from an API response using one adapter
but i want to display data from more then one API response (so i need to make more then one get request)
this is my adapter :
private Context Context1;
private List<TraitementTicketModel> followuplist;
public FollowupAdapter(Context mContext, List<TraitementTicketModel> followuplist) {
this.Context1 = mContext;
this.followuplist = followuplist;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v;
LayoutInflater layoutInflater=LayoutInflater.from(Context1);
v=layoutInflater.inflate(R.layout.followupitem,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.users_id.setText(followuplist.get(position).getUsers_id());
holder.date.setText(followuplist.get(position).getDate());
holder.titre.setText(followuplist.get(position).getTitre());
holder.content.setText(html2text(followuplist.get(position).getContent()));
}
#Override
public int getItemCount() {
return followuplist.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
TextView users_id;
TextView date;
TextView content;
TextView titre;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
users_id=itemView.findViewById(R.id.user_id_followup);
date =itemView.findViewById(R.id.date_followup);
content=itemView.findViewById(R.id.contenu_followup);
titre=itemView.findViewById(R.id.titre_followup);
}
}
public static String html2text(String html) {
return Jsoup.parse(Jsoup.parse(html).text()).text();
}
and this is the code to display the data into the recyclerview
SharedPreferences sp = getApplicationContext().getSharedPreferences("tokenPref", Context.MODE_PRIVATE);
String sestoken = sp.getString("token", "");
SharedPreferences sp1 = getApplicationContext().getSharedPreferences("idPref", Context.MODE_PRIVATE);
String id = sp1.getString("id", "");
Retrofit retrofit = RetrofitInstance.getRetrofitInstance();
final Api api = retrofit.create(Api.class);
Call<List<TraitementTicketModel>> call = api.getfollowup(id, sestoken);
call.enqueue(new Callback<List<TraitementTicketModel>>() {
#Override
public void onResponse(Call<List<TraitementTicketModel>> call, Response<List<TraitementTicketModel>> response) {
if (!response.isSuccessful()) {
Toast.makeText(getApplicationContext(),"Something is wrong !! ",Toast.LENGTH_LONG).show();
Log.e("TAG", "onResponse: something is wrong");
}
List<TraitementTicketModel> followups = response.body();
for (TraitementTicketModel followup : followups) {
followuplist.add(followup);
}
followuplist.add(firstfollowup());
PutDataIntoRecyclerView(followuplist);
}
#Override
public void onFailure(Call<List<TraitementTicketModel>> call, Throwable t) {
}
});
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
FollowupAdapter adapter =new FollowupAdapter(this,followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}
so is it possible to display data into one recylerview using one adapter and more then one API request .
Edit :
this is the TraitementTicketModel class :
public class TraitementTicketModel {
private String users_id;
private String date;
private String content;
private String titre;
public TraitementTicketModel(String users_id, String date, String content, String titre) {
this.users_id = users_id;
this.date = date;
this.content = content;
this.titre = titre;
}
public String getTitre() {
return titre;
}
public String getUsers_id() { return users_id; }
public String getDate() { return date; }
public String getContent() {
return content;
}
}
when i try to sort the list by date before i put it in the adapter the data doesn't show .
in the adapter class :
public List addToList(List<TraitementTicketModel> list) {
this.followuplist.addAll(list);
notifyDataSetChanged();
Collections.sort(followuplist, new Comparator<TraitementTicketModel>() {
#Override
public int compare(TraitementTicketModel o1, TraitementTicketModel o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return this.followuplist;
}
in the main activity :
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
Sort(followuplist);
if (adapter == null) {
adapter=new FollowupAdapter(this,followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}else {
adapter=new FollowupAdapter(this,adapter.addToList(followuplist));
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}
}
private List Sort (List<TraitementTicketModel> datalist){
Collections.sort(datalist, new Comparator<TraitementTicketModel>() {
#Override
public int compare(TraitementTicketModel o1, TraitementTicketModel o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return datalist;
}
so is it possible to display data into one recylerview using one adapter and more then one api request
Yes it's possible if all API responses have the same data scheme as the adapter list.
You can add a method in the adapter that accumulates the current list:
public addToList(List<TraitementTicketModel> list) {
this.followuplist.addAll(list);
notifyDataSetChanged();
}
Then make the adapter as a class field, to only be instantiated for the first response, and reuse it in further responses:
FollowupAdapter mAdapter;
Then if the adapter not instantiated, instantiate it with the initial list, otherwise accumulate the list:
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
if (mAdapter == null) {
mAdapter = new FollowupAdapter(this, followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
} else {
mAdapter.addToList(followuplist);
}
}
I'm creating an Android app, the data that i'm sending through intent is being retrieved every time i click on the item.
I'm sending the retrieved data(which it's a subcollection that is being retrieved every time i click on item) through the intent,and all data receives in an arraylist, so the listener don't know if the same data existed in the arraylist,because the data are in the other activity.
when i click for the first time the data displayed normally in ItemMarkerActivity but when i go back and click again on the same item i see the data load again in the recycler view,and added to the previous same data, i'm using the technique of removing the data onStop but it didn't work perfectly,because i need to close all activities to see that the data removed, i tried to send the CollectionReference through intent but i couldn't do. so I need a way of removing the data immediately after closing the activity, and if anyone has another approach for solving this problem it would better.
Thanks in advance
adapter.setOnItemClickListener(new MarketAdapterRecyclerView.OnItemClickListener() {
#Override
public void onItemClick(DocumentSnapshot documentSnapshot, int position) {
CollectionReference path = documentSnapshot.getReference().collection("ShoppingItems");
listener = path.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (e != null) {
return;
}
for (DocumentChange dc : queryDocumentSnapshots.getDocumentChanges()) {
if (dc.getType() == DocumentChange.Type.ADDED) {
item = dc.getDocument().toObject(Item.class);
itemList.add(item);
}
}
Intent intent = new Intent (shoppingActivity.this, ItemMarkerActivity.class);
Log.v(TAG,"###################################" + itemList.toString());
intent.putExtra("keyName", itemList);
startActivity(intent);
}
});
}
}
The Activity That Receives The data
The Manifest
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> implements Parcelable{
public ArrayList<Item> ItemList;
public Context mContext;
private onMallListener mOnMallListener;
private static final int NO_POSITION = -1;
public ItemAdapter(ArrayList<Item> ItemList, Context mContext, onMallListener mOnMallListener) {
this.ItemList = ItemList;
this.mContext = mContext;
this.mOnMallListener = mOnMallListener;
}
protected ItemAdapter(Parcel in) {
ItemList = in.createTypedArrayList(Item.CREATOR);
}
public static final Creator<ItemAdapter> CREATOR = new Creator<ItemAdapter>() {
#Override
public ItemAdapter createFromParcel(Parcel in) {
return new ItemAdapter(in);
}
#Override
public ItemAdapter[] newArray(int size) {
return new ItemAdapter[size];
}
};
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_card_view_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(view, mOnMallListener);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
Item item = ItemList.get(i);
viewHolder.itemType.setText(ItemList.get(i).getItemType());
Picasso.with(mContext)
.load(item.getImageUrl())
.fit()
.centerCrop().into(viewHolder.imageUrl);
}
#Override
public int getItemCount() {
return ItemList.size();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(ItemList);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View mView;
public TextView price;
public TextView description;
public TextView itemType;
public ImageView imageUrl;
onMallListener onMallListener;
public ViewHolder(#NonNull View itemView, onMallListener mOnMallListener) {
super(itemView);
mView = itemView;
itemType = (TextView) mView.findViewById(R.id.card_view_image_title);
imageUrl = (ImageView) mView.findViewById(R.id.card_view_image);
this.onMallListener = mOnMallListener;
mView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(mOnMallListener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
mOnMallListener.onMallClick(position);
}
}
}
}
public interface onMallListener{
void onMallClick(int position);
}
}
Save data using Room database in first activity and retrieve it in second.
In any place of your code (and in any activity's callback) you can clean db and all lists/recyclers which listen this data.
https://developer.android.com/training/data-storage/room
Hope it'll help
I have an activity with three fragments, each one with a separate RecyclerView with a bunch of items. When scrolling between fragments, the onClick() gets mixed up and click on an item in fragment 1 goes to the same position but for the item in fragment 3 therefore taking me to the wrong screen. Am I suppose to differentiate the pages in the custom onClick() method I have setup? All the fragments use the same adapter, so I am not sure if that is part to blame then? Not sure what code would be useful here, but here is my adapter class:
public class ExploreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static OnEntryClickListener mOnEntryClickListener;
private List<Explore> exploreList;
private List<String> trackedProjects;
private Context context;
private Typeface typeFace, italicTypeface, boldTypeface;
private int typeOfExplore;
private HashMap<String, Boolean> uniqueExploreItems;
private HashMap<String, Long> offSet;
private int firstSet, secondSet;
private boolean apiProcessing;
private String stringValue;
//firebase
private DatabaseReference mDatabase;
public void changeTracked(List<String> tracks) {
trackedProjects = tracks;
notifyDataSetChanged();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView projectTitle, projectCompany;
public ImageView projectPicture;
private ShineButton projectTrack;
public MyViewHolder(View view) {
super(view);
projectTitle = (TextView) view.findViewById(R.id.exploreProjectTitle);
projectCompany = (TextView) view.findViewById(R.id.exploreProjectCompany);
projectPicture = (ImageView) view.findViewById(R.id.exploreProjectPicture);
projectTrack = (ShineButton) view.findViewById(R.id.exploreProjectTrack);
view.setOnClickListener(this);
projectTrack.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mOnEntryClickListener != null) {
mOnEntryClickListener.onEntryClick(v, getAdapterPosition());
}
}
}
public ExploreAdapter(Context mContext, List<Explore> explores, List<String> trackedProj, int typeOfE, String strV, HashMap<String, Boolean> uniqueE, HashMap<String, Long> offs, Typeface myTypeface, Typeface myTypefaceItalic, Typeface myTypefaceBold) {
context = mContext;
exploreList = explores;
typeFace = myTypeface;
italicTypeface = myTypefaceItalic;
boldTypeface = myTypefaceBold;
typeOfExplore = typeOfE;
uniqueExploreItems = uniqueE;
offSet = offs;
stringValue = strV;
apiProcessing = true;
mDatabase = FirebaseDatabase.getInstance().getReference();
trackedProjects = trackedProj;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.explore_item, parent, false));
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
Explore proj = exploreList.get(position);
myViewHolder.projectTitle.setTypeface(boldTypeface);
myViewHolder.projectCompany.setTypeface(italicTypeface);
myViewHolder.projectTitle.setText(proj.getProjectTitle());
myViewHolder.projectCompany.setText(proj.getSubTitle());
//for updates
if(typeOfExplore == 1) {
String createImagePath = Constants.PHASES_IMAGE + proj.getProjectPicture();
Picasso.with(context).load(createImagePath).placeholder(R.drawable.default_liovinci_bg).resize(320, 240).into(myViewHolder.projectPicture);
} else {
String createImagePath = Constants.PROJECT_IMAGE + proj.getProjectPicture();
Picasso.with(context).load(createImagePath).placeholder(R.drawable.default_liovinci_bg).resize(320, 240).into(myViewHolder.projectPicture);
}
if(typeOfExplore == 1 || typeOfExplore == 2) {
myViewHolder.projectTrack.setVisibility(View.GONE);
} else {
if(trackedProjects != null && trackedProjects.contains(proj.getProjectId())) {
myViewHolder.projectTrack.setColorFilter(ContextCompat.getColor(context, R.color.actionBlue), PorterDuff.Mode.SRC_IN);
myViewHolder.projectTrack.setChecked(true);
} else {
myViewHolder.projectTrack.setColorFilter(ContextCompat.getColor(context, R.color.bottomBarGray), PorterDuff.Mode.SRC_IN);
}
}
If you are using view pager then it initialises all the fragments which you have bound to that view pager. So at last it will initialise last fragment and your adapter class will contains context from your last initialised fragment.
This is the reason. so to overcome your problem you should make different adapter for different fragment.
I started to work with Retrofit. In my application i have one RecyclerView with two ViewHolder's, where trying to get data from my models, in logs coming type:
#Override
public void onResponse(Call<DropDown> call, Response<DropDown> response) {
DropDown jsonResponse = response.body();
Log.d("type",jsonResponse.getForm().getmGroupss().get(1).getmControls().get(2).getTitle()+"");
adapter = new DataAdapter(response.body());
recyclerView.setAdapter(adapter);
}
How can I display this type in my RecyclerView, if there will be a few types?
Now i get next message:
09-13 09:20:40.958 2798-2798/com.random.secondproject E/RecyclerView: No adapter attached; skipping layout
DataAdapter:
public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final String TYPE_TEXTVIEW = "0";
public static final String TYPE_EDITVIEW = "1";
private DropDown mList;
public DataAdapter(DropDown list) {
this.mList = list;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case 0:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_numeric, parent, false);
return new NumericViewHolder(view);
case 1:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.drop_down_options, parent, false);
return new DropDownViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
DropDown object = mList.get(position);
if (object != null) {
switch (object.getTitle()){
case TYPE_TEXTVIEW:
((NumericViewHolder) holder).title.setText(String.valueOf(object.getTitle()));
break;
case TYPE_EDITVIEW:
((DropDownViewHolder) holder).title_options.setText(String.valueOf(object.getTitle()));
break;
}
}
}
#Override
public int getItemCount() {
if (mList == null)
return 0;
return mList.size();
}
#Override
public int getItemViewType(int position) {
DropDown object = mList.get(position);
if (object.getTitle().equals("drop_down_options"))
return 0;
else return 1;
}
public class NumericViewHolder extends RecyclerView.ViewHolder {
private TextView title;
public NumericViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
}
}
public class DropDownViewHolder extends RecyclerView.ViewHolder {
private EditText title_options;
public DropDownViewHolder(View itemView) {
super(itemView);
title_options = (EditText) itemView.findViewById(R.id.title_options);
}
As you can see, I'm going to take two types (TextView and EditText)
so I will write a few ways to model(array i think). For example, as I wrote in Log.d .
Everything seem ok to me in your adapter. Try to call recyclerView.invalidate(). The idea is that you draw your RecyclerView before calling the onResponse method. Thus, you have empty view. The invalidate() method will try to redraw the view.
There are some error so that onResponse function not call, or you do with element in recyclerview before onResponse called.
You need create an adapter with empty Dropdown
adapter = new DataAdapter(new Dropdown());
When onResponse called you only notifyDatasetChange to adapter, don't setAdapter again.
Or you put the code that pratice with element of recyclerview to onResponse.
Basically I have in my Parse database two columns "rank" and "rankCount" which are both numbers.
Rank represents the total rank of the item in that row and rankCount represents the number of people who ranked it.
What I'm trying to do is create a method which will sum the average between those two, make an Int out of the number(in case its a Double/Float) and display the corresponding number with stars in a RatingBar between 1-5 stars, inside a specified Fragment with a ListView in it.
Note: I don't want to make changes in the parse database because I'm using it for the iphone version of this app witch is already complete, but I'm having a more difficult time with android.
specific Fragment class:
public class RecommendedTab extends Fragment {
ListView recommendedListView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View tab_recommended = inflater.inflate(R.layout.tab_recommended, container, false);
recommendedListView = (ListView)tab_recommended.findViewById(R.id.recommendedList);
ParseQuery<ParseObject> query = ParseQuery.getQuery("Place");
new RemoteDataTask(){
protected void onPostExecute(List<Places> places) {
recommendedListView.setAdapter(new PlacesAdapter(getActivity(), places, null));
}
}.execute(query);
return tab_recommended;
}
}
Adapter class:
public class PlacesAdapter extends BaseAdapter{
private List<Places> places=null;
private List<Places> filteredPlaces=null;
LayoutInflater inflater;
ImageLoader imageLoader;
private Context context;
private Location loc;
public PlacesAdapter(Context context, List<Places> places, Location loc){
this.context = context;
this.places = places;
inflater = LayoutInflater.from(context);
imageLoader = new ImageLoader(context);
resetPlaces();
}
public void resetPlaces(){
filteredPlaces = places;
}
public void filter(String s){
//validation
filteredPlaces = new ArrayList<Places>();//
for(int i=0;i<places.size();i++){
if(places.get(i).getName().toLowerCase().contains(s.toLowerCase())){
filteredPlaces.add(places.get(i));
}
}
}
public class ViewHolder {
RatingBar ratingBar;
TextView name;
TextView type;
TextView adress;
TextView phone;
TextView hours;
TextView details;
ImageView image;
}
#Override
public int getCount() {
return filteredPlaces.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public Object getItem(int position) {
return filteredPlaces.get(position);
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.row_layout, null);
holder.name = (TextView)view.findViewById(R.id.placeName);
holder.type = (TextView) view.findViewById(R.id.placeType);
holder.image = (ImageView) view.findViewById(R.id.placeImage);
holder.ratingBar = (RatingBar)view.findViewById(R.id.placeRate);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.ratingBar.setOnRatingBarChangeListener(onRatingChangedListener(holder, position));
holder.ratingBar.setTag(position);
holder.ratingBar.setRating(places.get(position).getRatingStar());
holder.name.setText(places.get(position).getName());
holder.type.setText(places.get(position).getType());
imageLoader.DisplayImage(places.get(position).getImage(),
holder.image);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(context, PlaceDetails.class);
intent.putExtra("name", (places.get(position).getName()));
intent.putExtra("phone", (places.get(position).getPhone()));
intent.putExtra("hours", (places.get(position).getHours()));
intent.putExtra("rank", (places.get(position).getRatingStar()));
intent.putExtra("details", (places.get(position).getDetails()));
intent.putExtra("image", (places.get(position).getImage()));
context.startActivity(intent);
}
});
return view;
}
private RatingBar.OnRatingBarChangeListener onRatingChangedListener(final ViewHolder holder, final int position) {
return new RatingBar.OnRatingBarChangeListener() {
#Override
public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
places.get(position).setRatingStar(v);
}
};
}
}
class for the query:
public class RemoteDataTask extends AsyncTask<ParseQuery<ParseObject>, Void, List<Places>> {
#Override
protected List<Places> doInBackground(ParseQuery<ParseObject>... query) {
List<Places> places = new ArrayList<Places>();
try {
List<ParseObject> ob = query[0].find();
for (ParseObject place : ob) {
ParseFile image = (ParseFile) place.get("image");
Places p = new Places();
p.setName((String) place.get("name"));
p.setType((String) place.get("type"));
p.setHours((String) place.get("hours"));
p.setPhone((String)place.get("phone"));
p.setDetails((String) place.get("details"));
p.setImage(image.getUrl());
places.add(p);
}
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return places;
}
}
I have many other classes in my project but im quite sure they are irrelevant for my question.
PS: what is the android equevilant for Swift's "NSUserDefaults"?
i need to check if an item already been rated and disable the RatingBar.
There are several ways to do it, for example you can:
Add an instance variable int rank to class Place with needed setter & getter.
Using Math.round set to each Place rank rounded value of rank/rankCount, both you can get with relevant ParseObject.getDouble
And then when creating view for Place, just use it's predefined rank variable as a counter for needed stars.
Note:
it's better to use: ParseObject.getString
instead of (String) place.get("name") getting an Object and then casting to String as you did. It's also mentioned in it's Parse Documentation:
In most cases it is more convenient to use a helper function such as ParseObject.getString(String) or ParseObject.getInt(String).
Leave a comment if you need further assistance