Adapter in FirebaseUI is getting null - android

I've used firebase Recycler Adapter to get data. But always getting error,
Attempt to invoke virtual method 'void
androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)'
on a null object reference
My fragment is
public class MyBooksFragment extends BaseFragment {
private ShimmerFrameLayout mShimmerViewContainer;
private RecyclerView recyclerView ;
private FirebaseRecyclerAdapter adapter;
private FirebaseUser user= FirebaseAuth.getInstance().getCurrentUser();
#Override
public BaseFragment provideFragment() {
return new MyBooksFragment();
}
#Override
public View provideFragmentView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_books,parent,false);
mShimmerViewContainer=view.findViewById(R.id.mybook_shimmer_view_container);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view_books);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
fetchBooks(1);
FloatingActionButton fab = view.findViewById(R.id.addBookFab_);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), BookAdder.class);
startActivity(intent);
}
});
return view;
}
private FirebaseRecyclerOptions<Book> queryBuilderParser(){
Query bookQuery= FirebaseDatabase
.getInstance()
.getReference()
.child("Books")
.orderByChild("ownerID")
.equalTo(user.getUid());
FirebaseRecyclerOptions<Book> options =
new FirebaseRecyclerOptions.Builder<Book>()
.setQuery(bookQuery,Book.class)
.build();
return options;
}
protected void fetchBooks(int type)
{
Log.e("profile",type+" ");
FirebaseRecyclerOptions<Book> options;
Query bookQuery= FirebaseDatabase
.getInstance()
.getReference()
.child("Books")
.orderByChild("ownerID")
.equalTo(user.getUid());
options = new FirebaseRecyclerOptions.Builder<Book>()
.setQuery(bookQuery,Book.class)
.build();
Log.e("profile","inside fetchReviw "+options.getSnapshots());
adapter= new FirebaseRecyclerAdapter<Book, BookViewHolder>(options) {
#NonNull
#Override
public BookViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.book_row_item, parent, false);
return new BookViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull BookViewHolder bookViewHolder, int i, #NonNull Book book) {
bookViewHolder.book_name.setText(book.getBookName());
bookViewHolder.book_author.setText(book.getAuthors());
bookViewHolder.book_category.setText(book.getCategory());
bookViewHolder.book_rating.setText(book.getRating()+"");
Glide.with(getActivity()).load(book.getThumbnail()).into(bookViewHolder.img_thumbnail);
}
#Override
public void onDataChanged() {
if(getItemCount()>0 && mShimmerViewContainer!=null){
mShimmerViewContainer.stopShimmerAnimation();
mShimmerViewContainer.setVisibility(View.GONE);
}
}
#Override
public void onError(DatabaseError e) {
// Called when there is an error getting data. You may want to update
// your UI to display an error message to the user.
// ...
Log.e("profile","database error");
}
};
recyclerView.setAdapter(adapter);
}
}
Here, I've extended a base fragment which extends Fragment.

You haven't put the right arguments into the adapter. The adapter takes 4 arguments in:
Object class
List item layout resource
Viewholder Class
Query/firebase reference
Here is how it should look, also the adapter does a lot of the hard word so you only need to use the populateViewHolder function:
FirebaseRecyclerViewAdapter<Object, ObjectViewHolder> adapter = new FirebaseRecyclerViewAdapter<Object, ObjectViewHolder>
(Object.class, android.R.layout.*list_item_layout*, ObjectViewHolder.class, objectQuery) {
public void populateViewHolder(ObjectViewHolder ObjectViewHolder, Object Object) {
//in your case the following lines:
bookViewHolder.book_name.setText(book.getBookName());
bookViewHolder.book_author.setText(book.getAuthors());
bookViewHolder.book_category.setText(book.getCategory());
bookViewHolder.book_rating.setText(book.getRating()+"");
Glide.with(getActivity()).load(book.getThumbnail()).into(bookViewHolder.img_thumbnail);
}
};
recycler.setAdapter(mAdapter);

Related

Why is my FirestoreRecyclerView not automatically showing the latest items after I login to my application?

I have a problem with my FirestoreRecyclerView where it will not automatically show the latest items added when I login to the application. I have to manually scroll up the recyclerview, then the newly added items will be shown.
Brief description of my app: My application will record a log every minute.FirestoreRecyclerView should show the latest logs at the top of the recyclerview every minute.
My problem is, when I logged in at 3.53pm, the previous logs which I logged in at 3.16pm are shown instead.
However, if I scroll up, I will see the latest 3.53pm log:
I am not sure why this is happening. Is there a way to show the latest log without having to scroll up? Or is there a way to clear the FirestoreRecyclerView everytime I log in?
Logs Fragment Class:
public class UserLogsFragment extends Fragment implements UserLogsAdapter.OnListItemClick{
private RecyclerView mFirestoreList;
private FirebaseFirestore firebaseFirestore;
private UserLogsAdapter adapter;
private FirestoreRecyclerOptions<UserLogsModel> options;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_logs2, container, false);
firebaseFirestore = FirebaseFirestore.getInstance();
// Query from firebase
Query query = firebaseFirestore.collection("UOW_log") // TODO: filter by organisation ID
.orderBy("date", Query.Direction.DESCENDING);
// Recycler options
options = new FirestoreRecyclerOptions.Builder<UserLogsModel>()
.setLifecycleOwner(this)
.setQuery(query, new SnapshotParser<UserLogsModel>() {
#NonNull
#Override
public UserLogsModel parseSnapshot(#NonNull DocumentSnapshot snapshot) {
UserLogsModel userLogsModel = snapshot.toObject(UserLogsModel.class);
String docId = snapshot.getId();
userLogsModel.setDocument_id(docId);
return userLogsModel;
}
})
.build();
// Create recycler adapter
adapter = new UserLogsAdapter(options, this);
mFirestoreList = view.findViewById(R.id.firestore_list2);
mFirestoreList.setHasFixedSize(true);
mFirestoreList.setLayoutManager(new LinearLayoutManager(getContext(),
LinearLayoutManager.VERTICAL, false));
mFirestoreList.setAdapter(adapter);
return view;
}
#Override
public void onItemClick(UserLogsModel snapshot, int position) {
Log.d("ITEM_CLICK", "Clicked the item: " + position + " and the ID is: " + snapshot.getDocument_id());
//startActivity(new Intent(getActivity(), LogsDetailActivity.class));
Fragment fragment = UserLogDetailsFragment.newInstance(snapshot.getDocument_id());
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
//transaction.hide(getActivity().getSupportFragmentManager().findFragmentByTag("user_logs_fragment"));
transaction.replace(R.id.container, fragment, "user_log_details_fragment");
//transaction.add(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
/*
transaction.replace(android.R.id.content, fragment);
transaction.addToBackStack(null);//add the transaction to the back stack so the user can navigate back
// Commit the transaction
transaction.commit();
*/
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
Adapter class:
public class UserLogsAdapter extends FirestoreRecyclerAdapter<UserLogsModel, UserLogsAdapter.UserLogsViewHolder> {
private OnListItemClick onListItemClick;
public UserLogsAdapter(#NonNull FirestoreRecyclerOptions<UserLogsModel> options, OnListItemClick onListItemClick) {
super(options);
this.onListItemClick = onListItemClick;
}
#Override
protected void onBindViewHolder(#NonNull UserLogsViewHolder holder, int position, #NonNull UserLogsModel model) {
if(position != RecyclerView.NO_POSITION){
// Do your binding here
holder.doc_id.setText(model.getDocument_id());
}
//holder.doc_id.setText(model.getDocument_id());
Log.d("POSITION","Position: " + position);
}
#NonNull
#Override
public UserLogsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_logs_list_item_single2, parent, false);
return new UserLogsViewHolder(view);
}
// Viewholder class for user logs
protected class UserLogsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView doc_id;
public UserLogsViewHolder(#NonNull View itemView) {
super(itemView);
doc_id = itemView.findViewById(R.id.userLogs_recyView_docId2);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onListItemClick.onItemClick(getItem(getAdapterPosition()), getAdapterPosition());
}
}
public interface OnListItemClick{
void onItemClick(UserLogsModel snapshot, int position);
}
}

About opening a new activity in respond to a click on a RecyclerView item which is inside of a fragment

I'm loading some data into a RecyclerView from Firebase Realtime Database. This RecyclerView is in a fragment and I want to open a new activity when an item is clicked. But when i add the onClickListener to an item from the adapter, my click doesn't even recognized by the app. I'm not sure what I'm doing wrong here because this method worked fine for a RecyclerView when it is inside of a normal activity.
This is a project for my university and I should submit it tomorrow. So I can really use some help.
This is the my data Adapter class,
public class Adapter_NoLimit extends RecyclerView.Adapter<Adapter_NoLimit.LViewHolder> {
Context context;
ArrayList<Helper> list_nl;
public Adapter_NoLimit(Context context, ArrayList<Helper> list_nl) {
this.context = context;
this.list_nl = list_nl;
}
#NonNull
#Override
public Adapter_NoLimit.LViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.itemlist, parent, false);
return new LViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull Adapter_NoLimit.LViewHolder holder, int position) {
//final Helper temp = list_nl.get(position);
String fname_txt = list_nl.get(position).getFname();
String catg_txt = list_nl.get(position).getSpin();
String prof_img = list_nl.get(position).getProfile_url();
holder.setUsers(fname_txt, catg_txt, prof_img);
holder.f_name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity activity = (AppCompatActivity) v.getContext();
Intent i = new Intent(activity, UserProfile_VV.class);
i.putExtra("full name", fname_txt);
activity.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return list_nl.size();
}
public class LViewHolder extends RecyclerView.ViewHolder{
private TextView f_name, catG;
private ImageView profile_pic;
public LViewHolder(#NonNull View itemView) {
super(itemView);
f_name = itemView.findViewById(R.id.username_view);
catG = itemView.findViewById(R.id.category_view);
profile_pic = itemView.findViewById(R.id.userimage);
}
public void setUsers(String fname_txt, String catg_txt, String prof_img) {
f_name.setText(fname_txt);
catG.setText(catg_txt);
Picasso.get().load(prof_img).fit().into(profile_pic);
}
}
}
This is one of fragments,
public class Beauty_Frag extends Fragment {
RecyclerView recyclerView;
DatabaseReference reference, user_ref;
ArrayList<Helper> list;
Adapter adapter;
FirebaseAuth auth;
String uid;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_beauty, container, false);
recyclerView = v.findViewById(R.id.beauty_recycler_frag);
reference = FirebaseDatabase.getInstance().getReference();
user_ref = reference.child("users");
auth = FirebaseAuth.getInstance();
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
//searchField = findViewById(R.id.search_field);
list = new ArrayList<>();
adapter = new Adapter(getContext(), list);
recyclerView.setAdapter(adapter);
user_ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull /*#org.jetbrains.annotations.NotNull*/ DataSnapshot snapshot) {
for (DataSnapshot key : snapshot.getChildren()) {
if( key.child("spin").getValue().toString().equals("Beauty")) {
Helper helper = key.getValue(Helper.class);
list.add(helper);
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onCancelled(#NonNull /*#org.jetbrains.annotations.NotNull*/ DatabaseError error) {
}
});
return v;
}
}
You are very welcome if you have any solution.
Use below code for onClicklistner:
holder.f_name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context, UserProfile_VV.class);
i.putExtra("full name", fname_txt);
context.startActivity(i);
}
});

Recyclerview fetch existing data after delete an item from adapter and does not update properly

I try to implement a friend request feature in the fragment using custom adapter with firebase database. The problem is when a user accepts or delete someone request, it deletes from firebase but not properly update in the RecyclerView. this problems occurred in only runtime. If I refresh the page then my problem goes away.
Let I have two friend request. If I delete 2nd data then 2nd data will gone from RecyclerView but the problem is RecyclerView shows 1st data doubles. and if I delete 1st data then 1st data goes in the 2nd row and 2nd data came into the first row.
here is my database screenshot
Fragment class-
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_notification, container, false);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
return view;
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Custom Adapter -
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder> {
private Context context;
private List<Friend> friendList;
public NotificationAdapter(Context context, List<Friend> friendList) {
this.context = context;
this.friendList = friendList;
}
#NonNull
#Override
public NotificationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_notification_item, parent, false);
return new NotificationAdapter.NotificationViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
getUserInfo(holder.profileImage, holder.NotificationUserName, friend.getSenderID());
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest")
.child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return friendList.size();
}
private void getUserInfo(final CircleImageView prfileImage, final TextView NotificationUserName, String senderID) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(senderID);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Users users = dataSnapshot.getValue(Users.class);
NotificationUserName.setText(users.getUserName());
Picasso.with(context).load(users.getImageUrl()).into(prfileImage);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public class NotificationViewHolder extends RecyclerView.ViewHolder {
private TextView NotificationUserName;
private Button cancelRequestButton;
private CircleImageView profileImage;
public NotificationViewHolder(#NonNull View itemView) {
super(itemView);
NotificationUserName = itemView.findViewById(R.id.NotificationUserName);
cancelRequestButton = itemView.findViewById(R.id.cancelRequestBtn);
profileImage = itemView.findViewById(R.id.profileImage);
}
}
}
My APP Problems screenshot -
let I have two request
1) if I delete 2nd data 1st data show doubles:
2) if I delete 1st data, 1st data goes into 2nd row and 2nd data came into 1st row:
Replace
removeItem(position);
with
removeItem(holder.getAdapterPosition());
You initialize your recyclerView and adapter in onCreateView which was not appropriate.You have to override the method onViewCreated then initialize your recyclerView and adapter.try like this
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_notification, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Ok I just noticed you passed a parameter in removeItem method using holder.getAdapterPosition() which is causing your problem.Try to pass the position which is provided by public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position).So the basic error is when you are in onBindViewHolder you don't need to use holder.getAdapterPosition() because onBindViewHolder already giving you the position
In your removeItem method use notifyDataSetChanged instead of notifyItemRemoved(position)
try like this
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest").child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}

Recyclerview ListAdapter not updating

I have implemented a basic ListAdapter in RecyclerView as I am using View Model. The data I am getting is from networkManager to Viewmodel by calling API. Even when I did got the data the submitList is not Working and thus no data is getting inflated.
UpcomingGroupFragment
public class UpcomingGroupFragment extends Fragment {
private UpcomingViewModel mViewModel;
private RecyclerView recyclerView;
private GroupAdapter_new adapter;
public static UpcomingGroupFragment newInstance() {
return new UpcomingGroupFragment();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_chatgroups, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new GroupAdapter_new();
recyclerView.setAdapter(adapter);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(UpcomingViewModel.class);
mViewModel.getMutableLiveData().observe(this, new Observer<List<ChatGroups_New>>() {
#Override
public void onChanged(#Nullable List<ChatGroups_New> chatGroups_news) {
adapter.submitList(chatGroups_news);
Log.e("Upcoming", String.valueOf(chatGroups_news.size()));
}
});
}
}
The Adapter Class extends the ListAdapter.
Link for overriding submitlist: https://stackoverflow.com/a/50062174
The Code is as follows:
GroupAdapter_new
public class GroupAdapter_new extends ListAdapter<ChatGroups_New,GroupAdapter_new.ViewHolder> {
public GroupAdapter_new() {
super(DIFF_CALLBACK);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
int layoutID = R.layout.ongoing_group;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(layoutID,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ChatGroups_New currentGroup = getItem(position);
holder.text_flightarrival.setText(currentGroup.getFlightNameArrival());
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
//... Finding ID's for various Views
}
}
/****ADDED THIS FROM CODE*****/
#Override
public void submitList(List<ChatGroups_New> list) {
super.submitList(list != null ? new ArrayList<ChatGroups_New>() : null);
}
/***********/
private static final DiffUtil.ItemCallback<ChatGroups_New> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ChatGroups_New>() {
#Override
public boolean areItemsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
Log.e("areItemsTheSame", String.valueOf(oldItem.getMergedLogId() == newItem.getMergedLogId()));
return oldItem.getMergedLogId() == newItem.getMergedLogId();
}
#Override
public boolean areContentsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
if(oldItem.getFlightIcon().equals(newItem.getFlightIcon()) && oldItem.getFlightNameArrival().equals(newItem.getFlightNameArrival())){
if(oldItem.getGateValue().equals(newItem.getGateValue()) && oldItem.getEtaValue().equals(newItem.getEtaValue())){
if(oldItem.getAlertValue().equals(newItem.getAlertValue()) && oldItem.getTaskcompletedValue().equals(newItem.getTaskcompletedValue())){
Log.e("areContentsTheSame", "true");
return true;
}
}
}
return false;
}
};
}
If you want to see my ViewModel Class then:
UpcomingViewModel
public class UpcomingViewModel extends AndroidViewModel
implements I_NetworkResponse {
private NetworkManager networkManager;
private SharedPrefService prefService;
private HashMap<String, String> header;
private final String TAG = "UpcomingViewModel";
private List<ChatGroups_New> upcomingList;
private MutableLiveData<List<ChatGroups_New>> mutableLiveData;
public UpcomingViewModel(#NonNull Application application) {
super(application);
prefService = SharedPrefService.getInstance(application);
networkManager = new NetworkManager(application,this);
upcomingList = new ArrayList<>();
mutableLiveData = new MutableLiveData<>();
mutableLiveData.setValue(upcomingList);
header = new HashMap<>();
header.put("authorizationcode",prefService.getStringValue(Keys.getPreferenceAuthKey()));
if(upcomingList.isEmpty()){
networkManager.Volley_JsonObjectRequest(Keys.getBaseUrl()+"AviLeap/flights/upcoming",
header,null,TAG,"AviLeap/flights/upcoming");
}
}
public MutableLiveData<List<ChatGroups_New>> getMutableLiveData() { return mutableLiveData; }
#Override
public void getNetworkSuccessResponse(String TAG, String successResponse, String TAGforApi) {
Log.e(TAGforApi,successResponse);
parseUpcomingFlight(successResponse, upcomingList);
mutableLiveData.setValue(upcomingList);
}
#Override
public void getNetworkFailResponse(String TAG, VolleyError failResponse, String TAGforApi) { }
#Override
protected void onCleared() {
super.onCleared();
networkManager.stopNetworkCallsWithTag(TAG);
}
private void parseUpcomingFlight(String successResponse, List<ChatGroups_New> upcomingList) {
try {
JSONObject rootObject = new JSONObject(successResponse);
if(rootObject.has("upcomingflights") && rootObject.opt("upcomingflights") instanceof JSONArray){
JSONArray flightsArray = rootObject.optJSONArray("upcomingflights");
for(int flightIndex = 0; flightIndex < flightsArray.length(); flightIndex++){
JSONObject flightObject = flightsArray.optJSONObject(flightIndex);
int mergedLogId = flightObject.optInt("logid");
upcomingList.add(new ChatGroups_New(mergedLogId));
Log.e("parseUpcomingFlight", String.valueOf(upcomingList.size()));//..... Log Point
}
}
}
catch (JSONException e) { e.printStackTrace(); }
}
}
Initially the Size of the List is zero, so the Error is coming for as
AviLeap/flights/upcoming: //.... API CALL
2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 1 2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 2
2019-03-02 13:25:53.653 8477-8477/com.avileapconnect.com E/Upcoming: 2
The above logs show that the data is being added to the arraylist, but it is not updating. Also after all these logs when I go back to my Fragment I get the following error.
no adapter Attached, Skipping Layout
One more thing to add is that the adapter's getItemCount is getting updated properly. But even after that I am getting error:
no adapter Attached, Skipping Layout
EDIT: I fixed the error by commenting out the code for overriding the SubmitList method. I am also setting the adapter in the observer method in the fragment Class

Custom methods in adapter are not resolving in android

I have 2 methods inside of adapter class.
addValues(brandMap);
setBrandMap(brandMap);
that I'm trying to call after async call. However, the compiler is complaining that it cannot resolve these methods. What is the issue?
This is complete class.
public class FragmentBrandList extends ListFragment {
private String TAG = getClass().getSimpleName();
private Map<String, Brand> brandMap = new ConcurrentHashMap<>();
private RecyclerView.Adapter adapter;
private FirebaseDatabase database = FirebaseDatabase.getInstance();
private RecyclerView recyclerView;
private Query query = database.getReference("brands").orderByChild("name");
public FragmentBrandList() {
}
public static FragmentBrandList newInstance(int num) {
FragmentBrandList f = new FragmentBrandList();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.recycler_list, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 3);
RecyclerView.setLayoutManager(mLayoutManager);
adapter = new FragmentBrandList.MyAdapter(Utility.getBrandMap(), getActivity());
recyclerView.setAdapter(adapter);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
Brand brand = Utility.getBrands().get(position);
Intent intent = new Intent(getActivity(), ActivityProductList.class);
intent.putExtra("BrandId", brand.getId());
startActivity(intent);
}
#Override
public void onLongClick(View view, int position) {
}
}));
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Brand brand = dataSnapshot1.getValue(Brand.class);
brandMap.put(brand.getId(), brand);
}
Utility.setBrandMap(brandMap);
adapter.addValues(brandMap);
adapter.setBrandMap(brandMap);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
Utility.displayToast("Failed to read value." + error.toException());
}
});
return v;
}
Adapter class
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Brand> brandList = new ArrayList<>();
private Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public MyViewHolder(View view) {
super(view);
imageView = (ImageView) view.findViewById(R.id.thumbnail);
}
}
public MyAdapter(Map<String, Brand> brands, Context context) {
//public MyAdapter(List<Brand> brands, Context context) {
this.brandList = new ArrayList<>(brandMap.values());
//this.brandList = brands;
this.context = context;
}
public void setBrandMap(Map<String, Brand> brandMap){
this.brandList = new ArrayList<>(brandMap.values());
notifyDataSetChanged();
}
public void addValues(Map<String, Brand> brands){
brandList.clear();
brandList.addAll(brands.values());
notifyDataSetChanged();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_brand, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (brandList != null && brandList.size() > 0) {
Brand brand = brandList.get(position);
Glide.with(context).load(String.valueOf(brand.getImage()))
.error(R.drawable.placeholder)
.placeholder(R.drawable.placeholder)
.into(holder.imageView);
}
}
#Override
public int getItemCount() {
return brandList.size();
}
}
You have declared your adapter field as:
private RecyclerView.Adapter adapter;
That means wherever you use it, you'll see it as just a RecyclerView.Adapter, which doesn't have your custom methods on it. It doesn't matter that you've assigned there a subclass of RecyclerView.Adapter that has extra methods. It is because you might've assigned there a different subclass that didn't have those methods.
If you want to use your custom methods then change the declaration to:
private MyAdapter adapter;
Then you can use all methods declared in MyAdapter and inherited from superclasses. The tradeoff is that you cannot assign there any other subclass of RecyclerView.Adapter, but thanks to that compiler can know you can always use your extra methods.
The problem is this line.
private RecyclerView.Adapter adapter;
As you are holding your custom adapter object in the Base reference, hence those methods of your custom adapter is not visible to you. Change the reference to the type of your Custom Adapter and it should work fine.

Categories

Resources