I am trying to implement multiple view or so called heterogeneous recyclerview using firebase realtime database. I found a example of heterogeneous recyclerview implementation on github.
I followed this to implement on firebase. But my code didn't work.
fragment_search.java (one of the fragment in my tabbed view) This is my fragment file which contains the main recyclerview which will hold multiple views
public class fragment_search extends Fragment {
RecyclerView recyclerViewSearch;
private static SingleSearchBannerModel singleSearchBannerModel;
private static SingleSearchType1Model singleSearchType1Model;
private static DatabaseReference databaseReference;
private List<Object> objects = new ArrayList<>();
private static SearchMainAdapter searchMainAdapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search,null);
//Recycler view initialized and Properties Set.
recyclerViewSearch = view.findViewById(R.id.recyclerview_search);
recyclerViewSearch.setHasFixedSize(true);
recyclerViewSearch.setLayoutManager(new LinearLayoutManager(getContext()));
databaseReference = FirebaseDatabase.getInstance().getReference();
return view;
}
private List<Object> getObjects(){
objects.addAll(getBannerData());
objects.addAll(getType1Data());
return objects;
}
public static List<SingleSearchBannerModel> getBannerData(){
final List<SingleSearchBannerModel> singleSearchBannerModelList = new ArrayList<>();
databaseReference.child("Featured").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
singleSearchBannerModel = dataSnapshot.getValue(SingleSearchBannerModel.class);
singleSearchBannerModelList.add(singleSearchBannerModel);
searchMainAdapter.notifyDataSetChanged();
System.out.println("this is image in getBanner == "+singleSearchBannerModel.getImage());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return singleSearchBannerModelList;
}
public static List<SingleSearchType1Model> getType1Data(){
final List<SingleSearchType1Model> singleSearchType1ModelList = new ArrayList<>();
databaseReference.child("Featured").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
singleSearchType1Model = dataSnapshot.getValue(SingleSearchType1Model.class);
singleSearchType1ModelList.add(singleSearchType1Model);
searchMainAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return singleSearchType1ModelList;
}
#Override
public void onStart() {
super.onStart();
searchMainAdapter = new SearchMainAdapter(getContext(),getObjects());
System.out.println("this is getObject == "+getObjects());
System.out.println("this is getBanner == "+getBannerData());
System.out.println("this is getType1 == "+getType1Data());
recyclerViewSearch.setAdapter(searchMainAdapter);
}
}
fragment_home.xml this is the xml file of fragment which contains one recyclerview (My main recyclerview).
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_search"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
Model files
*I have two model files. Basically getter and setters *
SingleSearchBannerModel.java My firsts model file.
public class SingleSearchBannerModel {
String Image;
public SingleSearchBannerModel() {
}
public SingleSearchBannerModel(String image) {
Image = image;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
SingleSearchType1Model.java This is my second model file.
public class SingleSearchType1Model {
String Image;
public SingleSearchType1Model() {
}
public SingleSearchType1Model(String image) {
Image = image;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
RecyclerView Adapters
Adapters are the ones used to set the value to the recyclerView. I have three Adapters as I'm trying to insert two views in one recyclerview. One is the MainAdapter which combines the other two Adapters. The MainAdapter is set to the the recyclerview of fragment_search.java (my main fragment)
SearchBannerAdapter.java This adapter is to generate the required layout file and populate the inflated layout file.
public class SearchBannerAdapter extends RecyclerView.Adapter<SearchBannerAdapter.TaskViewHolder>{
List<SingleSearchBannerModel> data;
public SearchBannerAdapter(List<SingleSearchBannerModel> data) {
this.data = data;
}
#NonNull
#Override
public TaskViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_single_banners,parent,false);
return new TaskViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TaskViewHolder holder, int position) {
SingleSearchBannerModel singleSearchBannerModel = data.get(position);
Picasso.get().load(singleSearchBannerModel.getImage()).fit().into(holder.imageView);
}
#Override
public int getItemCount() {
return data.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder{
View mView;
ImageView imageView;
public TaskViewHolder(View itemView) {
super(itemView);
mView = itemView;
imageView = mView.findViewById(R.id.search_banner_imgView);
}
}
}
search_single_banners.xml The xml file which is inflated in SearchBannerAdapter.java
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="290dp"
android:layout_height="160dp"
android:id="#+id/longCard"
android:layout_marginTop="50dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="20sp"
app:cardElevation="#dimen/ten"
app:cardPreventCornerOverlap="false"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/search_banner_imgView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/test1"/>
</android.support.v7.widget.CardView>
SearchType1Adapter.java This is the second adapter which inflates search_type_1.xml
public class SearchType1Adapter extends RecyclerView.Adapter<SearchType1Adapter.TaskViewHolder>{
List<SingleSearchType1Model> data;
public SearchType1Adapter(List<SingleSearchType1Model> data) {
this.data = data;
}
#NonNull
#Override
public TaskViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_type_1,parent,false);
return new TaskViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TaskViewHolder holder, int position) {
SingleSearchType1Model singleSearchType1Model = data.get(position);
Picasso.get().load(singleSearchType1Model.getImage()).fit().into(holder.imageView);
}
#Override
public int getItemCount() {
return data.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder{
View mView;
ImageView imageView;
public TaskViewHolder(View itemView) {
super(itemView);
mView = itemView;
imageView = mView.findViewById(R.id.search_single_type_1_imgView);
}
}
}
search_type_1.xml The file that is inflated in SearchType1Adapter.java
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="290dp"
android:layout_height="160dp"
android:id="#+id/longCard"
android:layout_marginTop="50dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="20sp"
app:cardElevation="#dimen/ten"
app:cardPreventCornerOverlap="false"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/search_single_type_1_imgView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/test1"/>
</android.support.v7.widget.CardView>
SearchMainAdapter.java This is the main adapter which is used in fragment_search to populate the main recyclerview.
public class SearchMainAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<Object> items;
private final int BANNER = 1;
private final int TYPE1 = 2;
public SearchMainAdapter(Context context, List<Object> items) {
this.context = context;
this.items = items;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view;
RecyclerView.ViewHolder holder;
switch (viewType){
case BANNER:
view = inflater.inflate(R.layout.search_banners,parent,false);
holder = new BannerViewHolder(view);
break;
case TYPE1:
view = inflater.inflate(R.layout.search_type_1,parent,false);
holder = new Type1ViewHolder(view);
break;
default:
view = inflater.inflate(R.layout.search_banners,parent,false);
holder = new Type1ViewHolder(view);
break;
}
return holder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if(holder.getItemViewType() == BANNER)
BannerView((BannerViewHolder) holder);
else if (holder.getItemViewType() == TYPE1)
Type1View((Type1ViewHolder) holder);
}
private void BannerView(BannerViewHolder holder){
SearchBannerAdapter searchBannerAdapter = new SearchBannerAdapter(getBannerData());
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
holder.recyclerView.setAdapter(searchBannerAdapter);
}
private void Type1View(Type1ViewHolder holder){
SearchType1Adapter searchType1Adapter = new SearchType1Adapter(getType1Data());
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
holder.recyclerView.setAdapter(searchType1Adapter);
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof SingleSearchBannerModel)
return BANNER;
if (items.get(position) instanceof SingleSearchType1Model)
return TYPE1;
return -1;
}
public static class BannerViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public BannerViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.recyclerview_banners);
}
}
public static class Type1ViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public Type1ViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.recyclerview_search_type_1);
}
}
}
search_banners.xml and search_type_1.xml have the same code
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_banners"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
The above code is not working. I want to know where i went wrong. My main objective is to make an app something like google play store or hotstar (In terms of UI). So I assume they are using single recyclerview and multiple view within it.
Thanks for help.
I know this answer is a bit late but it might still help someone in future. Here is how I achived the goal
public class HeteroActivity extends AppCompatActivity {
private ArrayList<Object> objects = new ArrayList<>();
private static final String TAG = HeteroActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hetero);
RecyclerView recyclerView = findViewById(R.id.recycler_View);
MainAdapter adapter = new MainAdapter(this, getObject());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private ArrayList<Object> getObject() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Data");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
objects.add(getVerticalData(dataSnapshot).get(0));
objects.add(getHorizontalData(dataSnapshot).get(0));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return objects;
}
public static ArrayList<SingleVertical> getVerticalData(DataSnapshot dataSnapshot) {
ArrayList<SingleVertical> singleVerticals = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
singleVerticals.add(new SingleVertical(
snapshot.child("price").getValue(String.class),
snapshot.child("location").getValue(String.class),
snapshot.child("image").getValue(String.class)
));
Log.e(TAG,"Text loaded");
}
return singleVerticals;
}
public static ArrayList<SingleHorizontal> getHorizontalData(DataSnapshot dataSnapshot) {
ArrayList<SingleHorizontal> singleHorizontals = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
singleHorizontals.add(new SingleHorizontal(
snapshot.child("price").getValue(String.class),
snapshot.child("location").getValue(String.class),
snapshot.child("image").getValue(String.class)
));
Log.e(TAG,"Horizontal data loaded");
}
return singleHorizontals;
}
}
Then in your main Adapter
do this:
private void verticalView(final VerticalViewHolder holder) {
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
VerticalAdapter adapter1 = new VerticalAdapter(getVerticalData(dataSnapshot), context);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context));
holder.recyclerView.setAdapter(adapter1);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void horizontalView(final HorizontalViewHolder holder) {
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
HorizontalAdapter adapter = new HorizontalAdapter(getHorizontalData(dataSnapshot),context);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Related
I am creating an Android app which is based on wallpaper. I have different categories in my app that shows images and after clicking on particular image it will show full image. The problem is when I click on any categories the images are shown are very slow. I am retrieving images from firebase realtime database. I am showing images in grid layout in two columns. I have also compress all the images then to the process of showing images is very slow.
This is one of the category code.
public class AnimalWallpaper extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar progressBar;
private DatabaseReference reference;
private ArrayList<String> list;
private WallpaperAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animal_wallpaper);
reference = FirebaseDatabase.getInstance().getReference().child("animal");
recyclerView = findViewById(R.id.recyclerViewAnimal);
progressBar = findViewById(R.id.progressBarAnimal);
getData();
}
private void getData() {
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
progressBar.setVisibility(View.GONE);
list = new ArrayList<>();
for (DataSnapshot shot : snapshot.getChildren()) {
String data = shot.getValue().toString();
list.add(data);
}
recyclerView.setLayoutManager(new GridLayoutManager(AnimalWallpaper.this, 2));
adapter = new WallpaperAdapter(list, AnimalWallpaper.this);
recyclerView.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
progressBar.setVisibility(View.GONE);
Toast.makeText(AnimalWallpaper.this, "Error : "+error.getMessage() , Toast.LENGTH_SHORT).show();
}
});
}
}
This is wallpaperadapter class code.
public class WallpaperAdapter extends RecyclerView.Adapter<WallpaperAdapter.WallpaperViewHolder> {
private ArrayList<String> list;
private Context context;
public WallpaperAdapter(ArrayList<String> list, Context context) {
this.list = list;
this.context = context;
}
#NonNull
#org.jetbrains.annotations.NotNull
#Override
public WallpaperViewHolder onCreateViewHolder(#NonNull #org.jetbrains.annotations.NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.custom_image_layout, parent, false );
return new WallpaperViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull #org.jetbrains.annotations.NotNull WallpaperAdapter.WallpaperViewHolder holder, int position) {
Glide.with(context).load(list.get(position)).into(holder.imageView);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, FullImageActivity.class);
intent.putExtra("images", list.get(position));
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public class WallpaperViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public WallpaperViewHolder(#NonNull #NotNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.item_image);
}
}
}
the firebase data doesn't appear in the recycler view
i have some realtimeDb in Google firebase
i try to read it in the recyclerView but nothing appears ,
logcat shows null and here is my code:
1-Here is HomeFragment(Main) Code
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
Unbinder unbinder;
#BindView(R.id.recycler_popular)
RecyclerView recyclerView;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
unbinder= ButterKnife.bind(this,root);
init();
homeViewModel.getPopularList().observe(this, new Observer<List<PopularCategoryModel>>() {
#Override
public void onChanged(List<PopularCategoryModel> PopularCategoryModel) {
//create adapter
MyPopularCategoriesAdapter adapter = new MyPopularCategoriesAdapter(HomeFragment.this.getContext(), PopularCategoryModel);
recyclerView.setAdapter(adapter);
}
});
return root;
}
private void init() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
}
}
2-Here is HomeViewModel Code
public class HomeViewModel extends ViewModel implements IPopularCallbackListener {
private static final String TAG = "HomeViewModel";
private MutableLiveData<List<PopularCategoryModel>> popularList;
private MutableLiveData<String> messageError;
private IPopularCallbackListener popularCallbackListener;
public HomeViewModel() {
}
public MutableLiveData<List<PopularCategoryModel>> getPopularList() {
if (popularList== null){
popularList=new MutableLiveData<>();
messageError=new MutableLiveData<>();
loadPopularList();
}
return popularList;
}
private void loadPopularList() {
final List<PopularCategoryModel> tempList = new ArrayList<>();
DatabaseReference popularRef= FirebaseDatabase.getInstance().getReference(Common.POPULAR_CATEGORY_REF);
popularRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
tempList.clear();
for (DataSnapshot itemSnapShot:dataSnapshot.getChildren()){
PopularCategoryModel model=itemSnapShot.getValue(PopularCategoryModel.class);
tempList.add(model);
Log.d(TAG, "onDataChange:Adel2020"+tempList.size()+popularRef);
}
//popularCallbackListener.onPopularLoadSuccess(tempList);
Log.e(TAG, "Data received:" + tempList.size());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
popularCallbackListener.onPopularLoadFailed(databaseError.getMessage());
}
});
}
public MutableLiveData<String> getMessageError() {
return messageError;
}
#Override
public void onPopularLoadSuccess(List<PopularCategoryModel> popularCategoryModels) {
popularList.setValue(popularCategoryModels);
}
#Override
public void onPopularLoadFailed(String message) {
messageError.setValue(message);
}
}
3- This is the Adapter
public class MyPopularCategoriesAdapter extends RecyclerView.Adapter<MyPopularCategoriesAdapter.PopViewHolder> {
private List<PopularCategoryModel> listPopularCategoryModel ;
Context context;
public MyPopularCategoriesAdapter( Context context,List<PopularCategoryModel> listPopularCategoryModel) {
this.listPopularCategoryModel = listPopularCategoryModel;
this.context = context;
}
#NonNull
#Override
public PopViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new PopViewHolder(LayoutInflater.from(parent.getContext()).inflate
(R.layout.layout_popular_categories_item, parent, false));
}
#Override
public void onBindViewHolder(#NonNull PopViewHolder holder, int position) {
Glide.with(context).load(listPopularCategoryModel.get(position).getImage()).into(holder.popCategoryImage);
holder.popCategoryName.setText(listPopularCategoryModel.get(position).getName());
}
#Override
public int getItemCount() {
return listPopularCategoryModel.size();
}
public class PopViewHolder extends RecyclerView.ViewHolder {
Unbinder unbinder;
#BindView(R.id.pop_category_name)
TextView popCategoryName;
#BindView(R.id.pop_category_image)
CircleImageView popCategoryImage;
public PopViewHolder(#NonNull View itemView) {
super(itemView);
unbinder= ButterKnife.bind(this,itemView);
}
}
}
4-This is Model
public class PopularCategoryModel {
private String menu_id,food_id,name,image;
public PopularCategoryModel() {
}
public PopularCategoryModel(String menu_id, String food_id, String name, String image) {
this.menu_id = menu_id;
this.food_id = food_id;
this.name = name;
this.image = image;
}
public PopularCategoryModel(String name, String image) {
this.name = name;
this.image = image;
}
+SetterGetter
5-Here is the Data
I am using a recyclerview and inside its adapter I have another recyclerview.
How to prevent item change and item refresh when an item is updated.
This is creating visual glitches and wrong positioning of the items
I have tried to read directly from a database reference on the current position of the holder.
Result: https://media.giphy.com/media/j6TpXZRE6e44cMZVIP/giphy.gif
public class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.ViewHolder>{
private Context mContext;
private List<Comments> mComments;
private List<Replies> allReplies;
public CommentsAdapter(Context mContext, List<Comments> mComments, List<Replies> allReplies )
{
this.mContext = mContext;
this.mComments = mComments;
this.allReplies = allReplies;
}
#NonNull
#Override
public CommentsAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.all_comments_layout, viewGroup, false);
return new CommentsAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position)
{
final Comments comments = mComments.get(position);
holder.like.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommentUps.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
{
if (dataSnapshot.child(PostKey).child(com_uid).hasChild(currentUserID)) {
CommentUps.child(PostKey).child(com_uid).child(currentUserID).removeValue();
CommentsRef.child(PostKey).child(com_uid).child("likes").setValue(comments.getLikes() - 1);
} else {
CommentUps.child(PostKey).child(com_uid).child(currentUserID).setValue(true);
CommentsRef.child(PostKey).child(com_uid).child("likes").setValue(comments.getLikes() + 1);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
});
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Replies");
//reference.orderByChild("pLikes")
reference.orderByChild(com_uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
holder.repliesList.clear();
for (DataSnapshot snapshot : dataSnapshot.child(PostKey).child(com_uid).getChildren())
{
Replies replies = snapshot.getValue(Replies.class);
//final String com = comment.toString();
// Log.d(new String("Comments"), com);
//for (String id : followingList)
if (replies.getComment_uid().equals(com_uid))
{
holder.repliesList.add(replies);
}
}
holder.repliesAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public int getItemCount() {
return mComments.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageButton like
List<Replies> repliesList;
RepliesAdapter repliesAdapter;
public ViewHolder(View itemView) {
super(itemView);
like = itemView.findViewById(R.id.comment_like_button);
repliesRecycler = itemView.findViewById(R.id.all_replies_recycler);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);
repliesRecycler.setLayoutManager(linearLayoutManager);
repliesRecycler.setHasFixedSize(true);
repliesList = new ArrayList<>();
repliesAdapter = new RepliesAdapter(mContext, repliesList);
repliesRecycler.setAdapter(repliesAdapter);
repliesAdapter.notifyDataSetChanged();
}
// Second Method - Same Result
private void displayReplies(final String com_uid ,final String PostKey, final boolean locked) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Replies");
reference.child(PostKey).child(com_uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
repliesList.clear();
if (dataSnapshot.exists()) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
final Replies replies = snapshot.getValue(Replies.class);
if (replies.getComment_uid().equals(com_uid)) {
repliesList.add(replies);
repliesAdapter.notifyDataSetChanged();
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
My replies adapter:
public class RepliesAdapter extends RecyclerView.Adapter<RepliesAdapter.ViewHolder>
{
public Context mContext;
public List<Replies> mReplies;
public RepliesAdapter(Context mContext, List<Replies> mReplies)
{
this.mContext = mContext;
this.mReplies = mReplies;
}
#NonNull
#Override
public RepliesAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.all_replies_layout, viewGroup, false);
mAuth = FirebaseAuth.getInstance();
return new RepliesAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position)
{
final Replies replies = mReplies.get(position);
holder.myUserName.setText(replies.getUsername());
holder.myComment.setText(replies.getReply());
holder.myTime.setText(replies.getTime());
}
#Override
public int getItemCount() {
return mReplies.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView myUserName, myComment,myTime;
public ViewHolder(View itemView) {
super(itemView);
myUserName = itemView.findViewById(R.id.reply_username);
myComment = itemView.findViewById(R.id.reply_text);
myTime = itemView.findViewById(R.id.reply_time);
}
}
I am trying to load firebase list of data in my custom recycler adapter but I am unable to load it.
this code is displaying data in my logcat but I am unable to load in my app.
logcat showing no errors though. If I use firebase UI and try to do this thing then it is working fine but I want to inset native ads in recycler view to I had to migrate to custom adapter and now I am stuck with this issue. :(
my custom recycler adapet.
public class AuthorNameCustomRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<AuthorsCLA> authorlist;
Context mcontext;
public class NamesHolder extends RecyclerView.ViewHolder {
public TextView name;
public NamesHolder(View itemView) {
super(itemView);
name = (TextView)itemView.findViewById(R.id.authorNameTextView);
}
}
public AuthorNameCustomRecyclerAdapter(ArrayList<AuthorsCLA> authorlist, Context mcontext) {
this.authorlist = authorlist;
this.mcontext = mcontext;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case 1: {
View view = inflater.inflate(R.layout.author_list_cv, parent, false);
viewHolder = new NamesHolder(view);
break;
}
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final AuthorsCLA authorsModel = authorlist.get(holder.getAdapterPosition());
switch (holder.getItemViewType()){
case 1:{
NamesHolder nameHolder = (NamesHolder) holder;
nameHolder.name.setText(authorsModel.getAuthorname());
nameHolder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), AuthorQuotesDetailActvity.class);
mcontext.startActivity(intent);
}
});
}
}
}
#Override
public int getItemCount() {
return authorlist.size();
}
}
here is the class where i am calling custom recycler adapter.
public class AuthorsList extends AppCompatActivity {
private RecyclerView recyclerViewAuthor;
private StaggeredGridLayoutManager mlayoutManager;
private GridLayoutManager manager;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference mdatabaseReference = database.getReference();
private AdView mAdView;
private RecyclerView.Adapter adapter;
private ArrayList<AuthorsCLA> authorlist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.authors_list);
MobileAds.initialize(this, "ca-app-pub-7854400750152181~4721849113");
mAdView = (AdView) findViewById(R.id.adView1);
AdRequest adRequest = new AdRequest.Builder().addTestDevice("2A79E20CADE70C60CF36B2E8EE9103FF").build();
mAdView.loadAd(adRequest);
recyclerViewAuthor = (RecyclerView) findViewById(R.id.authorsRecyclerView);
DatabaseReference mListItemRef = mdatabaseReference.child("en/of");
authorlist = new ArrayList<>();
manager = new GridLayoutManager(this,2);
recyclerViewAuthor.setLayoutManager(manager);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d("Added",dataSnapshot.getKey());
fetchData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
mListItemRef.addChildEventListener(childEventListener);
adapter = new AuthorNameCustomRecyclerAdapter(authorlist, this);
recyclerViewAuthor.setAdapter(adapter);
}
private void fetchData(DataSnapshot dataSnapshot) {
AuthorsCLA listItem=dataSnapshot.getValue(AuthorsCLA.class);
authorlist.add(listItem);
// recyclerViewAuthor.setAdapter(adapter);
}
}
onChildAdded() will be called each time when the child is fetched by firebase call. This is asynchronous process.
In your code you are adding it into ArrayList<>, but somehow you are not notifying the adapter that child is being added. It is safe to do that in your
private void fetchData(DataSnapshot dataSnapshot) {
AuthorsCLA listItem = dataSnapshot.getValue(AuthorsCLA.class);
authorlist.add(listItem);
adapter.notifyItemInserted(authorlist.size() - 1); // Notify the adapter
}
I am trying to create a cardView with recyclerView with creating the CardView programmatically, here is my code, if it is not possible please let me know to use XML
onCreate of the main class
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.lesson_layout, container, false);
ExampleRecyclerView = (RecyclerView) rootView.findViewById(R.id.ExampleRecyclerView);
List<ViewExample> exampleList = new ArrayList<>();
Log.i("dddddd", String.valueOf(exampleList));
//alos the list just show [] in the Logs
adapter = new ExampleAdapter(this, exampleList);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setSmoothScrollbarEnabled(true);
ExampleRecyclerView.setScrollbarFadingEnabled(true);
ExampleRecyclerView.setLayoutManager(llm);
ExampleRecyclerView.setAdapter(adapter);
return rootView;
}
the ViewExample class
public class ViewExample {
private String StepHeader, Code, Explanation;
public ViewExample(String stepHeader, String code, String explanation) {
StepHeader = stepHeader;
Code = code;
Explanation = explanation;
}
Getters & Setters are here...
}
And the Adapter
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleHolder> {
CardView ExampleCV;
List<ViewExample> exampleList;
ViewLesson viewLesson;
public ExampleAdapter(ViewLesson viewLesson, List<ViewExample> exampleList) {
this.viewLesson = viewLesson;
this.exampleList = exampleList;
}
public class ExampleHolder extends RecyclerView.ViewHolder { // here is where you define what text have value
LinearLayout parentL;
public ExampleHolder(View itemView) {
super(itemView);
parentL = new LinearLayout(parentL.getContext());
ExampleCV = new CardView(ExampleCV.getContext());
ExampleCV.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
parentL.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
parentL.setOrientation(LinearLayout.VERTICAL);
ExampleCV.addView(parentL);
}
}
#Override
public ExampleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ExampleHolder(ExampleCV);
}
#Override
public void onBindViewHolder(final ExampleHolder holder, int position) {
TextView tv = null;
final TextView finalTv = tv;
RootRef.child("Development").child("Level 2").child("Intent").child("Putextra").child("Examples")
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.i("isa 5air", String.valueOf(dataSnapshot.getValue()));
finalTv.setText(String.valueOf(dataSnapshot.getValue()));
holder.parentL.addView(finalTv);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public int getItemCount() {
return 0;
}
}
Edit
NB : I have noticed that the code doesn't enter onBindViewHolder as I put test Log in it it doesn't print out
you can use in your lesson_layout with cardview as given below cardview can only one child you can use another container layout such linear or relative as you need
<android.support.v7.widget.CardView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp"
card_view:contentPadding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
............some other views.....
</LinearLayout>
</android.support.v7.widget.CardView>
In your code, it seems that you are passing empty list to RecyclerView Adapter
List<ViewExample> exampleList = new ArrayList<>();
Log.i("dddddd", String.valueOf(exampleList));
//alos the list just show [] in the Logs
adapter = new ExampleAdapter(this, exampleList);
Suggested changes:
1.You can Add some elements in it before passing to the adapter or add element in list and then call
adapter.notifyDataSetChanged();
2.In your ExampleAdapter change getItemCount() method with bellow
#Override
public int getItemCount() {
return exampleList.size();
}
Edit:
3.Change your onCreateViewHolder()
#Override
public ExampleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ExampleCV = new CardView(ExampleCV.getContext());
ExampleCV.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
return new ExampleHolder(ExampleCV);
}
4.Constructor of ExampleHolder with:
public ExampleHolder(View itemView) {
super(itemView);
parentL = new LinearLayout(parentL.getContext());
parentL.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
parentL.setOrientation(LinearLayout.VERTICAL);
itemView.addView(parentL);
}