Unable to populate RecyclerView adapter with Firebase data - android

I'm trying to fetch the data from my Firebase database but from some reason it doesn't work, so I'll try to provide as much info as posible ..
This is the database snapshot:
This is a POJO class:
public class Result2 implements Serializable {
private int score;
private String userName;
public Result2(int score, String userName) {
this.score = score;
this.userName = userName;
}
public int getScore() {
return score;
}
public String getUserName() {
return userName;
}
}
This is my activitys layout called activity_results.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:weightSum="2"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:textColor="#000"
android:textSize="16sp"
android:gravity="center"
android:text="USERNAME"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<TextView
android:textColor="#000"
android:textSize="16sp"
android:text="SCORE"
android:gravity="center"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
<View
android:background="#000"
android:layout_width="match_parent"
android:layout_height="1dp"
/>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10dp"
android:clipToPadding="false"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
As you can see, I want to have 2 TextViews that will act like tabs and a RecyclerView underneath that will show the data
Here is my Adapters ViewHolder layout called score_view_holder.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/username"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="14sp" />
<TextView
android:id="#+id/score"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="14sp" />
</LinearLayout>
<View
android:background="#4545"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"/>
So it will contain two horizontal TextViews and a View as a line below..
Here is my Adapter:
public class ScoreAdapter extends RecyclerView.Adapter<ScoreAdapter.ScoreViewHolder> {
private List<Result2> results = new ArrayList<>();
public void setResults(List<Result2> results) {
this.results.clear();
this.results.addAll(results);
notifyDataSetChanged();
}
#Override
public ScoreAdapter.ScoreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.score_view_holder, parent, false);
return new ScoreAdapter.ScoreViewHolder(view);
}
#Override
public void onBindViewHolder(ScoreAdapter.ScoreViewHolder holder, int position) {
Result2 result = getResult(position);
if (result != null) {
holder.setUsername(result.getUserName() != null ? result.getUserName() : "-");
holder.setScore(String.valueOf(result.getScore()));
}
}
private Result2 getResult(int position) {
return !results.isEmpty() ? results.get(position) : null;
}
#Override
public int getItemCount() {
return results.size();
}
public class ScoreViewHolder extends RecyclerView.ViewHolder {
private TextView username;
private TextView score;
public ScoreViewHolder(View itemView) {
super(itemView);
username = itemView.findViewById(R.id.username);
score = itemView.findViewById(R.id.score);
}
public void setUsername(String username) {
this.username.setText(username);
}
public void setScore(String score) {
this.score.setText(score);
}
}
}
It should get List of Result2 objects and just set text in those two TextViews (username and score)
And finally my Activity where all the magic doesn't happen :)
public class Results extends AppCompatActivity {
private DatabaseReference mDatabase;
private ScoreAdapter scoreAdapter;
private RecyclerView recyclerView;
private List<Result2> results = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
recyclerView = findViewById(R.id.recycler_view);
scoreAdapter = new ScoreAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(scoreAdapter);
mDatabase = FirebaseDatabase.getInstance().getReference();
loadResults();
}
private void loadResults() {
mDatabase.child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
Result2 result = childSnapshot.getValue(Result2.class);
if(result != null) {
results.add(result);
}
}
Toast.makeText(Results.this, String.valueOf(results.size()), Toast.LENGTH_SHORT).show();
scoreAdapter.setResults(results);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
}
);
}
}
Funniest thing, Toast shows correct number of Results, but when scoreAdapter.setResults(results); is called, screen blinks and goes back to first screen... Does it have something to do with a POJO class, or onDataChange method or main thread?
I tried with debugging and also funny thing here.. This is what is caught on breakpoint inside ScoreAdapter setResult method:
I tried setting breakpoints inside onBindViewHolder and getResults() but none of them gets called :o

if(result != null) {
results.add(result);
}
See here you are checking result != null. But result is a reference variable of type Results. So it will not be null, it will contains some value.
So, try removing that if statement and do only -
results.add(result);

Related

android visible for linearlayout does not work

I create one recyclerview with address. When this recyclerview is empty, want one spesicif LinearLayout appear and when recyclerView has one or more items this LinearLayout disapear.But it is not working. I use funtions setVisibility(). Please help!!!
My code for xml is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/user_location_bg_color"
android:orientation="vertical"
tools:context=".UserLocationActivity">
<ImageButton
android:id="#+id/user_location_back_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="50dp"
android:background="#color/my_account_bg_color"
android:contentDescription="#null"
android:src="#drawable/ic_back" />
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:text="#string/user_location_text"
android:textColor="#color/black"
android:textSize="20sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:background="#color/black" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/coffee_recycler_bg_color" />
<LinearLayout
android:id="#+id/empty_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="invisible">
<pl.droidsonroids.gif.GifImageView
android:id="#+id/location_giffy"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:src="#drawable/location_gif" />
<TextView
android:id="#+id/user_location_blank_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="60dp"
android:gravity="center"
android:text="#string/user_address_blank_text"
android:textColor="#color/black"
android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center|bottom"
android:orientation="vertical">
<Button
android:id="#+id/add_new_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
android:backgroundTint="#color/btn_add_new_address"
android:text="#string/btn_add_new_address_text"
android:textAllCaps="false"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
My code for Activity is:
public class UserLocationActivity extends AppCompatActivity implements AddressAdapter.OnAddressListener {
//Init Variables
RecyclerView recyclerAddress;
private FirebaseDatabase db = FirebaseDatabase.getInstance();
private DatabaseReference ref = db.getReference().child("UserAddress");
private AddressAdapter adapter;
private ArrayList<UserLocation> list;
public LinearLayout empty_address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_location);
recyclerAddress = findViewById(R.id.recycler_address);
recyclerAddress.setHasFixedSize(true);
recyclerAddress.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList<>();
adapter = new AddressAdapter(this, list, this);
recyclerAddress.setAdapter(adapter);
empty_address = findViewById(R.id.empty_address);
if (adapter.getItemCount() == 0) {
//making it semi-transparent
empty_address.setVisibility(LinearLayout.VISIBLE);
}
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
UserLocation userLocation = dataSnapshot.getValue(UserLocation.class);
list.add(userLocation);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
#Override
public void onAddressItemDelete(int position) {
}
}
My adapter code is:
public class AddressAdapter extends RecyclerView.Adapter<AddressAdapter.AddressViewHolder> {
private List<UserLocation> listData = new ArrayList<>();
UserLocationActivity userLocationActivity;
private OnAddressListener mOnAddressListener;
public AddressAdapter(UserLocationActivity userLocationActivity, List<UserLocation> listData, OnAddressListener onAddressListener){
this.listData = listData;
this.userLocationActivity = userLocationActivity;
this.mOnAddressListener = onAddressListener;
}
#NonNull
#Override
public AddressViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(userLocationActivity).inflate(R.layout.address_item , parent, false);
return new AddressViewHolder(v,mOnAddressListener);
}
#Override
public void onBindViewHolder(#NonNull AddressViewHolder holder, int position) {
UserLocation userLocation = listData.get(position);
holder.addressItem.setText(userLocation.getUserLocation());
}
#Override
public int getItemCount() {
if (listData.size() == 0){
userLocationActivity.empty_address.setVisibility(LinearLayout.VISIBLE);
}
return listData.size();
}
public static class AddressViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView addressItem;
public ImageView btnAddressItemDelete;
OnAddressListener onAddressListener;
public AddressViewHolder(View itemView, OnAddressListener onAddressListener){
super(itemView);
addressItem = itemView.findViewById(R.id.address_item);
btnAddressItemDelete = itemView.findViewById(R.id.btn_address_item_delete);
this.onAddressListener = onAddressListener;
}
#Override
public void onClick(View v) {
onAddressListener.onAddressItemDelete(getAdapterPosition());
}
}
public interface OnAddressListener{
void onAddressItemDelete(int position);
}
}
It seems there's a bug in your code, I have fixed it.
The bug is you're checking recyclerView is empty first then adding the data into recyclerView
public class UserLocationActivity extends AppCompatActivity implements AddressAdapter.OnAddressListener {
//Init Variables
RecyclerView recyclerAddress;
private FirebaseDatabase db = FirebaseDatabase.getInstance();
private DatabaseReference ref = db.getReference().child("UserAddress");
private AddressAdapter adapter;
private ArrayList<UserLocation> list;
public LinearLayout empty_address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_location);
recyclerAddress = findViewById(R.id.recycler_address);
recyclerAddress.setHasFixedSize(true);
recyclerAddress.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList<>();
adapter = new AddressAdapter(this, list, this);
recyclerAddress.setAdapter(adapter);
empty_address = findViewById(R.id.empty_address);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
UserLocation userLocation =
dataSnapshot.getValue(UserLocation.class);
list.add(userLocation);
}
adapter.notifyDataSetChanged();
if (list.size() == 0) {
empty_address.setVisibility(View.VISIBLE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
#Override
public void onAddressItemDelete(int position) {
}
}

RecyclerView does not show list of objects

I tried the solutions on the other similar posts that I found here but they did not help me. I hope someone can help.
I get data from Unsplash's API and the ArrayList contains 10 items once I get a response, that's why I think It has to be something with the way the view is inflated.
This is code:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "unsplash";
private final String CLIENT_ID = "...myclientID...";
// testing keyword used on the API to search for pictures
private final String KEYWORD = "stackOverflow";
private final String urlBase = "https://api.unsplash.com/";
private Retrofit retrofit;
private RecyclerView recyclerView;
private RecyclerViewAdapter recyclerViewAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
retrofit = new Retrofit.Builder()
.baseUrl(urlBase)
.addConverterFactory(GsonConverterFactory.create())
.build();
recyclerView = findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(layoutManager);
recyclerViewAdapter = new RecyclerViewAdapter();
recyclerView.setAdapter(recyclerViewAdapter);
getData();
}
private void getData() {
PictureService service = retrofit.create(PictureService.class);
Call<PictureResponse> pictureResponseCall = service.getPictureList(KEYWORD, CLIENT_ID);
pictureResponseCall.enqueue(new Callback<PictureResponse>() {
#Override
public void onResponse(Call<PictureResponse> call, Response<PictureResponse> response) {
if (response.isSuccessful()){
PictureResponse pictureResponse = response.body();
ArrayList<UnsplashPic> pictureList = pictureResponse.getResults();
recyclerViewAdapter.addPictures(pictureList);
}else{
Log.e (TAG, " onResponse " + response.errorBody());
}
}
#Override
public void onFailure(Call<PictureResponse> call, Throwable t) {
Log.e (TAG, " onFailure " + t.getMessage());
}
});
}
}
My adapter class:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private ArrayList<UnsplashPic> pictureList;
public RecyclerViewAdapter (){
pictureList = new ArrayList<>();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_view_holder, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
UnsplashPic pic = pictureList.get(i);
viewHolder.artistName.setText(pic.user.getUsername());
viewHolder.unsplash.setText("Unsplash");
}
#Override
public int getItemCount() {
return pictureList.size();
}
public void addPictures(ArrayList<UnsplashPic> pictureList) {
pictureList.addAll(pictureList);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView artistName;
private TextView unsplash;
public ViewHolder (View itemView){
super(itemView);
imageView = itemView.findViewById(R.id.imageview);
artistName = itemView.findViewById(R.id.artist_name);
unsplash = itemView.findViewById(R.id.unsplash_name);
}
}
}
item_view_holder.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/imageview"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#ababab"
android:contentDescription="unsplash picture" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Photo by "/>
<TextView
android:id="#+id/artist_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="on "/>
<TextView
android:id="#+id/unsplash_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true" />
</LinearLayout>
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Search for pictures"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerview">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Here:
public void addPictures(ArrayList<UnsplashPic> pictureList) {
pictureList.addAll(pictureList);
notifyDataSetChanged();
}
you are actually adding the content of the pictureList you send as parameter of the function to that same list, your list from adapter is not updated.
You should do like this instead:
public void addPictures(ArrayList<UnsplashPic> pictureList) {
this.pictureList.addAll(pictureList);
notifyDataSetChanged();
}

onBindViewHolder not called after RecyclerView Adapter notifyDataSetChanged()

I'm getting some data from Firebase database and I'm trying to populate RecyclerView adapter with it. After Adapter's notifyDataSetChanged() is called, screen blinks and nothing happens, I couldn't even catch a breakpoint inside onBindViewHolder.
Here is my code:
POJO class:
public class Result2 implements Serializable {
private int score;
private String userName;
public Result2(int score, String userName) {
this.score = score;
this.userName = userName;
}
public int getScore() {
return score;
}
public String getUserName() {
return userName;
}
}
This is my activitys layout called activity_results.xml that contains RecyclerView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="USERNAME"
android:textColor="#000"
android:textSize="16sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="SCORE"
android:textColor="#000"
android:textSize="16sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000"
/>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingTop="10dp"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
Here is my Adapters ViewHolder layout called score_view_holder.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/username"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="14sp"/>
<TextView
android:id="#+id/score"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="14sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:background="#4545"/>
So it will contain two horizontal TextViews and a View as a line below..
Here is my Adapter:
public class ScoreAdapter extends RecyclerView.Adapter<ScoreAdapter.ScoreViewHolder> {
private List<Result2> results = new ArrayList<>();
public void setResults(List<Result2> results) {
this.results.clear();
this.results.addAll(results);
notifyDataSetChanged();
}
#Override
public ScoreAdapter.ScoreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.score_view_holder, parent, false);
return new ScoreAdapter.ScoreViewHolder(view);
}
#Override
public void onBindViewHolder(ScoreAdapter.ScoreViewHolder holder, int position) {
Result2 result = getResult(position);
if (result != null) {
holder.setUsername(result.getUserName() != null ? result.getUserName() : "-");
holder.setScore(String.valueOf(result.getScore()));
}
}
private Result2 getResult(int position) {
return !results.isEmpty() ? results.get(position) : null;
}
#Override
public int getItemCount() {
return results.size();
}
public class ScoreViewHolder extends RecyclerView.ViewHolder {
private TextView username;
private TextView score;
public ScoreViewHolder(View itemView) {
super(itemView);
username = itemView.findViewById(R.id.username);
score = itemView.findViewById(R.id.score);
}
public void setUsername(String username) {
this.username.setText(username);
}
public void setScore(String score) {
this.score.setText(score);
}
}
}
It should get List of Result2 objects and just set text in those two TextViews (username and score)
And finally my Activity where I'm trying to notify adapter from:
public class Results extends AppCompatActivity {
private DatabaseReference mDatabase;
private ScoreAdapter scoreAdapter;
private RecyclerView recyclerView;
private List<Result2> results = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
recyclerView = findViewById(R.id.recycler_view);
scoreAdapter = new ScoreAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(scoreAdapter);
mDatabase = FirebaseDatabase.getInstance().getReference();
loadResults();
}
private void loadResults() {
mDatabase.child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
Result2 result = childSnapshot.getValue(Result2.class);
if (result != null) {
results.add(result);
}
}
Toast.makeText(Results.this, String.valueOf(results.size()), Toast.LENGTH_SHORT).show();
scoreAdapter.setResults(results);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
}
);
}
}
So after for loop is done, Toast shows correct number of results, adapter setResults method is called, there i receive correct number of results, here is a picture:
But after notifyDataSetChanged() is called, screen just blinks and everything is blank... methods inside onBindViewHolder can not be reached after putting breakpoints on them.. Any idea what's wrong here?
There are several problems in your code. The first one is that you are calling the setResults() method and pass your results list inside your ScoreAdapter class and not to the constrcutor. In order to solve this, change your setResults() method to become a constructor like this:
public ScoreAdapter(List<Result2> results) {
this.results.clear();
this.results.addAll(results);
notifyDataSetChanged();
}
The adapter must also be instantiated and set to your RecyclerView inside the callback. So to solve this, simply move the following lines of code:
ScoreAdapter scoreAdapter = new ScoreAdapter(result);
recyclerView.setAdapter(scoreAdapter);
Right after the following line:
Toast.makeText(Results.this, String.valueOf(results.size()), Toast.LENGTH_SHORT).show();
Don't also forget to comment this line of code: scoreAdapter.setResults(results);.
See now, to instantiate the adapter you need to pass the result list to the constructor.
Also please also don't forget to add the public no-argument constructor to your Result2 class. Please see here more details.

Display firebase data in custom recyclerview

I want to display the firebase data into the custom recyclerview. The data is added to the firebase from the arduino which i want to display in the app itself.
i am trying to run the following code but the app simply opens and doesnt display anything. Each time the app runs on the android, it opens and doesnt diaplay anything. The same code is working with my other 2-3 projects but doesnt seem to work in this case.
1.MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private DatabaseReference myref;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.mango);
myref = FirebaseDatabase.getInstance().getReference().child("database").child("values");
FirebaseRecyclerAdapter<valueretriever, ProgramViewHolder> recyclerAdapter = new FirebaseRecyclerAdapter<valueretriever, ProgramViewHolder>(
valueretriever.class,
R.layout.individual_row,
ProgramViewHolder.class,
myref
) {
#Override
protected void populateViewHolder(ProgramViewHolder viewHolder, valueretriever model, int position) {
viewHolder.setMoisture(model.getMoisture());
viewHolder.setMotor_time(model.getMotortime());
viewHolder.setPower(model.getPower());
}
};
recyclerView.setAdapter(recyclerAdapter);
}
public static class ProgramViewHolder extends RecyclerView.ViewHolder {
View mView;
TextView txtmoisture;
TextView txtmotor_time;
TextView txtpower;
String moisturee, motortimee, powerr;
public ProgramViewHolder(View itemView) {
super(itemView);
mView = itemView;
txtmoisture = itemView.findViewById(R.id.textview1);
txtmotor_time = itemView.findViewById(R.id.textview2);
txtpower = itemView.findViewById(R.id.textview3);
}
public void setMoisture(String moisture) {
txtmoisture.setText(moisture);
moisturee = txtmoisture.getText().toString();
}
public void setMotor_time(String motor_time) {
txtmotor_time.setText(motor_time);
motortimee = txtmotor_time.getText().toString();
}
public void setPower(String power) {
txtpower.setText(power);
powerr = txtpower.getText().toString();
}
}
}
2.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/mango"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
3.valueretriever.java
public class valueretriever {
private String moisture;
private String motor_time;
private String power;
public valueretriever() {
}
public valueretriever(String moisture, String motor_time, String power) {
this.moisture = moisture;
this.motor_time = motor_time;
this.power = power;
}
public String getMoisture() {
return moisture;
}
public void setMoisture(String moisture) {
this.moisture = moisture;
}
public String getMotortime() {
return motor_time;
}
public void setMotortime(String motor_time) {
this.motor_time = motor_time;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
}
4.individual_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#282828"
android:orientation="vertical">
<TextView
android:id="#+id/textview1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_below="#+id/textview2"
android:layout_centerHorizontal="true"
android:gravity="center_vertical"
android:textColor="#ffffff"
android:textSize="50sp" />
<TextView
android:id="#+id/textview2"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:gravity="center_vertical"
android:textColor="#ffffff"
android:textSize="50sp" />
<TextView
android:id="#+id/textview3"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:textColor="#ffffff"
android:textSize="50sp" />
</RelativeLayout>

Item not showing inside RecyclerView

I check everything in my code,I ask a question and do some of the modification,and also reading all the question about "Item not showing in RecyclerView",but the layout still not appear in my recyclerView.
This is my previous question,I attach all my code here,have 3 answer tell me,I should use LinearLayout instead of RelativeLayout as the parent of RecyclerView,so I modified the code as below
Fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/commentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/titlebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_marginTop="#dimen/feed_item_margin"
android:layout_weight="1"
android:text="Be the first to like this" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/comment_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:animateLayoutChanges="false"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:id="#+id/commentInsert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="horizontal">
<EditText
android:id="#+id/commentField"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#null"
android:ems="10"
android:hint="Add a comment" />
<Button
android:id="#+id/sendButton"
android:layout_width="77dp"
android:layout_height="wrap_content"
android:text="Send" />
</LinearLayout>
</LinearLayout>
Here is the item which should be appear in the RecyclerView.comment_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:id="#+id/commentProfilePic"
android:layout_weight="0.05"
android:layout_width="#dimen/comment_item_profile_pic"
android:layout_height="#dimen/comment_item_profile_pic"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_marginTop="#dimen/feed_item_margin"
android:scaleType="fitCenter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_marginTop="#dimen/feed_item_margin"
android:orientation="vertical"
android:layout_weight="1"
android:paddingLeft="#dimen/comment_item_profile_info_padd">
<TextView
android:id="#+id/commentUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/comment_item_status_pad_left_right"
android:paddingRight="#dimen/comment_item_status_pad_left_right"
android:textStyle="bold" />
<TextView
android:id="#+id/commentBody"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/comment_item_status_pad_left_right"
android:paddingRight="#dimen/comment_item_status_pad_left_right" />
<TextView
android:id="#+id/commentTimestamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/comment_item_status_pad_left_right"
android:paddingRight="#dimen/comment_item_status_pad_left_right"
android:paddingTop="#dimen/comment_item_timestamp_pad_top" />
</LinearLayout>
I read this issue tell that need to add this line of code adapter.notifyDataSetChanged();,I done that,this is how I notifyDataSetChanged() when I parse the JSON.
private void parseJsonFeed(JSONObject response) {
try {
JSONArray commentArray = response.getJSONArray("comment");
//get all the item in Json
for (int i = 0; i < commentArray.length(); i++) {
JSONObject commentObj = (JSONObject) commentArray.get(i);
commentId = commentObj.getInt("comment_id");
commenterUsername= commentObj.getString("commenter_username");
commentBody = commentObj.getString("comment_body");
commenterProfileImage = commentObj.getString("commenter_profile_image");
commentCreatedAt = commentObj.getString("comment_created_at");
//set all item to the Array list
setItemToCommentArrayList(commentId,commenterUsername,commenterProfileImage,commentBody,commentCreatedAt);
}
// notify data changes to list adapter
commentAdapter.notifyDataSetChanged();
}catch (JSONException e){
System.out.println("end of content");
}
}
I checked,whether is something wrong when I set my adapter to the RecycleView.So i read this answer,and here is how I set my adapter
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View dialogView = inflater.inflate(R.layout.fragment_comment, container,false);
commentRecyclerView =(RecyclerView)dialogView.findViewById(R.id.comment_recycler_view);
commentRecyclerView.setNestedScrollingEnabled(false);
//bind the recycler view with the adapter
commentAdapter = new CommentAdapter(getActivity(),commentItems);
final LinearLayoutManager myLayoutManager = new LinearLayoutManager(getActivity());
commentRecyclerView.setLayoutManager(myLayoutManager);
commentRecyclerView.setAdapter(commentAdapter);
Here is my CommentAdpater , I still didnt see any different with my another recycleview adapter.
public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.MyViewHolder>{
private Context cContext;
private List<CommentItem> commentItems;
class MyViewHolder extends RecyclerView.ViewHolder{
TextView commentBody,commentUsername,commentTimeStamp;
ImageView commentProfilePic;
//find all the view here
MyViewHolder(final View view) {
super(view);
commentProfilePic = (ImageView)view.findViewById(R.id.commentProfilePic);
commentUsername = (TextView)view.findViewById(R.id.commentUsername);
commentBody = (TextView)view.findViewById(R.id.commentBody);
commentTimeStamp = (TextView)view.findViewById(R.id.commentTimestamp);
}
}
public CommentAdapter(Context cContext, List<CommentItem> commentItems) {
this.cContext = cContext;
this.commentItems = commentItems;
}
#Override
public long getItemId(int position) {
return position;
}
//this one for make the adview inside this
#Override
public int getItemViewType(int position) {
return position;
}
//bind the comment item here
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View commentItemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.comment_item, parent, false);
return new MyViewHolder(commentItemView);
}
//do all the action here
#Override
public void onBindViewHolder(CommentAdapter.MyViewHolder holder, int position) {
final CommentItem commentItem = commentItems.get(position);
//commenter username
holder.commentUsername.setText(commentItem.getUsername());
//commenter profile image
Glide
.with(cContext)
.load(commentItem.getCommentProfilePic())
.fitCenter()
.into(holder.commentProfilePic);
//comment body
holder.commentBody.setText(commentItem.getCommentBody());
//comment timestamp
holder.commentTimeStamp.setText(commentItem.getCommentTimeStamp());
}
#Override
public int getItemCount() {
return commentItems.size();
}
}
I make sure my JSON is received in my volley Request.I log it out,is received in Volley onResponse .My JSON is look like this
"comment":[{"comment_created_at":"2017-03-21 13:03:40","comment_id":8,"comment_body":"abc","commenter_username":"abc","profile_image_path":"http:\/\/abc\/def\/v1\/ef\/defaultmale.jpg"
And this question I ask just tell me no need to worry about cause I using Glide to load my image,Glide will handle that
This is all the solution that tried,and still havent get it done,so what I still missing out here,in order the comment_xmlappear to the recyclerView inside Fragment.xml? Any guide that lead me to the right direction is well-appreciated.Thanks
UPDATE
Here is my setItemToCommentArrayList()
private void setItemToCommentArrayList(int commentId, String commenterUsername, String commenterProfileImage, String commentBody, String commentCreatedAt) {
CommentItem item = new CommentItem();
item.setCommentId(commentId);
item.setUsername(commenterUsername);
item.setCommentProfilePic(commenterProfileImage);
item.setCommentBody(commentBody);
item.setCommentTimeStamp(commentCreatedAt);
//save it to the comment array list
commentItems.add(item);
}
Here is my data model of Comment Item
public class CommentItem {
private String username,commentBody,commentTimeStamp,commentProfilePic;
private int commentId;
public CommentItem(){
}
public CommentItem(int commentId, String username,String commentBody,String commentTimeStamp,String commentProfilePic){
super();
this.commentId = commentId;
this.username = username;
this.commentBody = commentBody;
this.commentProfilePic= commentTimeStamp;
this.commentTimeStamp= commentProfilePic;
}
public int getCommentId() {
return commentId;
}
public void setCommentId(int commentId) {
this.commentId = commentId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCommentBody() {
return commentBody;
}
public void setCommentBody(String commentBody) {
this.commentBody = commentBody;
}
public String getCommentTimeStamp() {
return commentTimeStamp;
}
public void setCommentTimeStamp(String commentTimeStamp) {
this.commentTimeStamp = commentTimeStamp;
}
public String getCommentProfilePic() {
return commentProfilePic;
}
public void setCommentProfilePic(String commentProfilePic) {
this.commentProfilePic = commentProfilePic;
}
}
First of all try to print out your dataSet size into getItemCount method of recyclerview -
#Override
public int getItemCount() {
Log.e("Size of data:", "" +commentItems.size())
return commentItems.size();
}
If it returns greater than zero - there may be a problem with your row_item of recyclerview. Double check your comment_item.xml file. Possibly try to remove weights.
Are items not showing in the cards or is the recycler view itself not showing?
If the recycler view itself is not showing, maybe the problem is inside the getItemCount the size being sent is 0.
do a check there and return 1 if size is zero.
#Override
public int getItemCount() {
if(commentItems.size() == 0)
return 1;
else
return commentItems.size();
}

Categories

Resources