I'm trying to retrieve data from Firebase to Recyclerview. I've already implement all other steps but now i'm getting error at the last stage when i'm implementing the adapter(FirebaseRecyclerAdapter).
My Fragment
public class Journal extends Fragment {
RecyclerView recyclerView;
DatabaseReference myref;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_journal,container,false);
myref= FirebaseDatabase.getInstance().getReference("/Journal");
recyclerView = (RecyclerView) v.findViewById(R.id.journal_rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
FirebaseRecyclerAdapter<JournalEntry, JournalHolder> adapter = new FirebaseRecyclerAdapter<JournalEntry, JournalHolder>(
JournalEntry.class,
R.layout.journal_list_item,
JournalHolder.class,
myref) {
#Override
protected void onBindViewHolder(JournalHolder holder, int position, JournalEntry model) {
holder.setTitle(model.getEvent_title());
holder.setContent(model.getEvent_content());
holder.setSchool(model.getSchool_name());
holder.setDate(model.getDate());
holder.setStudents(model.getNumber_of_students());
holder.setSchoolIv(model.getImg_url());
}
#Override
public JournalHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
};
return v;
}
public static class JournalHolder extends RecyclerView.ViewHolder{
TextView Jtitle , Jcontent,Jschool,Jstudents,jdate;
ImageView schoolIV;
public JournalHolder(View itemView) {
super(itemView);
Jtitle =(TextView)itemView.findViewById(R.id.journal_title);
Jcontent =(TextView)itemView.findViewById(R.id.event_content);
Jschool =(TextView)itemView.findViewById(R.id.journal_school);
Jstudents =(TextView)itemView.findViewById(R.id.journal_students);
jdate = (TextView)itemView.findViewById(R.id.journal_dates) ;
schoolIV = (ImageView)itemView.findViewById(R.id.journal_image);
}
public void setTitle(String title) {
Jtitle.setText(title);
}
public void setContent(String content) {
Jcontent.setText(content);
}
public void setSchool(String school) {
Jschool.setText(school);
}
public void setDate(String date) {
jdate.setText(date);
}
public void setStudents(String students) {
Jstudents.setText(students);
}
public void setSchoolIv(String schoolIv) {
Picasso.with(itemView.getContext())
.load(schoolIv)
.into(schoolIV);
}
}
}
This is what is shown as error
FireBaseRecyclerView in FirebaseRecyclerView can not be applied to :
JournalEntry.class (java...consti.last.database.JournalEntry>)
R.layout.journal_list_item (int)
BlogViewHolder.class (java...consti.last.Journal.BlogViewHolder>)
myref (com...firebase.database.DatabaseReference)
Please help me. I tried all the methods but nothing works.
Or if you have any advice...thank you in advance.
PS : I'm using Fragments
under Activity declaration write:-
private FirebaseRecyclerAdapter<JournalEntry, JournalHolder> adapter;
then inside onCreateView():
adapter = new FirebaseRecyclerAdapter<JournalEntry, JournalHolder>(
JournalEntry.class,
R.layout.journal_list_item,
JournalHolder.class,
myref) { //be sure that these classes and parameters are correct..
above return v;:
recyclerView.setAdapter(adapter);
Use this method instead of onBindViewHolder:
#Override
protected void populateViewHolder(JournalHolder holder,JournalEntry model, int position) {
Be sure you have all the correct methods in the model class JournalEntry.class and holder class JournalHolder.class and that its the right location and right layout.
I finally found solution here:Firebase RecyclerView
I had the same problem.
In this version FirebaseResycleView use the following:
Query query = FirebaseDatabase.getInstance()
.getReference(); // you can add child as .child("child_name");
FirebaseRecyclerOptions<JournalEntry> options = new FirebaseRecyclerOptions.Builder<JournalEntry>()
.setQuery(query, JournalEntry.class)
.build();
FirebaseRecyclerAdapter<JournalEntry, JournalHolder> adapter = new FirebaseRecyclerAdapter<JournalEntry, JournalHolder>(
options) {
#Override
protected void onBindViewHolder(JournalHolder holder, int position, JournalEntry model) {
holder.setTitle(model.getEvent_title());
holder.setContent(model.getEvent_content());
holder.setSchool(model.getSchool_name());
holder.setDate(model.getDate());
holder.setStudents(model.getNumber_of_students());
holder.setSchoolIv(model.getImg_url());
}
#Override
public JournalHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.journal_list_item, parent, false);
return new JournalHolder(view);
}
};
And after don't forget:
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
adapter.startListening();
Related
I'm creating an app to simply store the records of a tractions and able to see the record.
In IteamListActivity I want to see my records of tractions.
I want to list all the data item in recycle view.
When I click 'View' button in activity_home xml, app crashes.
GitHub Link of the project is Here
Code is
Adapter
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.viewHolder>{
ArrayList<DataModel> list;
Context context;
public DataAdapter(ArrayList<DataModel> list, Context context) {
this.list = list;
this.context = context;
}
#NonNull
#Override
public viewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(context).inflate(R.layout.data_list_design,parent,false);
return new viewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
DataModel model = list.get(position);
holder.sn.setText(model.getSn());
holder.date.setText(model.getDate());
holder.name.setText(model.getName());
holder.weight.setText(model.getWeight());
holder.rate.setText(model.getRate());
holder.total.setText(model.getTotal());
}
#Override
public int getItemCount() {
return list.size();
}
public class viewHolder extends RecyclerView.ViewHolder {
TextView sn,date,name,weight,rate,total;
public viewHolder(#NonNull View itemView) {
super(itemView);
sn = itemView.findViewById(R.id.snTitle);
date = itemView.findViewById(R.id.dateTitle);
name = itemView.findViewById(R.id.nameTitle);
weight = itemView.findViewById(R.id.weightTitle);
rate = itemView.findViewById(R.id.rateTitle);
total = itemView.findViewById(R.id.totalTitle);
}
}
}
HomeActivity
binding.listview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(HomeActivity.this,ItemListActivity.class );
startActivity(intent);
}
});
ItemListActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityItemListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
ArrayList<DataModel> list = new ArrayList<>();
list.add(new DataModel(1,"2021-07-29","Potato", 76,50,100));
list.add(new DataModel(2,"2021-07-30","Potato", 106,60,100));
list.add(new DataModel(3,"2021-08-02","Potato", 83,80,100));
list.add(new DataModel(4,"2021-08-03","Potato", 67,90,100));
list.add(new DataModel(5,"2021-08-05","Potato", 70,70,100));
DataAdapter adapter = new DataAdapter(list,this);
LinearLayoutManager linearLayoutManager = new
LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
binding.datalistRv.setLayoutManager(linearLayoutManager);
binding.datalistRv.setNestedScrollingEnabled(false);
binding.datalistRv.setAdapter(adapter);
}
Solution is
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
DataModel model = list.get(position);
holder.sn.setText(model.getSn().toString());
holder.date.setText(model.getDate());
holder.name.setText(model.getName());
holder.weight.setText(model.getWeight().toString());
holder.rate.setText(model.getRate().toString());
holder.total.setText(model.getTotal().toString());
}
Reason of crush is model.getSn(), model.getWeight(), model.getRate(), model.getTotal() return Integer and textView.setText() calls public final void setText(#StringRes int resid) which tries to find string by Integers which you provided from your model.
I am using navigation component in my app I have 2 fragments one fragments list of items and another shows detail of an item when user clicks on an item in fragments 1 it goes to detail fragment and when I switch back to first fragment then all the listing duplicates again.
Below is my code:
CakeFragment.java
public class CakeFragment extends Fragment {
List<AllCakes> allCakeList = new ArrayList<>();
AllCakesAdapter adapter;
BottomNavigationView navView;
FragmentCakeBinding fragmentCakeBinding;
public CakeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeBinding = FragmentCakeBinding.inflate(inflater,container,false);
navView = getActivity().findViewById(R.id.navView);
navView.setVisibility(View.GONE);
getAllCakes();
return fragmentCakeBinding.getRoot();
}
private void getAllCakes(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<AllCakes>> call = apiService.getAllCake();
call.enqueue(new Callback<List<AllCakes>>() {
#Override
public void onResponse(Call<List<AllCakes>> call, Response<List<AllCakes>> response) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
fragmentCakeBinding.allCakeRecycler.setHasFixedSize(true);
fragmentCakeBinding.allCakeRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
#Override
public void onFailure(Call<List<AllCakes>> call, Throwable t) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
TastyToast.makeText(getActivity(),t.getMessage(),TastyToast.LENGTH_SHORT,TastyToast.ERROR).show();
}
});
}
}
AllCakesAdapter.java
public class AllCakesAdapter extends RecyclerView.Adapter<AllCakesAdapter.ViewHolder> {
Context context;
List<AllCakes> allCakeList;
public AllCakesAdapter(Context context, List<AllCakes> allCakeList) {
this.context = context;
this.allCakeList = allCakeList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.allcakes_row,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
AllCakes model = allCakeList.get(position);
Glide.with(context).load(model.getImgurl()).into(holder.allCakeImg);
holder.allCakeName.setText(model.getName());
holder.cakeDisPrice.setPaintFlags(holder.cakeDisPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.moreCake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavController navController = Navigation.findNavController((Activity) context,R.id.fragment);
navController.navigate(R.id.cakeDetailFragment);
}
});
}
#Override
public int getItemCount() {
return allCakeList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView allCakeImg;
Button moreCake;
TextView allCakeName;
public ViewHolder(#NonNull View itemView) {
super(itemView);
allCakeImg = itemView.findViewById(R.id.allCakeImg);
moreCake = itemView.findViewById(R.id.moreCake);
allCakeName = itemView.findViewById(R.id.allCakeName);
}
}
}
CakeDetailFragment.java
public class CakeDetailFragment extends Fragment {
FragmentCakeDetailBinding fragmentCakeDetailBinding;
public CakeDetailFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeDetailBinding = FragmentCakeDetailBinding.inflate(inflater,container,false);
return fragmentCakeDetailBinding.getRoot();
}
}
Why is this happening?
private void getAllCakes(){
...
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
...
you're calling:
allCakeList.addAll(response.body());
every time without clearing your list out.
you have to clear that list:
allCakeList.clear();
allCakeList.addAll(response.body());
this is something you can easily determine yourself by just putting a breakpoint on your allCakeList to see what's inside it, if you haven't ever done this before, you should consider trying it out
Try the following and see if it solves your issue
CakeFragment.java
allCakeList.clear();
allCakeList.addAll(response.body());
//rest of the logic remains same
sorry for my bad english
My problem: when I rotate my application, all data is lost, I am using a ViewModel, my data loads when I push the button, this is my code for test .
https://github.com/elviss116/androidMvvm-master
This is the Fragment :
public class MovieListFragment extends Fragment {
private MovieListViewModel mViewModel;
private List<MovieModel.DataModel> movieList = new ArrayList<>();
private RecyclerView recyclerView;
private MoviesAdapter mAdapter;
private Button cargar;
public static MovieListFragment newInstance() {
return new MovieListFragment();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.movie_list_fragment, container, false);
recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
cargar = view.findViewById(R.id.btnCargar);
mAdapter = new MoviesAdapter(movieList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
cargar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mViewModel = ViewModelProviders.of(MovieListFragment.this).get(MovieListViewModel.class);
mViewModel.init();
mViewModel.getMovies().observe(MovieListFragment.this, new Observer<MovieModel>() {
#Override
public void onChanged(#Nullable MovieModel movieModels) {
movieList.addAll(movieModels.getData());
mAdapter.notifyDataSetChanged();
}
});
}
});
}
}
this is the ViewModel :
public class MovieModel {
#SerializedName("data")
List<DataModel> data;
public List<DataModel> getData() {
return data;
}
public void setData(List<DataModel> data) {
this.data = data;
}
public class DataModel {
#SerializedName("name")
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
this is the adapter :
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<MovieModel.DataModel> moviesList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
}
}
public MoviesAdapter(List<MovieModel.DataModel> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.movie_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MovieModel.DataModel movie = moviesList.get(position);
holder.name.setText(movie.getName());
}
#Override
public int getItemCount() {
return moviesList.size();
}
}
When you rotate your phone the activity gets destroyed and re-created, so that is why you're seeing your data dissapear.
What I would recommend is grabbing and observing the view model when the activity is created, outside of the click listener. This way the fragment will immediately start observing the data when it is rotated, but will only be initialized when the button is clicked.
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(MovieListFragment.this).get(MovieListViewModel.class);
mViewModel.getMovies().observe(MovieListFragment.this, new Observer<MovieModel>() {
#Override
public void onChanged(#Nullable MovieModel movieModels) {
movieList.addAll(movieModels.getData());
mAdapter.notifyDataSetChanged();
}
});
cargar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mViewModel.init();
}
});
}
I want to use a recyclerView to show some products, they are inside firebase-firestore and, to get them I use a query. After this, I call the adapter to show but nothing appears.
You can see my adapter where:
public class ProdutoRecyclerAdapter extends FirestoreRecyclerAdapter <Produto, ProdutoRecyclerAdapter.ProdutoHolder> {
public ProdutoRecyclerAdapter(#NonNull FirestoreRecyclerOptions<Produto> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull ProdutoHolder produtoHolder, int i, #NonNull Produto produto) {
produtoHolder.tNome.setText(produto.getNomeP());
produtoHolder.tPontos.setText(String.valueOf(produto.getPontosP()));
}
#NonNull
#Override
public ProdutoHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.lista_produtos,parent,false);
ProdutoHolder holder = new ProdutoHolder(v);
return holder;
}
class ProdutoHolder extends RecyclerView.ViewHolder{
TextView tNome;
TextView tPontos;
public ProdutoHolder(#NonNull View itemView) {
super(itemView);
tNome = itemView.findViewById(R.id.nomeP);
tPontos= itemView.findViewById(R.id.pontosP);
}
}
And here there is my fragment:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.store,null);
toolbar = view.findViewById(R.id.toolbar_loja);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
Query query = produtoRef.orderBy("pontos");
FirestoreRecyclerOptions<Produto> option = new FirestoreRecyclerOptions.Builder<Produto>()
.setQuery(query, Produto.class)
.build();
adapter = new ProdutoRecyclerAdapter(option);
recyclerView = (RecyclerView) view.findViewById(R.id.produtos_list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
I don't have any error, but nothing appears on the screen, and I already did the debug and I know the variables are passing the right value.
At your adapter, you should have the override of getItemCount() and getItem()
/**
* Gets the item at the specified position from the backing snapshot array.
*
* #see ObservableSnapshotArray#get(int)
*/
#NonNull
public T getItem(int position) {
return mSnapshots.get(position);
}
#Override
public int getItemCount() {
return mSnapshots.isListening(this) ? mSnapshots.size() : 0;
}
where mSnapshots is your array of data.
Docuementation here
I'm having a problem with making a RecycleView in a fragment with data from Firebase. I expect the app to show the RecycleView after I clicked on a button to change from one fragment to the RecycleView fragment, but it does change the showed fragment but it does not show anything.
I know there are plenty of questions like this but I don't seem to find the correct solution to this problem.
I've made everything needed for a Firebase RecyclerView, and also tried to build it inside an activity instead fragment and it did work, but not with the fragment.
I've tried to initialize the adapter and recyclerview inside the onCreateView method, onActivityCreated, and onViewCreated method and none of them seem to be working.
Here's my fragment code:
private KidAdapter adapter;
private RecyclerView recyclerView;
Button button;
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.uangsaku_menu_fragment, container, false);
button = view.findViewById(R.id.btn_add);
button.setOnClickListener(this);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
setUpRecyclerView();
return view;
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.btn_add){
Intent intent = new Intent(getActivity(), Register.class);
startActivity(intent);
}
}
public void setUpRecyclerView(){
Query query = FirebaseDatabase.getInstance().getReference("kids");
FirebaseRecyclerOptions<kidData> options = new FirebaseRecyclerOptions.Builder<kidData>()
.setQuery(query, kidData.class)
.build();
adapter = new KidAdapter(options);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
}
#Override
public void onStart() {
super.onStart();
if (adapter != null) {
adapter.startListening();
}
}
#Override
public void onStop() {
super.onStop();
if (adapter != null) {
adapter.stopListening();
}
}
}
The adapter class
public class KidAdapter extends FirebaseRecyclerAdapter<kidData, KidAdapter.KidViewHolder> {
public KidAdapter(#NonNull FirebaseRecyclerOptions<kidData> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull KidViewHolder holder, int position, #NonNull kidData model) {
holder.nama.setText(model.getKidName());
holder.balance.setText(model.getKidBalance());
holder.limit.setText("Limit: "+model.getKidLimit());
holder.spending.setText("Spending xxx.xxx");
}
#NonNull
#Override
public KidViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.kids_card,
viewGroup, false);
return new KidViewHolder(v);
}
public class KidViewHolder extends RecyclerView.ViewHolder {
TextView nama, balance, limit, spending;
public KidViewHolder(#NonNull View itemView) {
super(itemView);
nama = itemView.findViewById(R.id.tv_nama);
balance = itemView.findViewById(R.id.tv_balance);
limit = itemView.findViewById(R.id.tv_dailylimit);
spending = itemView.findViewById(R.id.tv_dailyspending);
}
}
}
The kidData model class
public class kidData {
String kidName, kidEmail, kidDoB, kidLimit, kidBalance;
public kidData(){
}
public kidData(String kidName, String kidEmail, String kidDoB, String kidLimit, String kidBalance) {
this.kidName = kidName;
this.kidEmail = kidEmail;
this.kidDoB = kidDoB;
this.kidLimit = kidLimit;
this.kidBalance = kidBalance;
}
public String getKidName() {
return kidName;
}
public String getKidEmail() {
return kidEmail;
}
public String getKidDoB() {
return kidDoB;
}
public String getKidLimit() {
return kidLimit;
}
public String getKidBalance() {
return kidBalance;
}
}
The problem in your code is the use of the following line of code:
recyclerView.setHasFixedSize(true);
And this is because when using the latest version of Firebase-UI library, there is no need to set the size of the RecyclerView as fixed. The solution for solving this problem is to simply remove/comment the above line of code. That's it!