The issue is the recycler view is not displaying the data after the onchanged method is called. Or if it does, it takes a long time to display the information. heres the code:
public void onFilter(Filters filters) {
Query query = mFireStore.collection("Products");
// Category (equality filter)
if (filters.hasCategory()) {
query = query.whereEqualTo(Product.FIELD_CATEGORY, filters.getCategory());
}
// City (equality filter)
if (filters.hasCity()) {
query = query.whereEqualTo(Product.FIELD_CITY, filters.getCity());
}
// Price (equality filter)
if (filters.hasPrice()) {
query = query.whereEqualTo(Product.FIELD_PRICE, filters.getPrice());
}
// Sort by (orderBy with direction)
if (filters.hasSortBy()) {
query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
}
// Limit items
query = query.limit(LIMIT);
Log.d("Query Info", query.toString());
FirestoreRecyclerOptions<Product> response = new FirestoreRecyclerOptions.Builder<Product>()
.setQuery(query,Product.class)
.build();
adapter = new FirestoreRecyclerAdapter<Product,ExploreViewholder>(response) {
#Override
public ExploreViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_explore_item, parent, false);
return new ExploreViewholder(view);
}
#Override
protected void onBindViewHolder(#NonNull ExploreViewholder holder, int position, #NonNull Product model) {
holder.productName.setText(model.getProductName());
holder.creatorName.setText(mUser.getDisplayName());
holder.productDesc.setText(model.getProductDescription());
// Glide.with(getContext())
// .load(model.getProductImageUrl())
// .into(holder.productImage);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
};
adapter.notifyDataSetChanged();
mRecycler.setAdapter(adapter);
}
This is where the method gets called, i get data from the viewmodel, no problem with that but the recycler view dosent display the data.
mViewModel.getMutableLiveData().observe(this, new Observer<Filters>() {
#Override
public void onChanged(#Nullable Filters filters) {
if (filters != null){
Log.d("ExploreFragObserver", filters.getCategory() + " ");
Log.d("ExploreFragObserver", filters.getCity() + "");
Log.d("ExploreFragObserver", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getPrice() + " ");
onFilter(filters);
Log.d("Done Loading Adapt", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getCategory() + " ");
Log.d("ExploreFragObserver", filters.getCity() + "");
Log.d("ExploreFragObserver", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getPrice() + " ");
// onFilter(Filters.getDefault());
}
}
});
A dialog fragment sets the data for the filters object in the viewmodel that both this fragment and the calling fragment both share.
I think you forgot to add adapter.startListening().
Related
I'm currently creating an android project (A Vehicle Rental System) with Firebase as a server. Realtime Database is alright, meanwhile, every time I try to access the images stored in the Firebase Storage, it always gives out an error:
W/NetworkRequest: no auth token for request
W/NetworkRequest: No App Check token for request.
W/NetworkRequest: error sending network request GET /*insert imageURI here*/ failed
W/ExponenentialBackoff: network unavailable, sleeping.
Here is my CustomAdapter:
private ArrayList<ModelItem> modelItemsArrayList;
private OnItemClickListener onItemClickListener;
private static final String TAG = "ModelAdapter: ";
private FirebaseStorage storage;
private StorageReference storageReference;
private Context context;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener;
}
public static class ModelAdapterViewHolder extends RecyclerView.ViewHolder{
public ImageView modelImageView;
public TextView modelTextView;
public TextView brandTextView;
public CardView modelCardView;
public ModelAdapterViewHolder(#NonNull View itemView, OnItemClickListener listener) {
super(itemView);
modelImageView = itemView.findViewById(R.id.cvFrontProfileImageView);
modelTextView = itemView.findViewById(R.id.cvModelTextView);
brandTextView = itemView.findViewById(R.id.cvBrandTextView);
itemView.setOnClickListener(view -> {
if(listener != null) {
int position = getBindingAdapterPosition();
if(position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
});
}
}
public ModelAdapter(ArrayList<ModelItem> modelItemsArrayList) {
Log.d(TAG, "ModelAdapter: called");
this.modelItemsArrayList = modelItemsArrayList;
Log.d(TAG, "ModelAdapter: modelItemsArrayList.size() = " + modelItemsArrayList.size());
}
#NonNull
#Override
public ModelAdapterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_item_cardview, parent, false);
return new ModelAdapterViewHolder(view, onItemClickListener);
}
#Override
public void onBindViewHolder(#NonNull ModelAdapter.ModelAdapterViewHolder holder, int position) {
//enter data from Firebase here
ModelItem currentItem = modelItemsArrayList.get(position);
Log.d(TAG, "modelItemsArraylist.size() = " + modelItemsArrayList.size());
storage = FirebaseStorage.getInstance();
storageReference = storage.getReferenceFromUrl("gs://roadtrip-7a905.appspot.com/")
.child(currentItem.getmImageResource());
try {
Log.d(TAG, "onBindViewHolder: inside try catch nest");
final File file = File.createTempFile("image", "jpg");
storageReference.getFile(file).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
holder.modelImageView.setImageBitmap(bitmap);
Log.d(TAG, "onBindViewHolder: " + file.getPath() + " successfully loaded");
}
}).addOnFailureListener(e -> {
//Toast.makeText(context, "Failed to Load image: " + currentItem.getmImageResource(),
//Toast.LENGTH_SHORT).show();
Log.d(TAG, "onBindViewHolder: addOnFailureListener: " + e.toString());
});
} catch (Exception e) {
Log.d(TAG, "onBindViewHolder: " + e.toString());
}
//holder.modelImageView.setImageResource(currentItem.getmImageResource()); ==> setFile from storage here
holder.modelTextView.setText(currentItem.getmModelText());
holder.brandTextView.setText(currentItem.getmBrandText());
Log.d(TAG, currentItem.getmImageResource() + "\n"
+ currentItem.getmModelText() + "\n"
+ currentItem.getmBrandText());
}
#Override
public int getItemCount() {
return modelItemsArrayList.size();
}
And here is my CustomClass
package com.example.roadtrip;
public class ModelItem {
private String mImageResource;
private String mModelText;
private String mBrandText;
public ModelItem() {
}
public ModelItem(String mImageResource, String mModelText, String mBrandText) {
this.mImageResource = mImageResource;
this.mModelText = mModelText;
this.mBrandText = mBrandText;
}
public String getmImageResource() {
return mImageResource;
}
public void setmImageResource(String mImageResource) {
this.mImageResource = mImageResource;
}
public String getmModelText() {
return mModelText;
}
public void setmModelText(String mModelText) {
this.mModelText = mModelText;
}
public String getmBrandText() {
return mBrandText;
}
public void setmBrandText(String mBrandText) {
this.mBrandText = mBrandText;
}
}
I've been stuck for more than a week already. Can someone help me?
P.S. It's my first time posting here. I apologize for the Logs in the code, I was just trying to debug.
Trying to retrieve data and place it into RecyclerView. But i always end up getting a null adapter error. My List Adapter is not being recognized.
I have initialized adapter and recyclerview in OnCreate(), OnViewCreated() nothing changed except app-crash.
Can you guys shed any light please?
My List Adapter:
public class PostListAdapter extends RecyclerView.Adapter<PostListAdapter.ViewHolder>{
private static final String TAG = "PostListAdapter";
private static final int NUM_GRID_COLUMNS = 3;
private ArrayList<Post> mPosts;
private Context mContext;
public class ViewHolder extends RecyclerView.ViewHolder{
SquareImageView mPostImage;
public ViewHolder(View itemView) {
super(itemView);
mPostImage = (SquareImageView) itemView.findViewById(R.id.post_image);
int gridWidth = mContext.getResources().getDisplayMetrics().widthPixels;
int imageWidth = gridWidth/NUM_GRID_COLUMNS;
mPostImage.setMaxHeight(imageWidth);
mPostImage.setMaxWidth(imageWidth);
}
}
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(mContext);
public PostListAdapter(Context context, ArrayList<Post> posts) {
mPosts = posts;
mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_view_post, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(mContext));
UniversalImageLoader.setImage(mPosts.get(position).getImage(), holder.mPostImage);
//GlideApp.with(mContext).load(mPosts.get(position)).into(holder.mPostImage);
//imageLoader.displayImage(mPosts.get(position).getImage(), holder.mPostImage);
final int pos = position;
holder.mPostImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: selected a post");
//TODO
//view the post in more detail
}
});
}
#Override
public int getItemCount() {
return mPosts.size();
}
}
My Fragment (where i initiliaze adapter and recyclerview):
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
mFilters = view.findViewById(R.id.ic_search);
mSearchText = view.findViewById(R.id.input_search);
mRecyclerView = view.findViewById(R.id.recyclerView);
mFrameLayout = view.findViewById(R.id.container);
getElasticSearchPassword();
init();
return view;
}
private void setupPostsList(){
RecyclerViewMargin itemDecorator = new RecyclerViewMargin(GRID_ITEM_MARGIN, NUM_GRID_COLUMNS);
mRecyclerView.addItemDecoration(itemDecorator);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), NUM_GRID_COLUMNS);
mRecyclerView.setLayoutManager(gridLayoutManager);
mAdapter = new PostListAdapter(getActivity(), mPosts);
mRecyclerView.setAdapter(mAdapter);
}
private void init(){
mFilters.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: navigating to filters activity.");
Intent intent = new Intent(getActivity(), FiltersActivity.class);
startActivity(intent);
}
});
mSearchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
||actionId == EditorInfo.IME_ACTION_DONE
|| event.getAction() == KeyEvent.ACTION_DOWN
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER){
mPosts = new ArrayList<Post>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ElasticSearchAPI searchAPI = retrofit.create(ElasticSearchAPI.class);
HashMap<String, String> headerMap = new HashMap<String, String>();
headerMap.put("Authorization", Credentials.basic("", mElasticSearchPassword));
String searchString = "";
if(!mSearchText.equals("")){
searchString = searchString + mSearchText.getText().toString() + "*";
}
if(!mPrefCity.equals("")){
searchString = searchString + " city:" + mPrefCity;
}
if(!mPrefStateProv.equals("")){
searchString = searchString + " state_province:" + mPrefStateProv;
}
if(!mPrefCountry.equals("")){
searchString = searchString + " country:" + mPrefCountry;
}
Call<HitsObject> call = searchAPI.search(headerMap, "AND", searchString);
call.enqueue(new Callback<HitsObject>() {
#Override
public void onResponse(Call<HitsObject> call, Response<HitsObject> response) {
HitsList hitsList = new HitsList();
String jsonResponse = "";
try{
Log.d(TAG, "onResponse: server response: " + response.toString());
if(response.isSuccessful()){
hitsList = response.body().getHits();
}else{
jsonResponse = response.errorBody().string();
}
Log.d(TAG, "onResponse: hits: " + hitsList);
for(int i = 0; i < hitsList.getPostIndex().size(); i++){
Log.d(TAG, "onResponse: data: " + hitsList.getPostIndex().get(i).getPost().toString());
mPosts.add(hitsList.getPostIndex().get(i).getPost());
}
Log.d(TAG, "onResponse: size: " + mPosts.size());
//setup the list of posts
setupPostsList();
}catch (NullPointerException e){
Log.e(TAG, "onResponse: NullPointerException: " + e.getMessage() );
}
catch (IndexOutOfBoundsException e){
Log.e(TAG, "onResponse: IndexOutOfBoundsException: " + e.getMessage() );
}
catch (IOException e){
Log.e(TAG, "onResponse: IOException: " + e.getMessage() );
}
}
#Override
public void onFailure(Call<HitsObject> call, Throwable t) {
Log.e(TAG, "onFailure: " + t.getMessage() );
Toast.makeText(getActivity(), "search failed", Toast.LENGTH_SHORT).show();
}
});
}
return false;
}
});
}
public void viewPost(String postId){
ViewPostFragment fragment = new ViewPostFragment();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
Bundle args = new Bundle();
args.putString(getString(R.string.arg_post_id), postId);
fragment.setArguments(args);
transaction.replace(R.id.container, fragment, getString(R.string.fragment_view_post));
transaction.addToBackStack(getString(R.string.fragment_view_post));
transaction.commit();
mFrameLayout.setVisibility(View.VISIBLE);
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(getActivity()));
}
#Override
public void onResume() {
super.onResume();
getFilters();
}
private void getElasticSearchPassword(){
Log.d(TAG, "getElasticSearchPassword: retrieving elasticsearch password.");
Query query = FirebaseDatabase.getInstance().getReference()
.child(getString(R.string.node_elasticsearch))
.orderByValue();
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot singleSnapshot = dataSnapshot.getChildren().iterator().next();
mElasticSearchPassword = singleSnapshot.getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getFilters(){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
mPrefCity = preferences.getString(getString(R.string.preferences_city), "");
mPrefStateProv = preferences.getString(getString(R.string.preferences_state_province), "");
mPrefCountry = preferences.getString(getString(R.string.preferences_country), "");
Log.d(TAG, "getFilters: got filters: \ncity: " + mPrefCity + "\nState/Prov: " + mPrefStateProv
+ "\nCountry: " + mPrefCountry);
}
}
It seems like you never call the method setupPostsList(). You should move your code in Fragment from onCreateView() to onViewCreated() - that's the mehod where all views in fragment are created and you can use findViewById(). First find all view by ids and then call method setupPostsList() to set up the recycle view.
this getItemViewType()
public int getItemViewType(int position) {
boolean type = _arr_GameList.get(position).isFirstComment();
if (type) {
return 0;
} else {
return 1;
}
}
After that set the view holder type wise but not display data . i used one arraylist but i want to two arraylist position first parent and second chhailed position
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
object = _arr_GameList.get(position);
if (object != null) {
if (object.isFirstComment()) {
setData(holder, position);
} else {
setData(holder, position);
}
}
}
After that set the view holder type wise but not display data . i used one arraylist but i want to two arraylist position first parent and second chhailed position
private void ReplyCommentServiceCall(final MyViewHolder holder, int position, String comment_id, String comment_body) {
Call<ResponseBody> call;
call = LaravelRetrofite.addgetClient().AddreplyComment("Bearer " + preferencesUtility.getAccessToken(), "Application/json", article_id, comment_id, comment_body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
if (response.isSuccessful()) {
Log.v("Articalereplycomment", response.toString());
Log.v("replygetposition", "" + position);
boolean type = _arr_GameList.get(position).isFirstComment();
Log.v("layouttype", "" + type);
object = _arr_GameList.get(position);
ArticleCommentsModel articleCommentsModel = _arr_GameList.get(position + 1);
articleCommentsModel.setComment_body(comment_body);
articleCommentsModel.setDeleteCommentOption("1");
articleCommentsModel.setFirstComment(false);
_arr_GameList.add(articleCommentsModel);
setData(holder, position + 1);
notifyDataSetChanged();
} else {
// error case
switch (response.code()) {
case 404:
NetworkUtility.ToastFunction(mActivity, "not found");
break;
case 500:
NetworkUtility.ToastFunction(mActivity, "server broken");
break;
default:
NetworkUtility.ToastFunction(mActivity, "unknown error");
break;
}
}
} catch (Exception e) {
String message = e.getMessage().replace("java.lang.Throwable: ", "");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.v("Upload", t.getMessage());
String message = t.getMessage().replace("java.lang.Throwable: ", "");
}
});
}
are you sure you got the method right?
right now it seems that this if is useless.
both cases are the same.
if (object.isFirstComment()) {
setData(holder, position);
} else {
setData(holder, position);
}
I am new to android development.I have a recyclerview with Viewholder for displaying photo.I have implement like feature in my app but only problem that I am facing is when I add a like on the photo the like does not show on photo I liked instead it is showing like on another photo that is down below,when I see in firebase database it looks fine but it does not display in the right position in recycler view.
I think it is not updating position how can I solve this?
this is my adapter class
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position) {
// mHolder = holder;
photo = moviesList.get(position);
// final VideoHolder viewHolder2 = (VideoHolder)holder;
int viewType = getItemViewType(holder.getAdapterPosition());
switch ( viewType ) {
case IMAGE_TYPE:
PhotoHolder photoview = (PhotoHolder) holder;
mPhotoHolder = photoview;
getCurrentUsername();
getLikesPhotoString();
final ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(getItem(position).getImage_path(),photoview.image);
photoview.mHeart.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
addNewPhotolike(mPhotoHolder);
}
#Override
public void unLiked(LikeButton likeButton) {
removePhotolike(mPhotoHolder);
}
});
photoview.Star.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
}
#Override
public void unLiked(LikeButton likeButton) {
}
});
break;
case VIDEO_TYPE:
final VideoHolder viewHolder2 = (VideoHolder)holder;
mVideoHolder = viewHolder2;
break;
}
}
#Override
public int getItemCount() {
return moviesList.size();
}
public Photo getItem(int position) {
return moviesList.get(position);
}
#Override
public int getItemViewType ( int position ) {
int viewType;
if (moviesList.get(position).getType_post().contains("Photo")) {
viewType = IMAGE_TYPE;
} else{
viewType = VIDEO_TYPE;
}
return viewType;
}
this is were photo like is added to firebase
private void addNewPhotolike(TestAdapter.PhotoHolder holder, final int position){
Log.d(TAG, "addNewlike: adding new like ");
String newLikeID = mReference.push().getKey();
Likes likes = new Likes();
likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
mReference.child(mContext.getString(R.string.dbname_photos))
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
mReference.child(mContext.getString(R.string.dbname_user_photos))
.child(getItem(position).getUser_id())
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
holder.mHeartPhoto.setLiked(true);
HashMap<String ,String> notificationData = new HashMap<>();
notificationData.put("from",FirebaseAuth.getInstance().getCurrentUser().getUid());
notificationData.put("type","likes");
notificationData.put("photo_desc",getItem(position).getDescription());
holder.mNotification.child(getItem(position).getUser_id()).push().setValue(notificationData).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
});
}
This is my code where like is retrieved from firebase and shown in text.
private void getLikesPhotoString(final TestAdapter.PhotoHolder holder, final int postion){
Log.d(TAG, "getLikesString: getting likes string");
try{
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
reference.keepSynced(true);
Query query = reference
.child(mContext.getString(R.string.dbname_photos))
.child(getItem(postion).getPhoto_id())
.child(mContext.getString(R.string.field_likes));
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
holder.usersPhoto = new StringBuilder();
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(mContext.getString(R.string.dbname_users))
.orderByChild(mContext.getString(R.string.field_user_id))
.equalTo(singleSnapshot.getValue(Likes.class).getUser_id());
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: found like: " +
singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(",");
}
String[] splitUsers = holder.usersPhoto.toString().split(",");
if( holder.usersPhoto.toString().contains(currentUsername + ",")){
holder.likephotobycurrentUser = true;
}else{
holder.likephotobycurrentUser = false;
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
// setupwidjets();
int length = splitUsers.length;
if(length == 1){
holder.mLIkePhotoString = "Liked by " + splitUsers[0];
}
else if(length == 2){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ " and " + splitUsers[1];
}
else if(length == 3){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ " and " + splitUsers[2];
}
else if(length == 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + splitUsers[3];
}
else if(length > 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + (splitUsers.length - 3) + " others";
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
//setup likes string
// setupLikePhotostring(holder, holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(true);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
if(!dataSnapshot.exists()){
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
//setupwidjets();
// setupLikePhotostring(holder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(false);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}catch (NullPointerException e){
Log.e(TAG, "removeStar: NullPointer"+e.getMessage());
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
// setupLikePhotostring(mPhotoHolder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
}
Change this line
photo = moviesList.get(holder.getAdapterPosition());
to
photo = moviesList.get(position);
where position variable is same as we got in below function
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position);
And also change holder.getAdapterPosition() to position in onBindViewHolder(...) function.
I'm working on a chat app using nkzawa socket-io library. I have successfully sent messages to server and retrieved them in my log cat. I am unable to update the ui as the get message event was not done in the adapter.
I want to be able to separate the messages based on uid as mine or others and update ui properly. So far, I've been confused how to go about the adapter, should I retrieve the messages in adapter or in main UI?
Here's my adapter code:
public class MessagesAdapter extends RecyclerView.Adapter<MessagesViewHolder> {
private static final String TAG = MessagesAdapter.class.getSimpleName();
private Context context;
private DBHelper helper;
private TingTingUser user;
private List<HomeMessage> messageList;
public MessagesAdapter(Context context, List<HomeMessage> messageList) {
this.context = context;
this.messageList = messageList;
helper = new DBHelper(context);
}
#Override
public MessagesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View msgView = LayoutInflater.from(parent.getContext()).inflate(R.layout.messages_layout, parent, false);
return new MessagesViewHolder(msgView);
}
#Override
public void onBindViewHolder(MessagesViewHolder holder, int position) {
HomeMessage message = messageList.get(position);
//holder.upDateUI();
}
#Override
public int getItemCount() {
if (messageList.size() == 0) {
return 0;
}
return messageList.size();
}
public void upDateUI(String usersId) {
user = helper.getCurrentUser(1);
String currUid = user.getUserId();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.messages_layout, null, false);
MessagesViewHolder holder = new MessagesViewHolder(view);
Log.d(TAG, "Uid form DB is:\t" + currUid);
if (usersId != currUid) {
holder.mainLayout.setGravity(Gravity.LEFT);
holder.nameLayout.setVisibility(View.VISIBLE);
holder.msgHolderLayout.setBackgroundResource(R.drawable.receiver_msg_bkg);
} else {
holder.mainLayout.setGravity(Gravity.RIGHT);
holder.nameLayout.setVisibility(View.GONE);
holder.msgHolderLayout.setBackgroundResource(R.drawable.sender_msg_bkg);
}
} }
Here's my method to retrieve all socket messages:
private void getPublicMessages(){
String get_event = "cc-" + chatRoomId;
Log.d(TAG, "Get Event Name is:\t " + get_event.toString());
mSocket.on(get_event, new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONObject jsonObject = (JSONObject) args[0];
//JSONObject dataObject = jsonObject.getJSONObject();
String type = jsonObject.getString("type");
Log.d(TAG, "Message is of type:\t" + type);
JSONObject contentObject = jsonObject.getJSONObject("content");
String userId = contentObject.getString("userId");
String roomId = contentObject.getString("roomId");
String message = contentObject.getString("message");
String name = contentObject.getString("name");
String avatar = contentObject.getString("avatar");
Log.d(TAG, "Get Message is:\t" + message);
Log.d(TAG, "roomId:\t" + roomId);
Log.d(TAG, "Get userId is:\t" + userId);
Log.d(TAG, "Get name is:\t" + name);
Log.d(TAG, "Get avatar is:\t" + avatar);
TingTingUser otherUsers = new TingTingUser(userId, "Abhiram Labhani", "Unknown");
HomeMessage othersHomeMessages = new HomeMessage(message, otherUsers, System.currentTimeMillis());
List<HomeMessage> othersList = new ArrayList<>();
othersList.add(othersHomeMessages);
Log.d(TAG, "Other Messages size is:\t " + othersList.size());
messageList.add(othersHomeMessages);
messagesAdapter.notifyDataSetChanged();
Log.d(TAG, "All Messages list size is:\t " + messageList.size());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
The values like name, message, etc are coming directly in activity. How should I update the ui, will this adapter code work or I should put this method in adapter and update accordingly?
Thanks all.
First thing you have to add the message received to the data source list you use in the Adapter.
Second thing you have to call
recyclerView.getAdapter().notifyItemInserted(position)
OR
recycerView.getAdapter().notifyItemRangeInserted(positionStart, itemCount);
second one is used to notify that multiple items are added.