I have api call request with parameters: (page,pageSize:the maximum number of items desired(default 25,Maximum 100.From reddit api documentation)),and i want to use pagination in RecyclerView.My data is loading successfully but the problem how do i request to server for the next page.How i can perform pagination with method addOnScrollListener
WebService Class
public interface RedditWebService {
#GET("top.json")
Observable<Response> getTopPublication(#Query("count")int count,
#Query("limit")int pageSize);
}
Adapter Class
public class RedditAdapter extends RecyclerView.Adapter<RedditAdapter.RedditViewHolder> {
private List<Child> childList;
private Context context;
public RedditAdapter(Context context, List<Response.Data.Child> childList) {
this.childList = childList;
this.context = context;
}
#NonNull
#Override
public RedditViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_layout, parent, false);
return new RedditViewHolder(view);
}
#SuppressLint("DefaultLocale")
#Override
public void onBindViewHolder(#NonNull RedditViewHolder holder, int position) {
final Child child = childList.get(position);
holder.txtAuthor.setText(child.getmData().getmAuthor());
String timeAgo = TimeAgo.getTimeAgo(child.getmData().getmCreated());
Log.d("Time", "" + timeAgo);
holder.txtDate.setText(timeAgo);
holder.txtComment.setText(String.format("Comments: %d", child.getmData().getmNumComments()));
Picasso.get().load(child.getmData().getmThumbnail()).placeholder(R.drawable.placeholder).
transform(ImageTransformation.getTransformation(holder.imageView)).into(holder.imageView);
if (!child.getmData().getmThumbnail().equals("")) {
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context.getApplicationContext(), SecondActivity.class);
intent.putExtra("extraImage", child.getmData().getmThumbnail());
context.startActivity(intent);
}
});
}
}
#Override
public int getItemCount() {
return (childList == null) ? 0 : childList.size();
}
public class RedditViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView txtDate, txtAuthor, txtComment;
public RedditViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_view);
txtDate = itemView.findViewById(R.id.txt_date);
txtAuthor = itemView.findViewById(R.id.txt_author);
txtComment = itemView.findViewById(R.id.txt_comments_num);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private ProgressBar progressBar;
private RedditAdapter adapter;
private List<Child> redditList = new ArrayList<>();
private CompositeDisposable disposable = new CompositeDisposable();
private int page = 0;
private int pageSize = 50;
#Inject
RedditWebService webService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((BaseApplication) getApplication()).getComponent().inject(this);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progress_bar);
recyclerView = findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(this);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
fetchData();
}
private void fetchData() {
progressBar.setVisibility(View.VISIBLE);
disposable.add(webService.getTopPublication(page,pageSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Response>() {
#Override
public void accept(Response response) throws Exception {
adapter = new RedditAdapter(MainActivity.this, response.getData().getChildren());
recyclerView.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, throwable.toString(), Toast.LENGTH_LONG).show();
}
}));
}
Thanks in advance
Use EndlessRecyclerViewScrollListener.java, it will provide very easy way to do load more call.
Maintain one global variable "page" initialize by 1, and increase it by 1 on every API call or load more call.
EndlessRecyclerViewScrollListener scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
page++;
loadMoreCall(page);
}
};
inside loadMoreCall() you need to add your api call, and after successfull api call, you need to set data to your list and then you need to notify your adaper. thats it only.
reference: https://guides.codepath.com/android/endless-scrolling-with-adapterviews-and-recyclerview
here how to call, api using retrofit:
https://demonuts.com/android-recyclerview-retrofit/
Consider using the new paging library. Here's a sample and the documentation. It performs better and you don't have to manually keep track where you are in the scrolling. By following the sample I found it fairly easy to implement this, although it is a lot of boilerplate code.
Related
I have an issue where notifyDataSetChanged() in a response call will blank out the recyclerview but if the Adapter is initiated manually with a onClick, the recyclerview works. I have tested that the List has the items inside before calling notifyDataSetChanged() so i'm not sure what's wrong here.
[Main Activity] This works but i have to manually click the bnQuery.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
apiInterface = API_client.getClient().create(APIInterface.class);
etCoin = (EditText) findViewById(R.id.etCoin);
bnQuery = (Button) findViewById(R.id.bnQuery);
rcvMain = findViewById(R.id.rcvMain);
getCoinData("2");
//initRCV_Main();
bnQuery.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//getCoinData("2");
initRCV_Main();
}
});
}
private void initRCV_Main() {
rcvMainAdp = new rcvMainAdapter(cList);
rcvMain.setAdapter(rcvMainAdp);
rcvMain.setLayoutManager(new LinearLayoutManager(this));
}
private void getCoinData(String coinLimit){
Call<cInfoPack> call = apiInterface.doGetCoinData(coinLimit);
call.enqueue(new Callback<cInfoPack>() {
#Override
public void onResponse(Call<cInfoPack> call, Response<cInfoPack> response) {
cInfoPack list = response.body();
List<cData> listSorter = new ArrayList<>();
listSorter.addAll(list.getData());
Collections.sort(listSorter, new SortbyVolChg());
cList.clear();
cList = listSorter;
System.out.println("list " + list.getData().get(0).getQuote());
System.out.println("listSorter " + listSorter.get(0).getQuote());
System.out.println("cList " + cList.get(0).getQuote());
//rcvMainAdp.notifyDataSetChanged();
}
#Override
public void onFailure(Call<cInfoPack> call, Throwable t) {
Toast.makeText(MainActivity.this, "onFailure", Toast.LENGTH_SHORT).show();
Log.d("XXXX", t.getLocalizedMessage());
call.cancel();
}
});
}
[Main Activity] If i initiate the recyclerview during onCreate and use the notifyDataSetChanged() during getCoinData, I get a blank recycleview. system.out shows that the lists all contain information in them.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
apiInterface = API_client.getClient().create(APIInterface.class);
etCoin = (EditText) findViewById(R.id.etCoin);
bnQuery = (Button) findViewById(R.id.bnQuery);
rcvMain = findViewById(R.id.rcvMain);
getCoinData("2");
initRCV_Main();
bnQuery.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//getCoinData("2");
//initRCV_Main();
}
});
}
private void initRCV_Main() {
rcvMainAdp = new rcvMainAdapter(cList);
rcvMain.setAdapter(rcvMainAdp);
rcvMain.setLayoutManager(new LinearLayoutManager(this));
}
private void getCoinData(String coinLimit){
Call<cInfoPack> call = apiInterface.doGetCoinData(coinLimit);
call.enqueue(new Callback<cInfoPack>() {
#Override
public void onResponse(Call<cInfoPack> call, Response<cInfoPack> response) {
cInfoPack list = response.body();
List<cData> listSorter = new ArrayList<>();
listSorter.addAll(list.getData());
Collections.sort(listSorter, new SortbyVolChg());
cList.clear();
cList = listSorter;
System.out.println("list " + list.getData().get(0).getQuote());
System.out.println("listSorter " + listSorter.get(0).getQuote());
System.out.println("cList " + cList.get(0).getQuote());
rcvMainAdp.notifyDataSetChanged();
}
#Override
public void onFailure(Call<cInfoPack> call, Throwable t) {
Toast.makeText(MainActivity.this, "onFailure", Toast.LENGTH_SHORT).show();
Log.d("XXXX", t.getLocalizedMessage());
call.cancel();
}
});
}
[Adapter]
public class rcvMainAdapter extends RecyclerView.Adapter<rcvMainAdapter.ViewHolder> {
private List<cData> idxCoin;
//ItemClickListener itemClickListener;
rcvMainAdapter(List<cData> data) {this.idxCoin = data;}
#NonNull
#NotNull
#Override
public ViewHolder onCreateViewHolder(#NonNull #NotNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.rcv_main,parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull #NotNull ViewHolder holder, int position) {
cData cdata = idxCoin.get(position);
TextView tvSym = holder.tvSymbol;
tvSym.setText(cdata.getSymbol());
TextView tvQuo = holder.tvQuote;
BigDecimal tvQuote_BD = new BigDecimal(cdata.getQuote().getuSD().getPrice().toString());
tvQuote_BD.setScale(6, RoundingMode.DOWN);
tvQuo.setText(tvQuote_BD.toString());
TextView tvV24 = holder.tvVolume24;
BigDecimal tvVolume24_BD = new BigDecimal(cdata.getQuote().getuSD().getVolume24h().toString());
BigInteger tvVolume24_BI = tvVolume24_BD.toBigInteger();
tvV24.setText(tvVolume24_BI.toString());
}
#Override
public int getItemCount() {
return idxCoin.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvSymbol, tvQuote, tvVolume24;
public ViewHolder(#NonNull #NotNull View itemView) {
super(itemView);
tvSymbol = itemView.findViewById(R.id.tvSymbol);
tvQuote = itemView.findViewById(R.id.tvQuote);
tvVolume24 = itemView.findViewById(R.id.tvVolume24);
//itemView.setOnClickListener(this);
}
}
/*
public interface ItemClickListener{
void onItemClick(View view, int position);
}
*/
}
PS: apologies for the rubbish coding as this is self taught and modifying some codes found online.
Remove this in response.
cList.clear();
Add This line in response
rcvMainAdp.setdata(listSorter);
In rcvMainAdp Adapter, Create a Method setdata()
public void setdata(ArrayList<cData> data) {
this.idxCoin = data;
notifyDataSetChanged();
}
Problem most likely is that when you call initRCV_Main() You set the adapter to the list as in rcvMainAdp = new rcvMainAdapter(cList); And when list is changed and you set it to adapter it functions.
But when you call getCoinData() and rcvMainAdp.notifyDataSetChanged(); at the end you never set the changed list to the adapter until you click initRCV_Main() again.
So maybe the fix is calling rcvMainAdp = new rcvMainAdapter(cList) and then
rcvMainAdp.notifyDataSetChanged();
I am using retrofit to search the images and displaying. I am using SearchView to search and recyclerview and adapter to display the item.
It's working for the very first time. Second time when I search, it's displaying the same item. It's not clearing the view to display.
Here is my code:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
ImagesViewModel newsViewModel;
List<Hits> newsArticles;
List<Hits> articleArrayList;
ImagesAdapter newsAdapter;
RecyclerView rvHeadline;
SearchView searchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvHeadline = (RecyclerView) findViewById(R.id.rvNews);
searchView=(SearchView) findViewById(R.id.searchView);
searchView.setQueryHint("Search Images");
searchView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchView.setIconified(false);
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
callPixabayImages(query);
Toast.makeText(getBaseContext(), query, Toast.LENGTH_LONG).show();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
callPixabayImages(newText);
Toast.makeText(getBaseContext(), newText, Toast.LENGTH_LONG).show();
return false;
}
});
articleArrayList = new ArrayList<>();
}
private void callPixabayImages(String query){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ImageApiInterface.PIXABAY_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ImageApiInterface api = retrofit.create(ImageApiInterface.class);
Call<MyImages> call = api.getMovieDetails(query);
call.enqueue(new Callback<MyImages>() {
#Override
public void onResponse(Call<MyImages> call, Response<MyImages> response) {
Log.e("response","response"+response.code());
if(response.isSuccessful()){
Log.e("response","response"+response.code());
if((response.body() != null ? response.body().getHits() : null) !=null){
List<Hits> imagesList = response.body().getHits();
articleArrayList.addAll(imagesList);
newsAdapter.notifyDataSetChanged();
}
}
}
#Override
public void onFailure(Call<MyImages> call, Throwable t) {
System.out.println("Error: "+ t.getMessage());
Log.e("response","response"+t);
}
});
}
private void setupRecyclerView() {
if (newsAdapter == null) {
newsAdapter = new ImagesAdapter(MainActivity.this, articleArrayList);
rvHeadline.setLayoutManager(new LinearLayoutManager(this));
rvHeadline.setAdapter(newsAdapter);
rvHeadline.setItemAnimator(new DefaultItemAnimator());
rvHeadline.setNestedScrollingEnabled(true);
} else {
newsAdapter.notifyDataSetChanged();
}
}
Here where I need to reset to search the new item inorder to avoid to display the previous item. List is not clearing to display the new items.
Here is Adapter class:
public class ImagesAdapter extends RecyclerView.Adapter<ImagesAdapter.NewsViewHolder> {
private Context context;
private List<Hits> articles;
public ImagesAdapter(Context context, List<Hits> articles) {
this.context = context;
this.articles = articles;
}
#NonNull
#Override
public ImagesAdapter.NewsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.images_item, parent, false);
return new NewsViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ImagesAdapter.NewsViewHolder holder, final int position) {
String image = articles.get(position).getLargeImageURL();
Log.e("imagestest",image);
if (image != null) {
Glide.with(context) //passing context
.load(image) //passing your url to load image.
.dontAnimate()
.placeholder(context.getDrawable(R.drawable.image_not_available)) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
//.centerCrop()//this method help to fit image into center of your ImageView
.into(holder.ivNews); //pass imageView reference to appear the image.*/
}
}
#Override
public int getItemCount() {
return articles.size();
}
class NewsViewHolder extends RecyclerView.ViewHolder {
ImageView ivNews;
private NewsViewHolder(#NonNull View itemView) {
super(itemView);
ivNews = itemView.findViewById(R.id.ivNews);
}
}
}
I am clueless where exactly I need to clear the view to fetch the newly searched item.
Trial 1: I tried to clear the list object articleArrayList but it throws crash that adapter size is null.
Clean the
articleArrayList
before loading the searched items again.... by executing this line articleArrayList.clear();
public void onResponse(Call<MyImages> call, Response<MyImages> response) {
Log.e("response","response"+response.code());
if(response.isSuccessful()){
Log.e("response","response"+response.code());
if((response.body() != null ? response.body().getHits() : null) !=null){
List<Hits> imagesList = response.body().getHits();
articleArrayList.clear();
articleArrayList.addAll(imagesList);
newsAdapter.notifyDataSetChanged();
}
}
You're adding generated imagesList to the articleArrayList, you should be replacing the values.
articleArrayList = imagesList;
I have one activity which connects with database and all my data is coming, but I want when I click on one Card view to open data from data Card.
I have like on the first-page category and when I click on one I want to get all projects that are in that category.
I'm still learning (on my own) and this is the first problem I can't solve by myself.
Plesa helps me.
I have tried everything I can find online.
public class MainActivity extends AppCompatActivity {
ImageButton imageButton;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference firemRef = db.collection("kategorije");
private FirmeAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpRecyclerView();
}
private void setUpRecyclerView(){
Query query= firemRef.orderBy("logo",Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Firme> options = new
FirestoreRecyclerOptions.Builder<Firme>()
.setQuery(query,Firme.class)
.build();
adapter= new FirmeAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
public void onClickButton (View view){
Intent intent= new Intent(MainActivity.this,BeautyIzbornik.class);
MainActivity.this.startActivity(intent);
}
}
My ADAPTER
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.squareup.picasso.Picasso;
public class FirmeAdapter extends FirestoreRecyclerAdapter<Firme, FirmeAdapter.FirmeHolder> {
/**
* Create a new RecyclerView adapter that listens to a Firestore Query. See {#link
* FirestoreRecyclerOptions} for configuration options.
*
* #param options
*/
public FirmeAdapter(#NonNull FirestoreRecyclerOptions<Firme> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull FirmeHolder holder, int position, #NonNull final Firme model) {
holder.naziv.setText(model.getNaziv());
holder.setLogo(model.getLogo());
}
#NonNull
#Override
public FirmeHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.firme_item,
viewGroup,false);
return new FirmeHolder(v);
}
class FirmeHolder extends RecyclerView.ViewHolder {
ImageButton imageButton;
TextView naziv;
public FirmeHolder(#NonNull final View itemView) {
super(itemView);
naziv = itemView.findViewById(R.id.naziv);
imageButton =itemView.findViewById(R.id.logo);
}
public void setLogo(String logo) {
Picasso.get().load(logo).into(imageButton);
}
}
}
My Activity with my data
public class Firme {
public String logo;
public String naziv;
public String url;
public Firme ( ) {
}
public Firme (String naziv, String logo , String url){
this.logo= logo;
this.naziv= naziv;
this.url = url;
}
public String getLogo() {
return logo;
}
public String getNaziv() {
return naziv;
}
public void setLogo(String logo){
this.logo = logo;
}
public String getUrl(){
return url;
}
public void setUrl(String url){
this.url=url;
}
}
you have to perform a click listener on RecyclerView item :
Since each item has its own data , you should use this data to show the adequate information :
This how to implement a click listener for RecyclerView
In your RecyclerView.Adapter simply create an interface you can use.
private onItemClickListener mItemClickListener;
public void setOnItemClickListener(onItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public interface onItemClickListener {
void onItemClickListener(View view, int position, MyData myData);
}
In this case mItemClickListener is a global variable inside your adapter and the two methods go inside your adapter, too.
Then inside your ViewHolder apply a click listener to your itemView with itemView.setOnClickListener(this) (or whatever component you want clicked to retrieve the data)
#Override
public void onClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClickListener(view, getAdapterPosition(), my_data.get(getAdapterPosition()));
}
}
This will then pass the view that has been clicked, the position of said view and the object that is contained in your list within that position.
So in your Activity, you can then just simply call the interface.
adapter.setOnItemClickListener(new CustomAdapter.onItemItemClickListener() {
#Override
public void onItemClickListener(View view, int position, MyData data) {
//do on item click functionality here
}
});
Hello everyone I am doing a news app for university and I have kind of problem with displaying saved data to another activity. Im using retrofit to get data from internet and Sugar ORM to save data localy. So, news are displaying great and I created a CardView where it has a button "Read Later". The method to save data into database s working (at least on log it shows that it is working) but I cant get saved data to read_later activity. Alos I have an Adapter which contains onBindViewHolder.
#Override
public void onBindViewHolder(#NonNull MainArticalAdapter.ViewHolder viewHolder, int position) {
final Article articleModel = articleArrayList.get(position);
if(!TextUtils.isEmpty(articleModel.getTitle())){
viewHolder.titleText.setText(articleModel.getTitle());
}
if(!TextUtils.isEmpty(articleModel.getDescription())) {
viewHolder.descriptionText.setText(articleModel.getDescription());
}
if(!TextUtils.isEmpty(articleModel.getUrlToImage())){
Picasso.get().load(articleModel.getUrlToImage())
.resize(700,500)
.centerInside()
.into(viewHolder.imgView);
}
viewHolder.artilceAdapterParentLinear.setTag(articleModel);
Button btn = viewHolder.btn_read_later;
btn.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
Article art = new Article();
art.setAuthor("Harun Shaban");
art.save();
}
}
);
}
and viewholder which extends RecyclerView.ViewHolder
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView titleText, descriptionText;
private LinearLayout artilceAdapterParentLinear;
private ImageView imgView;
private Button btn_read_later;
public ViewHolder(#NonNull View view) {
super(view);
btn_read_later = view.findViewById(R.id.button_read_later);
imgView = view.findViewById(R.id.article_adapter_image_view);
titleText = view.findViewById(R.id.article_adapter_tv_title);
descriptionText = view.findViewById(R.id.article_adapter_tv_description);
artilceAdapterParentLinear = view.findViewById(R.id.article_adapter_ll_parent);
artilceAdapterParentLinear.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if(onRecyclerViewItemClickListener != null){
onRecyclerViewItemClickListener.onItemClick(getAdapterPosition(),view);
}
}
}
);
}
}
and this is in my MainActivity class which contains a method to display all data received from internet by retrofit
private void showData(){
// Second step to create the recycler view to show the data taken
final RecyclerView mainRecycler = findViewById(R.id.activity_main_tv);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mainRecycler.setLayoutManager(linearLayoutManager);
// First step to create the response
final APIInterface apiService = ApiClient.getClient().create(APIInterface.class);
Call<ResponeModel> call = apiService.getLatestNews("techcrunch", API_KEY);
//third step
call.enqueue(new Callback<ResponeModel>() {
#Override
public void onResponse(Call<ResponeModel> call, Response<ResponeModel> response) {
if(response.body().getStatus().equals("ok")){
List<Article> articleList = response.body().getArticles();
if(articleList.size()>0){
final MainArticalAdapter mainArticalAdapter = new MainArticalAdapter(articleList);
mainArticalAdapter.setOnRecyclerViewItemClickListener(MainActivity.this);
mainRecycler.setAdapter(mainArticalAdapter);
}
}
}
#Override
public void onFailure(Call<ResponeModel> call, Throwable t) {
Log.e("on Fail", t.toString());
}
});
}
I tried to work with same logic in Read_later_Activity but it crashes.
This is my Read_later_activity…
public void getDatafromDB() {
List <Article> savedArticles = Article.listAll(Article.class);
final RecyclerView read_later_recView = findViewById(R.id.activity_read_later_tv);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
read_later_recView.setLayoutManager(linearLayoutManager);
if(savedArticles.size()>0){
final MainArticalAdapter mainArticalAdapter = new MainArticalAdapter(savedArticles);
mainArticalAdapter.setOnRecyclerViewItemClickListener((OnRecyclerViewItemClickListener) ReadLaterActivity.this);
read_later_recView.setAdapter(mainArticalAdapter);
//to retrieve the data from DB, by id (crashes)
//Article art = Article.findById(Article.class, 0);
//titleText_readLater.setText(art.getTitle());
/*Don`t know what to do*/
}
}
Currently I can display all of the items in my RecyclerView. What I wish to do is calculate how many of these items there are. My items are saved in CardView. I don't want to calculate or sum any particular field, just the number of actual items. Here is my code and I have tried to set it up using getItemCount() method and attach this to a TextView and display outside of RecyclerView. This is not working for me:
public class COM800s1 extends AppCompatActivity {
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference attendanceRef = db.collection("Attendance");
private AttendanceAdapter adapter;
private Context context;
private TextView attendanceNumbers;
private int counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_com800s1);
attendanceNumbers = findViewById(R.id.attendanceNums);
FloatingActionButton floatingActionButton = findViewById(R.id.button_add_session);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(COM800s1.this,NewAttendanceRecord.class));
}
});
setUpRecyclerView();
}
private void setUpRecyclerView() {
final Query query = attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").orderBy("userEmail", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Attendance> options = new FirestoreRecyclerOptions.Builder<Attendance>()
.setQuery(query, Attendance.class).build();
adapter = new AttendanceAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
//counter = adapter.getItemCount();
//attendanceNumbers.setText("Currently " +counter+ " students have attended this session");
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.deleteItem(viewHolder.getAdapterPosition());
}
}).attachToRecyclerView(recyclerView);
adapter.setSetOnItemClickListener(new AttendanceAdapter.OnItemClickListener() {
#Override
public void onItemClick(Attendance documentSnapshot, int position) {
}
});
}
#Override
protected void onStart () {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop(){
super.onStop();
adapter.stopListening();
}
}
Here is my Adapter code:
public class AttendanceAdapter extends FirestoreRecyclerAdapter<Attendance, AttendanceAdapter.AttendanceHolder>{
private AttendanceAdapter.OnItemClickListener listener;
public AttendanceAdapter(#NonNull FirestoreRecyclerOptions<Attendance> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull AttendanceHolder holder, int position, #NonNull Attendance model) {
holder.textViewStudent.setText(model.getUserEmail());
holder.textViewTime.setText(model.getSignInTime());
holder.textViewSession.setText(model.getSessionID());
holder.textViewUserUID.setText(model.getUserUID());
}
#NonNull
#Override
public AttendanceHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.attendance_item, parent, false);
return new AttendanceAdapter.AttendanceHolder(v);
}
public void deleteItem(int position){
getSnapshots().getSnapshot(position).getReference().delete();
}
public int countItems(){
return getItemCount();
}
class AttendanceHolder extends RecyclerView.ViewHolder {
TextView textViewStudent;
TextView textViewTime;
TextView textViewSession;
TextView textViewUserUID;
public AttendanceHolder(View itemView){
super(itemView);
textViewStudent = itemView.findViewById(R.id.text_view_student_name);
textViewTime = itemView.findViewById(R.id.text_view_course);
textViewSession = itemView.findViewById(R.id.text_view_student_ID);
textViewUserUID = itemView.findViewById(R.id.text_view_user_UID);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && listener != null){
listener.onItemClick(getSnapshots().get(position),position);
}
}
});
}
}
public interface OnItemClickListener{
void onItemClick(Attendance documentSnapshot, int position);
}
public void setSetOnItemClickListener(AttendanceAdapter.OnItemClickListener listener){
this.listener = listener;
}
Here is my updates code which returns null pointer object on the onClickListener:
public class COM800s1 extends AppCompatActivity {
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference attendanceRef = db.collection("Attendance");
private AttendanceAdapter adapter;
private TextView attendanceNumbers;
private TextView attendanceNumbs;
private Button attendanceButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_com800s1);
attendanceNumbs = findViewById(R.id.attendanceNums);
attendanceButton = findViewById(R.id.calculateAttendance);
FloatingActionButton floatingActionButton = findViewById(R.id.button_add_session);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(COM800s1.this,NewAttendanceRecord.class));
}
});
setUpRecyclerView();
attendanceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
int count = 0;
for (DocumentSnapshot document : task.getResult()) {
count++;
attendanceNumbs = findViewById(R.id.attendanceNums);
attendanceNumbs.setText(count);
}
Log.d("TAG", count + "");
} else {
}
}
});
}
});
}
private void setUpRecyclerView() {
final Query query = attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").orderBy("userEmail", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Attendance> options = new FirestoreRecyclerOptions.Builder<Attendance>()
.setQuery(query, Attendance.class).build();
adapter = new AttendanceAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.deleteItem(viewHolder.getAdapterPosition());
}
}).attachToRecyclerView(recyclerView);
adapter.setSetOnItemClickListener(new AttendanceAdapter.OnItemClickListener() {
#Override
public void onItemClick(Attendance documentSnapshot, int position) {
}
});
}
#Override
protected void onStart () {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop(){
super.onStop();
adapter.stopListening();
}
}
If you want to get the list of your recyclerView just create a static method in your recyclerView's adapter and just return your list in that.
for example:
public static List<modelOfYourList> getCount(){
return yourAdapterList;
}
Perhaps add something like this to your AttendanceAdapter class?
I took a look at the FirestoreRecyclerOptionsclass, which exposes a getSnapshots() method. This returns a ObservableSnapshotArray, which in turn extends from Base ObservableSnapshotArray, which exposes a size() method.
class AttendanceAdapter extends FirestoreRecyclerAdapter<Attendance, AttendanceAdapter.AttendanceHolder>{
{
private FirestoreRecyclerOptions<Attendance> options;
public AttendanceAdapter(#NonNull FirestoreRecyclerOptions<Attendance> options)
{
super(options);
this.options = options;
}
#Override
public int getItemCount()
{
final int count = options.getSnapshots() != null
? options.getSnapshots().size()
: 0;
return count;
}
Sources:
FirestoreRecyclerOptions
ObservableSnapshotArray
BaseObservableSnapshotArray
Update: I see that the FirestoreRecyclerAdapter already has a getItemCount method already and you are calling it. Perhaps the data has not yet returned? What are you seeing for the count when you print it?
If you are trying to make the counter variable as a global variable and use it outside the callback it will always be null because as #Vinnie mentioned in his answer, the data has not finished loading yet. What's really happening is that you are trying to get the data from the database and immediately use it it while the counter variable has the initial value of 0. Then, when getting the data from the database completes, it changes counter's value, but it's never read again. To solve this, the use result of your getItemCount() method inside your adapter class to set it's value to the TextView.
If you want to count the number of documents beneath a collection, please also see my answer from this post.