how are you? I am trying to add Google AdMob native ads to a recyclerview feed. I followed the instructions provided by the Google Developer Codelabs here. https://codelabs.developers.google.com/codelabs/admob-native-advanced-feed-android/#0. It mostly worked. I have the ads inserted and posts being displayed. But the problem is, I think, the number of total items to be displayed, my app's posts plus the ads. I'm testing it, so there are only four posts to be displayed plus one native ad. But the feed is only returning three posts plus the one ad. Here is the Home Activity:
private PostAdapter postAdapter;
private List<Post> postList;
private List<String> followingList;
List<Object> mRecyclerViewItems = new ArrayList<>();
public static final int NUMBER_OF_ADS = 1;
// The AdLoader used to load ads.
private AdLoader adLoader;
// List of native ads that have been successfully loaded.
private List<UnifiedNativeAd> mNativeAds = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mContext = HomeActivity.this;
setupRecyclerView();
loadNativeAds();
}
private void insertAdsInMenuItems() {
if (mNativeAds.size() <= 0) {
return;
}
int offset = (mRecyclerViewItems.size() / mNativeAds.size()) + 1;
Log.d(TAG, "insertAdsInMenuItems: m native ads value: " + mNativeAds);
Log.d(TAG, "insertAdsInMenuItems: post list value: " + postList);
Log.d(TAG, "insertAdsInMenuItems: offset value: " + offset);
int index = 0;
for (UnifiedNativeAd ad: mNativeAds) {
mRecyclerViewItems.add(index, ad);
index = index + offset;
Log.d(TAG, "insertAdsInMenuItems: index value: " + index);
}
}
private void loadNativeAds() {
AdLoader.Builder builder = new AdLoader.Builder(this, getString(R.string.ad_mob_native_ad_id));
adLoader = builder.forUnifiedNativeAd(
new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// A native ad loaded successfully, check if the ad loader has finished loading
// and if so, insert the ads into the list.
mNativeAds.add(unifiedNativeAd);
if (!adLoader.isLoading()) {
insertAdsInMenuItems();
}
}
}).withAdListener(
new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load, check if the ad loader has finished loading
// and if so, insert the ads into the list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to"
+ " load another.");
if (!adLoader.isLoading()) {
insertAdsInMenuItems();
}
}
}).build();
// Load the Native Express ad.
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS);
}
private void setupRecyclerView(){
recyclerView = findViewById(R.id.recycler_view_posts);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
postList = new ArrayList<>();
postAdapter = new PostAdapter(getApplicationContext(), postList, mRecyclerViewItems);
recyclerView.setAdapter(postAdapter);
checkFollowing();
}
private void checkFollowing(){
Log.d(TAG, "checkFollowing: compile following list...");
followingList = new ArrayList<>();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("following").child(currentUserID);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
followingList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
followingList.add(snapshot.getKey());
Log.d(TAG, "checkFollowing: following list array" + followingList);
}
displayPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void displayPosts(){
Log.d(TAG, "displayPosts: running....");
allPostsReference.orderByKey().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
try{
Post post = snapshot.getValue(Post.class);
for (String id : followingList){
if (post.getUser_id().equals(id)){
postList.add(post);
}
}try{
if (post.getUser_id().equals(currentUserID)){
postList.add(post);
}
}catch (NullPointerException e){
e.getMessage();
}
int postCount = (int)dataSnapshot.getChildrenCount();
Log.d(TAG, "displayPosts: post count of my timeline: " + postCount);
}catch (NullPointerException e){
e.getMessage();
}catch (DatabaseException e){
e.getMessage();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
That's how I am adding the native ads to mRecyclerViewItems and all of the posts to postList. The checkFollowing method is displaying only posts of those I am following, which at this point, is all of the posts in the Firebase Realtime Database. And this is the relevant portions of the Post Adapter class:
public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "PostAdapter";
// A menu item view type.
private static final int MENU_ITEM_VIEW_TYPE = 0;
// The unified native ad view type.
private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
public Context mContext;
public List<Post> mPost;
public List<Object> mRecyclerViewItems;
public PostAdapter(Context mContext, List<Post> mPost, List<Object> mRecyclerViewItems) {
this.mContext = mContext;
this.mPost = mPost;
this.mRecyclerViewItems = mRecyclerViewItems;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType){
case UNIFIED_NATIVE_AD_VIEW_TYPE:
View unifiedNativeLayoutView = LayoutInflater.from(
parent.getContext()).inflate(R.layout.layout_native_express_ad_container, parent, false);
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
case MENU_ITEM_VIEW_TYPE:
//fall through
default:
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_post_item, parent, false);
return new PostViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType){
case UNIFIED_NATIVE_AD_VIEW_TYPE:
UnifiedNativeAd nativeAd = (UnifiedNativeAd) mRecyclerViewItems.get(position);
populateNativeAdView(nativeAd, ((UnifiedNativeAdViewHolder) holder).getAdView());
break;
case MENU_ITEM_VIEW_TYPE:
//follow through
default:
final PostViewHolder postViewHolder = (PostViewHolder) holder;
Post post = (Post) mPost.get(position);
final String postKey = post.getPost_key();
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
publicUserReference = FirebaseDatabase.getInstance().getReference().child("public_user");
allPostsReference = FirebaseDatabase.getInstance().getReference().child("all_posts");
//some sample methods
postViewHolder.setInitialLayouts(postKey);
mVotes.setTextForVoteButtons(postKey, postViewHolder.voteOne, postViewHolder.voteTwo, postViewHolder.voteThree, postViewHolder.voteFour);
postViewHolder.getProfilephotoFullnameUsername(postKey);
postViewHolder.getVoteText(postKey);
postViewHolder.getDate(postKey);
postViewHolder.displayPhoto(postKey);
}
#Override
public int getItemCount() {
return mPost.size() + mRecyclerViewItems.size();
}
#Override
public int getItemViewType(int position) {
try{
Object recyclerViewItem = mRecyclerViewItems.get(position);
if (recyclerViewItem instanceof UnifiedNativeAd) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}
}catch (IndexOutOfBoundsException e){
e.printStackTrace();
}
return MENU_ITEM_VIEW_TYPE;
}
Sorry if that's a lot of code, I am just kind of confused. Like I said, only three of my four posts in the database are being returned. It's as if the native ad is taking its place instead of being added into the feed along with the post items. Is there something I am missing? Should I be sending something different from Home Activity to the Post Adapter? Any help would be appreciated. Thank you.
So you have List<Post> and Ads two types of Data need to present into a single RecyclerView .So now you need to merge both data into 1 single data source to be used in the RecyclerView.
Here is the example:
First: Create a data class that combine Post and Ads named PostAdsData:
public class PostAdsData {
public int getType() {
return type;
}
public UnifiedNativeAd getAds() {
return ads;
}
public Post getPost() {
return post;
}
public int type; // 1 is ads and 2 is post
public UnifiedNativeAd ads;
public Post post;
}
Second: Your adapter should look like this:
public class YourAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// A menu item view type.
private static final int MENU_ITEM_VIEW_TYPE = 0;
// The unified native ad view type.
private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
public List<PostAdsData> postAdsDataList;
public PostAdapter(Context mContext) {
this.context = mContext;
}
public void setPostAdsDataList(List<PostAdsData> postAdsData){ // we set the data for the recyclerView here
this.postAdsDataList = postAdsData;
notifyDataSetChanged();
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
// here do your thing as usual
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, final int position) {
int viewType = getItemViewType(position);
switch (viewType){
// here switch viewType as usual,but refer the data from postAdsDataList
}
}
#Override
public int getItemViewType(int position) {
if(postAdsDataList.get(position).getType() == 1){
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}else{
return MENU_ITEM_VIEW_TYPE;
}
}
#Override
public int getItemCount() {
if (postAdsDataList != null) {
return postAdsDataList.size();
} else {
return 0;
}
}
}
Third: In your HomeActivity, so here is the place you need to set the data(Post) into the RecyclerView,you need to "transform" the data inside List<Post> to List<PostAdsData> like this:
private void displayContent(List<Post> posts){
List<PostAdsData> postAdsDataList = new ArrayList<>();
for(Post item : posts) {
PostAdsData data = new PostAdsData();
data.ads = null;
data.post = item;
data.type = 2; // here 1 for ads, 2 will be post
postAdsDataList.add(data);
}
yourAdapter.setPostAdsDataList(postAdsDataList); // here set in the Posts data into the recyclerView
}
displayContent() function above should be called after you get the data from Firebase I assumed.So it will look like this:
private void displayPosts(){
//ALL OTHER STUFF
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(....){
// after your for loop
// then all the Post will added inside the List<Post>
}
// then we called here
displayContent(postList) // your postList
}
}
So now we done insert the posts. Therefore, when you get the UnifiedNativeAd from Google Admob,we also need to "transform" UnifiedNativeAd to postAdsData object,like this:
// add this to YourAdapter class
public void insertAdsToRecyclerView(UnifiedNativeAd ad){ // if more than 1 ads,then here should be a list,and use for loop at the code below
PostAdsData adsData = new PostAdsData();
adsData.post = null;
adsData.ads = ad;
adsData.type = 1;
postAdsDataList.add(0,adsData); // here will add the ads to the 1st item of the list
notifyItemInserted(0);
}
Then in your insertAdsInMenuItems() will become like this:
private void insertAdsInMenuItems() {
postAdapter.insertAdsToRecyclerView(mNativeAds.get(0))// cause i seen you request for 1 ad only
}
Hope you get the idea.Now we successfully merge both Post and Ad into 1 data source.So it will easier for us to present in RecylerView.
Related
I am creating a chat program with Android Studio, and I am having trouble figuring out a way to show a list of messages that are left aligned for incoming messages and right aligned for outgoing messages. Right now, they are all left aligned.
What is the simplest way to left and right align text based on if the user id is the same as the current logged in user id? Below is what it looks like right now.
Current List View Sample
Assuming you are using Firebase for this app and getting the currently logged-in user details, you can make some changes to the Adapter class (MessageAdapter in this example).
Credits to numerous youtube videos and online resources that I used to do this in my app
Create chat_item_right.xml and chat_item_left.xml for 2 different users
Make some changes in the MessageAdapter class
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
public static final int MSG_TYPE_LEFT = 0;
public static final int MSG_TYPE_RIGHT = 1;
private Context mContext;
private List<Chat> mChat;
private String imageurl;
private FirebaseUser firebaseUser;
public MessageAdapter(Context mContext, List<Chat> mChat, String imageurl) {
this.mContext = mContext;
this.mChat = mChat;
this.imageurl = imageurl;
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Get the view type and create the right view
View view;
if (viewType == MSG_TYPE_RIGHT) {
view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false);
}
else {
view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false);
}
return new MyViewHolder(view);
}
// Method to get each chat message and show it
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Chat chat = mChat.get(position);
if (imageurl.equals("default")) {
holder.profile_image.setImageResource(R.mipmap.ic_launcher);
}
else {
Glide.with(mContext).load(imageurl).into(holder.profile_image);
}
if (chat.getType().equals("text")) {
holder.show_message.setText(chat.getMessage());
}
else if (chat.getType().equals("image")) {
// Depends on your code here
Glide.with(mContext).load(chat.getMessage()).into(holder.image_message);
}
}
#Override
public int getItemCount() {
return mChat.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView show_message, txt_seen;
private ImageView profile_image, image_message;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
show_message = itemView.findViewById(R.id.show_message);
profile_image = itemView.findViewById(R.id.profile_image);
txt_seen = itemView.findViewById(R.id.txt_seen);
image_message = itemView.findViewById(R.id.image_message);
}
}
#Override
public int getItemViewType(int position) {
// If i'm the sender show message on right else show it on left
if (mChat.get(position).getSender().equals(firebaseUser.getUid())) {
return MSG_TYPE_RIGHT;
}
else {
return MSG_TYPE_LEFT;
}
}
}
Call this in your MessageActivity or Fragment class
private MessageAdapter messageAdapter;
private List<Chat> mChat;
private DatabaseReference reference;
private FirebaseUser firebaseUser;
private String userid;
. // All your relevant code here
.
.
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
// You should have stored the current user the moment you have logged in
// in SharedPrefs perhaps (or DataStore or etc) so that we can compare later
// during set view_item to left or right
// For e.g sending the userID as bundle from Login Page to MessageActivity
// intent = new Intent(this, MessageActivity.class);
// bundle.putString("userid", user);
userid = intent.getStringExtra("userid");
private void readMessages(final String myId, final String userid, final String imageurl) {
mChat = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("Chats");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mChat.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Chat chat = snapshot.getValue(Chat.class);
// Add to chat list only messages between you and the sender
assert chat != null;
// The below code depends on your Chat object class
// So please modify accordingly
if (chat.getReceiver() != null && chat.getSender() != null) {
if (chat.getReceiver().equals(myId) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(myId)) {
mChat.add(chat);
}
}
}
// Create a new adapter and set it to our view
messageAdapter = new MessageAdapter(MessageActivity.this, mChat, imageurl);
recyclerView.setAdapter(messageAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
// Call the function
readMessages(firebaseUser.getUid(), userid, user.getImageURL());
When I try to load more items when the user had scrolled to the end, a progress dialog is displayed and removed and then again displayed and then more items are displayed but progress dialog is still not removed from recycler view. And sometimes progress dialog is removed but still, it takes more time to display more items in recycler view. I'm using firestore addOnSuccessListener to retrieve items from cloud firestore and adding it to an arraylist and then adding native ads advanced to that arraylist and add the data to the recycler adapter.
Activity where recycler view items are displayed, MovieLists.java
public class MovieLists extends AppCompatActivity implements ItemInterface{
//nothing important just a comment
boolean runshowMovieOnce = true;
Query mQuery;
int loaderPosition;
DocumentSnapshot lastVisible;
String docId, catName, titleName;
ItemInterface itemInterface;
DatabaseReference listData;
String VideoId;
MovieListAdapter movieListAdapter;
RecyclerView movieLists;
// List of native ads that have been successfully loaded.
private List<UnifiedNativeAd> mNativeAds = new ArrayList<>();
List<Object> itemDatas = new ArrayList<>();
LinearLayoutManager layoutManager;
// The number of native ads to load.
public static final int NUMBER_OF_ADS = 2;
// The AdLoader used to load ads.
private AdLoader adLoader;
int index = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_lists);
MaterialToolbar mToolBar = (MaterialToolbar) findViewById(R.id.imagePreviewToolbar);
setSupportActionBar(mToolBar);
docId = getIntent().getStringExtra("documentId");
catName = getIntent().getStringExtra("catName");
titleName = getIntent().getStringExtra("titleName");
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
getSupportActionBar().setTitle(titleName);
}
movieLists = (RecyclerView)findViewById(R.id.movie_lists);
layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
itemInterface = this;
loadMovies();
}
#Override
public void onFirebaseLoadSuccess(List<Object> itemDataList) {
loadNativeAds();
}
#Override
public void onFirebaseLoadFailed(String message) {
}
#SuppressLint("MissingPermission")
private void loadNativeAds() {
AdLoader.Builder builder = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/8135179316");
adLoader = builder.forUnifiedNativeAd(
new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// A native ad loaded successfully, check if the ad loader has finished loading
// and if so, insert the ads into the list.
mNativeAds.add(unifiedNativeAd);
if (!adLoader.isLoading()) {
insertAdsInMenuItems();
}
}
}).withAdListener(
new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load, check if the ad loader has finished loading
// and if so, insert the ads into the list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to"
+ " load another.");
if (!adLoader.isLoading()) {
insertAdsInMenuItems();
}
}
}).build();
// Load the Native ads.
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS);
}
private void insertAdsInMenuItems() {
if (mNativeAds.size() <= 0) {
return;
}
int offset = 3;
for (UnifiedNativeAd ad : mNativeAds) {
if (index<itemDatas.size()) {
itemDatas.add(index, ad);
}
index = index + offset;
}
//index = itemDatas.size() - 3;
if (runshowMovieOnce){
showMoviesList();
}
runshowMovieOnce = false;
}
private void showMoviesList() {
movieLists.setLayoutManager(layoutManager);
movieListAdapter = new MovieListAdapter(movieLists,MovieLists.this,itemDatas);
movieLists.setHasFixedSize(true);
movieLists.setAdapter(movieListAdapter);
movieListAdapter.setLoadMore(new ILoadMore() {
#Override
public void onLoadMore() {
itemDatas.add(null);
movieLists.post(new Runnable() {
public void run() {
movieListAdapter.notifyItemInserted(itemDatas.size() - 1);
Log.d("load position insert", ""+(itemDatas.size()-1));
}
});
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
itemDatas.remove(itemDatas.size()-1);
movieListAdapter.notifyItemRemoved(itemDatas.size() - 1);
Log.d("load position rem", ""+(itemDatas.size()-1));
int previousListSize = itemDatas.size();
Log.d("previousListSize",""+previousListSize);
loadMovies();
int newListSize = itemDatas.size();
Log.d("newListSize",""+newListSize);
movieListAdapter.notifyDataSetChanged();
movieListAdapter.setLoaded();
}
},5000);
}
});
}
private void loadMovies() {
FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
CollectionReference mPostsCollection = mFirestore.collection(catName).document(docId).collection("listItem");
//Defining Query cursors
if (lastVisible == null){
mQuery = mPostsCollection.orderBy("pr", Query.Direction.ASCENDING)
.limit(6);
}else {
mQuery = mPostsCollection.orderBy("pr", Query.Direction.ASCENDING)
.startAfter(lastVisible)
.limit(6);
}
mQuery.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
for (QueryDocumentSnapshot documentSnapshot : documentSnapshots){
ItemData itemData = documentSnapshot.toObject(ItemData.class);
itemDatas.add(itemData);
Log.d("movie name",itemData.getVn());
}
// Get the last visible document
if (documentSnapshots.size() > 0)
lastVisible = documentSnapshots.getDocuments()
.get(documentSnapshots.size() -1);
onFirebaseLoadSuccess(itemDatas);
}
});
}
}
MovieListAdapter.java
public class MovieListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<Object> itemDatas;
Context context;
String urlStart = "https://i1.ytimg.com/vi/";
String urlLast = "/mqdefault.jpg";
private static final int MOVIE_ITEM_VIEW_TYPE = 0;
private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
private final int VIEW_TYPE_LOADING = 2;
boolean isLoading;
ILoadMore loadMore;
int visibleThreshold ;
int lastVisibleItem,totalItemCount;
View itemV;
public MovieListAdapter(RecyclerView recyclerView, Context context, #NonNull List<Object> itemData) {
this.itemDatas = itemData;
this.context = context;
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager)recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
visibleThreshold = linearLayoutManager.getChildCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && (visibleThreshold + lastVisibleItem) >= totalItemCount){
if (loadMore != null){
loadMore.onLoadMore();
isLoading = true;
}
}
}
});
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
View unifiedNativeLayoutView = LayoutInflater.from(
parent.getContext()).inflate(R.layout.ad_unified,
parent, false);
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
case VIEW_TYPE_LOADING:
View viewL = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
return new LoadingViewHolder(viewL);
case MOVIE_ITEM_VIEW_TYPE:
// Fall through.
default: {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie_list, parent, false);
return new MovieListAdapter.MovieListsMyViewHolder(view);
}
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder myViewHolder, int i) {
//int viewType = getItemViewType(i);
if (myViewHolder instanceof MovieListAdapter.MovieListsMyViewHolder){
MovieListsMyViewHolder movieListsMyViewHolder = (MovieListsMyViewHolder) myViewHolder;
ItemData model = (ItemData)itemDatas.get(i);
movieListsMyViewHolder.txt_item_title.setText(model.getVn());
String urlImage = urlStart + model.getVi() + urlLast;
Log.e("urlImage", urlImage);
Glide.with(context)
.load(urlImage)
.placeholder(R.drawable.placeholder)
.error(R.drawable.placeholder)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.into(movieListsMyViewHolder.img_title);
movieListsMyViewHolder.setiItemClickListener(new IItemClickListener() {
#Override
public void onItemclickListener(View view, int position) {
ItemData itemData = new ItemData(model.getVi(),model.getVn(),model.getVd(),model.getPr(),model.getTc(),model.getVvc());
Log.d("Tmdb ID",String.valueOf(model.getTc()));
MovieDetails.startActivity(context, ((MovieListsMyViewHolder) myViewHolder).transformationLayout, itemData);
}
});
}else if (myViewHolder instanceof UnifiedNativeAdViewHolder){
Object recyclerViewItems = itemDatas.get(i);
UnifiedNativeAd nativeAd = (UnifiedNativeAd) recyclerViewItems;
populateNativeAdView(nativeAd, ((UnifiedNativeAdViewHolder) myViewHolder).getAdView());
}else if (myViewHolder instanceof LoadingViewHolder){
LoadingViewHolder loadingViewHolder = (LoadingViewHolder)myViewHolder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}
#Override
public int getItemCount() {
return itemDatas.size();
}
public class MovieListsMyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
AppCompatTextView txt_item_title;
ImageView img_title;
IItemClickListener iItemClickListener;
CardView itemCardView;
TransformationLayout transformationLayout;
public void setiItemClickListener(IItemClickListener iItemClickListener) {
this.iItemClickListener = iItemClickListener;
}
public MovieListsMyViewHolder(#NonNull View itemView) {
super(itemView);
itemV = itemView;
txt_item_title = (AppCompatTextView) itemView.findViewById(R.id.item_movie_Title);
img_title = (ImageView)itemView.findViewById(R.id.item_movie_Image);
//itemCardView = (CardView)itemView.findViewById(R.id.item_cardview);
//itemCardView.setOnClickListener(this);
transformationLayout = (TransformationLayout)itemView.findViewById(R.id.transformationMovieLayout);
transformationLayout.setOnClickListener(this);
}
#Override
public void onClick(View view){
iItemClickListener.onItemclickListener(view,getAdapterPosition());
}
}
private void populateNativeAdView(UnifiedNativeAd nativeAd,
UnifiedNativeAdView adView) {
// Some assets are guaranteed to be in every UnifiedNativeAd.
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
#Override
public int getItemViewType(int position) {
//DocumentSnapshot itemData = getItem(position);
Object recyclerViewItem = itemDatas.get(position);
if (recyclerViewItem instanceof UnifiedNativeAd) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}else if (itemDatas.get(position) == null){
return VIEW_TYPE_LOADING;
}else {
return MOVIE_ITEM_VIEW_TYPE;
}
}
public void setLoadMore(ILoadMore loadMore){
this.loadMore = loadMore;
}
private class LoadingViewHolder extends RecyclerView.ViewHolder {
ProgressBar progressBar;
public LoadingViewHolder(#NonNull View itemView) {
super(itemView);
progressBar = itemView.findViewById(R.id.progressBar);
}
}
public void setLoaded(){
isLoading = false;
}
}
The short term answer: There's a lot going on in your code. If you just want to remove the loadingProgress, add a void viewsLoaded() method inside your LoadingViewHolder with progressbar.setVisibility(View.GONE), and inside onBindViewHolder method, on the if(myViewHolder instanceof LoadingViewHolder), call the viewsLoaded() method if viewHolder is not positioned as the last one on the Adapter.
The long term answer: If you want to enhance the performance, read about how to use DiffUtil.ItemCallback<> instead of using notifydatasetchanged(), which is used for simple small datasets. You have a list of objectData on your activity and another one on your adapter, read about using LiveData, databinding and MVVM pattern.
i suggest first of all you should get The linearLayoutManager inside The Scroll View Listener.
another suggestion is to not call movieListAdapter.notifyItemInserted(itemDatas.size() - 1); Async inside the Runnable because after you add a null into list The Adapter should be notify:
itemsData.add(null);
movieListAdapter.notifyItemInserted(itemsData.size() - 1);
another is in the line: itemDatas.remove(itemDatas.size()-1)
after you remove the item from list, The List size will decrease by one.
so this would be correct:
movieListAdapter.notifyItemRemoved(itemDatas.size());
i Hope these would help.
This question already has an answer here:
Deleting row from recycler view and firebase
(1 answer)
Closed 3 years ago.
I want to remove an item from my recyclerview using an if condition
Here is my code for my adapter class. What I want to do is remove from displaying if its status is equal to unlive I'm retrieving the data from firebase
ArrayList<Adapter_Hotels> hotelsList;
Context context;
public Hotels_Adapter(ArrayList<Adapter_Hotels> list, Context context) {
this.hotelsList = list;
this.context = context;
}
#NonNull
#Override
public MyHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.listview_layout, parent, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyHolder holder, int i) {
holder.hName.setText(hotelsList.get(i).getTitle());
holder.hAddress.setText(hotelsList.get(i).getProvince() + ", " + hotelsList.get(i).getCountry());
Picasso.get().load(hotelsList.get(i).getUrl_path()).fit().into(holder.hImage);
String status = hotelsList.get(i).getStatus();
if (status.equals("unlive")) {
removeItem(holder.getAdapterPosition());
}
}
#Override
public int getItemCount() {
return hotelsList.size();
}
public void removeItem(int position){
hotelsList.remove(position);
this.notifyItemRemoved(position);
}
My activity code
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot hotelsSnapshot : dataSnapshot.getChildren()) {
Adapter_Hotels hotels = hotelsSnapshot.getValue(Adapter_Hotels.class);
String hotel_status = hotels.getStatus();
String hotel_name = hotels.getTitle();
String hotel_image = hotels.getUrl_path();
String hotel_province = hotels.getProvince();
String hotel_country = hotels.getCountry();
String hn = hotels.setTitle(hotel_name);
String hi = hotels.setUrl_path(hotel_image);
String hp = hotels.setProvince(hotel_province);
String hc = hotels.setCountry(hotel_country);
String hs = hotels.setStatus(hotel_status);
hotelList.add(new Adapter_Hotels(hn, hi, hc, hp, hs));
Log.v("DSDS", String.valueOf(hotelList.size()));
dialog.dismiss();
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
hotelsAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
hotelsAdapter = new Hotels_Adapter(hotelList, getContext());
mListview.setLayoutManager(new LinearLayoutManager(getContext()));
mListview.setAdapter(hotelsAdapter);
To remove, you can add this line
hotelList.remove(getAdapterPosition());
Perform the above code inside onLongClick() method in the ViewHolder class.
#Override
public boolean onLongClick(View view) {
//You can generate one list from which user can choose to delete.
hotelList.remove(getAdapterPosition());
return true;
}
Hi there ! why don't you remove the line of your list before pass that to the adapter ?
You can define function in your Activity to do this , and then pass the final list to your adapter
I have successfully to get next page of post using Blogger's API, but i can't achieve the smooth scrolling of recyclerview, it look lagging.
I have tried using recyclerViewData.setNestedScrollingEnabled(false) and adapter.notifyDataSetChanged() but still doesn't work.
My point is How to achieve smooth of recyclerview. Any suggestion will be appreciate. thank is advance.
Here is my code
private void getData() {
showLoading(true);
final Call<ResponseBlogPost> postList = apiService.getListPost(GlobalVariable.APP_KEY);
postList.enqueue(new Callback<ResponseBlogPost>() {
#Override
public void onResponse(Call<ResponseBlogPost> call, Response<ResponseBlogPost> response) {
showLoading(false);
ResponseBlogPost responseBlogPost = response.body();
initDataView(responseBlogPost);
}
#Override
public void onFailure(Call<ResponseBlogPost> call, Throwable t) {
showLoading(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void initDataView(ResponseBlogPost listpost){
GlobalFunction.saveString(this,GlobalVariable.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
itemsList.addAll(listpost.getItems());
adapter = new MainAdapter(itemsList) {
#Override
public void load() {
if(nextPageToken==null){
return;
}
getNextListPost();
}
};
recyclerViewData.setAdapter(adapter);
recyclerViewData.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2,1);
staggeredGridLayoutManager.setGapStrategy(0);
recyclerViewData.setLayoutManager(staggeredGridLayoutManager);
}
private void getNextListPost(){
showLoading(true);
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
Call<ResponseBlogPost> call = apiService.getNexPageListPost(GlobalVariable.APP_KEY,nextPageToken);
call.enqueue(new Callback<ResponseBlogPost>() {
#Override
public void onResponse(Call<ResponseBlogPost> call, Response<ResponseBlogPost> response) {
showLoading(false);
ResponseBlogPost responseModel = response.body();
if(nextPageToken!=null){
initDataView2(responseModel);
}else{
Toast.makeText(MainActivity.this, "tidak ada data lagi ya", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseBlogPost> call, Throwable t) {
showLoading(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void initDataView2(ResponseBlogPost listpost){
GlobalFunction.saveString(this,GlobalVariable.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
itemsList.addAll(listpost.getItems());
adapter = new MainAdapter(itemsList) {
#Override
public void load() {
if(nextPageToken!=null){
getNextListPost();
}
}
};
recyclerViewData.setAdapter(adapter);
recyclerViewData.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
staggeredGridLayoutManager.setGapStrategy(0);
recyclerViewData.setLayoutManager(staggeredGridLayoutManager);
}
My Adapter Code :
public abstract class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainViewHolder>{
private List<BlogPostModel> responseBlogPost;
public MainAdapter(List<BlogPostModel> responseBlogPost) {
this.responseBlogPost = responseBlogPost;
}
public abstract void load();
#Override
public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main,parent,false);
return new MainViewHolder(view);
}
#Override
public void onBindViewHolder(final MainViewHolder holder, int position) {
final BlogPostModel model = responseBlogPost.get(position);
ArrayList<String> urlImage = pullLinks(model.getContent());
String firstImage = "";
for (int i = 0; i < urlImage.size(); i++) {
firstImage = urlImage.get(1);
GlideCustomLoading.setImageFromURL(holder.itemView.getContext(), urlImage.get(0)
,holder.avLoadingIndicatorView, holder.ivItemPost,holder.tvFailedLoadImage);
}
holder.tvTitleItemPost.setText(model.getTitle());
final String finalFirstImage = firstImage;
holder.llItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String id = String.valueOf(model.getId());
DetailPostActivity.start(holder.itemView.getContext(), id, finalFirstImage, model.getTitle(), model.getUrl());
}
});
if(position>=getItemCount()-1){
load();
}
}
#Override
public int getItemCount() {
return responseBlogPost.size();
}
public class MainViewHolder extends RecyclerView.ViewHolder{
CardView cardViewItemPost;
ImageView ivItemPost;
TextView tvTitleItemPost;
AVLoadingIndicatorView avLoadingIndicatorView;
TextView tvFailedLoadImage;
LinearLayout llItem;
public MainViewHolder(View itemView) {
super(itemView);
cardViewItemPost = itemView.findViewById(R.id.cardview_item_post);
ivItemPost = itemView.findViewById(R.id.iv_image_post);
tvTitleItemPost = itemView.findViewById(R.id.tv_title_post);
avLoadingIndicatorView = itemView.findViewById(R.id.avi_load);
tvFailedLoadImage = itemView.findViewById(R.id.tv_gagal_menampilkan_gambar);
llItem = itemView.findViewById(R.id.ll_item_post);
}
}
private ArrayList pullLinks(String html) {
ArrayList links = new ArrayList();
Elements srcs = Jsoup.parse(html).select("[src]"); //get All tags containing "src"
for (int i = 0; i < srcs.size(); i++) {
links.add(srcs.get(i).attr("abs:src")); // get links of selected tags
}
return links;
}
}
While I'm not familiar with Jsoup I'm reasonably confident that it's the source of your scroll lag.
You are calling the method pullLinks in your onBindViewHolder method which is called every time a new view is added to your RecyclerView. I'm assuming pullLinks does some pretty intensive work that takes some time to complete.
What you would be better off doing is to add all of the data to each item in your responseBlogPost List before loading it in to the adapter.
I am developing an android app that displays the ranks of students based on their marks retrieved from the firebase database. Everything is working fine but, when I update the marks in the db, it keeps the old data and adds the new data in the recyclerView. I can restart the app to refresh the data. But while it is still running, it shows the old data too.
Below is my firebase data:
Student1: {
c: 70,
cPlus: 90,
java: 70,
name: "Samson",
regno: "16sksb7034",
unix: 60
}
Student2: {
c: 20,
cPlus: 85,
java: 68,
name: "Samson",
regno: "16sksb7034",
unix: 86
}
Student3: {
c: 70,
cPlus: 70,
java: 80,
name: "Samson",
regno: "16sksb7034",
unix: 90
}
Here is my dataModel class:
public class Marks {
private String name;
private String regno;
private int c;
private int cPlus;
private int java;
private int unix;
private int percentage;
public Marks() {}
public Marks(int c, int cPlus, int java, int unix) {
this.c = c;
this.cPlus = cPlus;
this.java = java;
this.unix = unix;
}
public int getPercentage() {
return percentage;
}
public void setPercentage(int percentage) {
this.percentage = percentage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRegno() {
return regno;
}
public void setRegno(String regno) {
this.regno = regno;
}
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
public int getcPlus() {
return cPlus;
}
public void setcPlus(int cPlus) {
this.cPlus = cPlus;
}
public int getJava() {
return java;
}
public void setJava(int java) {
this.java = java;
}
public int getUnix() {
return unix;
}
public void setUnix(int unix) {
this.unix = unix;
}
}
class MarksComparator implements Comparator<Marks> {
#Override
public int compare(Marks marks1, Marks marks2) {
int Marks1Total = marks1.getPercentage();
int Marks2Total = marks2.getPercentage();
if (Marks2Total < Marks1Total) {
return -1;
} else if (Marks2Total > Marks1Total) {
return 1;
} else {
return 0;
}
}
}
Here's my activity class:
public class MarksFragment extends Fragment{
private List<Marks> mMarksList = new ArrayList<>();
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private FirebaseDatabase mDatabase;
private DatabaseReference mReference;
private int total=0;
public MarksFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_marks, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
// specify an adapter (see also next example)
/*mAdapter = new MyAdapter(getContext(),mMarksList);
mAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mAdapter);*/
//get Firebase Reference
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
mDatabase = FirebaseDatabase.getInstance();
mReference = mDatabase.getReference();
mReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return view;
}
public void findPercentage(Marks value) {
total =value.getC() + value.getcPlus() + value.getJava() + value.getUnix();
value.setPercentage(total);
}
private void fetchData(DataSnapshot dataSnapshot) {
Marks value = dataSnapshot.getValue(Marks.class);
Log.v("Marks Fragment", "" +value);
findPercentage(value);
mMarksList.add(value);
Collections.sort(mMarksList, new MarksComparator());
// specify an adapter (see also next example)
mAdapter = new MyAdapter(getContext(),mMarksList);
mAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mAdapter);
Here is my adapter class:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
private Context mContext;
private List<Marks> marksList;
public MyAdapter(Context mContext, List<Marks> marksList) {
this.mContext = mContext;
this.marksList = marksList;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mItemName, mItemRegNo, mItemNo, mTotal;
CircleImageView mImageView;
public MyViewHolder(View view) {
super(view);
mItemName = (TextView) view.findViewById(R.id.card_name);
mItemRegNo = (TextView) view.findViewById(R.id.card_regno);
mItemNo = (TextView) view.findViewById(R.id.item_id);
mImageView = (CircleImageView) view.findViewById(R.id.item_photo);
mTotal = view.findViewById(R.id.card_total);
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
Marks marks = marksList.get(position);
int count = position + 1;
holder.mItemName.setText("" + marks.getName());
holder.mItemRegNo.setText("" + marks.getRegno());
holder.mItemNo.setText("" + count);
holder.mImageView.setImageResource(R.drawable.after_cookie);
holder.mTotal.setText(""+ marks.getPercentage());
}
#Override
public int getItemCount() {
return marksList.size();
}
}
So the code does what its intended to do it retrieves the data and calculates the total and ranks the students. but when I update the data in firebase console the views in recyclerView duplicates temporarily. Like for example if I update Student1 unix value as 10 then two views will be shown in the recyclerView: 1 for previous value and 2 for updated value and again if I update the values it will yet show another views representing the new data without removing the old views. But if I restart recyclerView gets refreshed and its all ok but while I am running the app during the update it shows temporary duplicate views too.
I am new here and this is my first question so I can't even upload picture as you need 10 points to upload photo. I really hope someone help me out on this. I thank you in advance.
UPDATE
Here is link to the image:
When I start the app, the image is:
first Image
when I update the unix value of Student3, the image in recyclerView becomes like this:
After updating the data in firebase console
So, you see it adds new data as well as keeps the old data untill I restart.
Your problem is that you're never checking if the student already exists in your mMarksList so you're simply duplicating him by adding him again with new grades.
What I would do in you case is to add an unique id in firebase to each student.
Then you can check in your fetchData whether the student with that id is already in the array, delete him and add the new one.
private void fetchData(DataSnapshot dataSnapshot) {
Marks value = dataSnapshot.getValue(Marks.class);
Log.v("Marks Fragment", "" +value);
findPercentage(value);
// Get an iterator.
Iterator<Marks> ite = mMarksList.iterator();
while(ite.hasNext()) {
Marks iteValue = ite.next();
if(iteValue.getId().equals(value.getId())) ite.remove();
}
mMarksList.add(value);
....
}
Optionally To make that even cleaner, you can override the equals and hashcode methods in your Marks data model, so that a Marks object is considered the same if the id is equal. More
//ASSUMING THAT ID IS int
#Override
public int hashCode() {
return id;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (this.getClass() != obj.getClass()) return false;
Marks other = (Marks) obj;
if (this.getId != other.getId) {
return false;
}
return true;
}
Then it's possible to either use a hashmap, which will override the old student automatically or a arraylist as is and iterate through it before and check if a student equals your new student, like this:
private void fetchData(DataSnapshot dataSnapshot) {
Marks value = dataSnapshot.getValue(Marks.class);
Log.v("Marks Fragment", "" +value);
findPercentage(value);
// Use an iterator.
Iterator<Marks> ite = mMarksList.iterator();
while(ite.hasNext()) {
Marks iteValue = ite.next();
if(iteValue.equals(value)) ite.remove();
}
mMarksList.add(value);
....
}