Recylerview not visible in Android App - android

I have created a recyclerView in one of the fragments of my activity. And I am binding it to a dataset. I have set both the LinearLayoutManager and RecyclerView Adapter. My dataset is also getting created correctly and so is my Viewholder. There are no compilation warnings, no exceptions in my Logcat. I have checked the XML layouts for both fragment and the individual item and both are having all items set to Visible.
Yet my recyclerView is not showing in the fragment.
What are the common oversights resulting in recyclerView not being visible. Appreciate any guidance I can get on the matter.
Relevant Method initialising my recylerView is below:
private void loadMyPlacardView(View view){
List<Post> postList = new ArrayList<>();
RecyclerView placardsRecyclerView = view.findViewById(R.id.fp_placards_recyclerView);
LinearLayoutManager postsLayoutManager = new LinearLayoutManager(view.getContext());
placardsRecyclerView.setHasFixedSize(true);
placardsRecyclerView.setLayoutManager(postsLayoutManager);
DataSnapshot dataSnapshot = FirebaseStorageUtils.postDataSnapshot;
for (DataSnapshot singleSnapShot: dataSnapshot.getChildren()) {
Post thisPost = singleSnapShot.getValue(Post.class);
postList.add(thisPost);
}
PlacardsRecyclerViewAdapter placardsRecyclerViewAdapter = new PlacardsRecyclerViewAdapter(postList);
placardsRecyclerView.setAdapter(placardsRecyclerViewAdapter);
}
Code for the RecyclerviewAdapter is here
public class PlacardsRecyclerViewAdapter
extends RecyclerView.Adapter<PlacardHolder> {
private static final String TAG = "PlacardsViewAdapter";
private List<Post> listofPosts;
public PlacardsRecyclerViewAdapter(List <Post> list) {
listofPosts = list;
}
#Override
public PlacardHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.placard_item, parent, false);
return new PlacardHolder(view);
}
#Override
public void onBindViewHolder(PlacardHolder placard, int position) {
Post currentPost = listofPosts.get(position);
String username = currentPost.getUserName();
placard.userName.setText(username);
}
#Override
public int getItemCount() {
return listofPosts.size();
}
}
Code for Recyclerviewholder as class PlacardHolder.java is below
public class PlacardHolder extends RecyclerView.ViewHolder {
private static final String TAG = "PlacardsHolder";
public TextView userName;
public PlacardHolder(View view){
super(view);
this.userName = view.findViewById(R.id.pi_profile_name);
}
}
XML for the Placard Item is placard_item.xml below
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/pi_profile_name"
android:text="#string/default_username"
android:textAlignment="center"
android:textSize="25sp"
android:textStyle="bold"
android:layout_weight="7"/></android.support.constraint.ConstraintLayout>
and code for fragment_placard.xml is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="testing recyclerview"/>
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fp_placards_recyclerView"
android:scrollbars="vertical"
android:visibility="visible"
android:layout_margin="10dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
The textview from the fragment_placard.xml is loading fine but not the recyclerview.

Okay! It is about Firebase. You are not notifying your adapter after adding data to dataset. Do
if(placardsRecyclerViewAdapter != null)
placardsRecyclerViewAdapter.notifyDataSetChanged();
after adding data to postList.
Updated
Full structure:
private ValueEventListener postListener = null;
private void loadMyPlacardView(View view) {
List<Post> postList = new ArrayList<>();
RecyclerView placardsRecyclerView = view.findViewById(R.id.fp_placards_recyclerView);
LinearLayoutManager postsLayoutManager = new LinearLayoutManager(view.getContext());
placardsRecyclerView.setHasFixedSize(true);
placardsRecyclerView.setLayoutManager(postsLayoutManager);
PlacardsRecyclerViewAdapter placardsRecyclerViewAdapter = new PlacardsRecyclerViewAdapter(postList);
placardsRecyclerView.setAdapter(placardsRecyclerViewAdapter);
//Fetching data from Firebase
postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChildren()) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Post thisPost = ds.getValue(Post.class);
postList.add(thisPost);
}
if(placardsRecyclerViewAdapter != null)
placardsRecyclerViewAdapter.notifyDataSetChanged(); //Now postList has data so notify adapter.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.e("DB error", "loadPost:onCancelled", databaseError.toException());
}
};
databaseReference.addListenerForSingleValueEvent(valueEventListener);
}

I found the answer to my question. there were 2 bugs. First problem was in the placard_item.xml where I had declared the Constraintview as follows:
android:layout_height ="match parent"
because of this the layout was taking up the entire space in the screen. The second bug was that I had defined the TextView as below
android:layout_width = "0dp"
This was causing the TextView to disappear inside the recyclerview at run-time, although it was showing perfectly well in the "Design" view of my xml in AndroidStudio IDE. I am posting answer here in case someone else faces same issues. "ConstraintView" in general is proving hard to handle while working with Recyclerview. So going back to the simpler LinearLayout.

Related

Refreshing items as the user scrolls down in SwipeRefreshLayout

I have a SwipeRefreshLayout on my RecyclerView, I want the items to refresh as the user scrolls down instead of just pulling down from the top every time. I need something like Instagram or facebook that the posts load as the user is scrolling down. So that the user doesn't have to keep coming up again and again to refresh and load more posts
Here is my XML code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bar">
</com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/bar">
<androidx.core.widget.NestedScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/bar">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/bar"
android:id="#+id/recycler_view_posts"/>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</RelativeLayout>
Here is my fragment code:
public class HomeFragment extends Fragment {
//POSTS
private RecyclerView recyclerViewPosts;
private PostAdapter postAdapter;
private List<Post> postLists;
private List<String> followingList;
private Context mContext;
private static final int TOTAL_NUMBER_OF_ITEMS_TO_LOAD = 5;
private SwipeRefreshLayout swipeRefreshLayout;
private int currentPage = 1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
//POSTS
recyclerViewPosts = view.findViewById(R.id.recycler_view_posts);
recyclerViewPosts.setHasFixedSize(true);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerViewPosts.setLayoutManager(linearLayoutManager);
postLists = new ArrayList<>();
postAdapter = new PostAdapter(getContext(), postLists);
recyclerViewPosts.setAdapter(postAdapter);
swipeRefreshLayout = view.findViewById(R.id.swiperefresh);
checkFollowing();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
#Override
public void onRefresh() {
currentPage++;
postLists.clear();
readPosts();
}
});
return view;
}
private void readPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
Query postQuery = reference.limitToLast(currentPage * TOTAL_NUMBER_OF_ITEMS_TO_LOAD);
postQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
postLists.add(post);
}
postAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
I would recommend you to use the Paging Library from Android. It is design for it and you have a nice tutorial for it here. It might be a bit of work but it is worth it.

E/RecyclerView: No adapter attached; skipping layout. No data is displayed [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to fetch data from firebase and put it into a recycler view through adapter. But, no data is being displayed.
My code in Main Activity:
DatabaseReference databaseReference;
RecyclerView recyclerView;
ArrayList<Menu> menuList;
EditMenuAdapter editMenuAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_menu);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
menuList = new ArrayList<Menu>();
databaseReference = FirebaseDatabase.getInstance().getReference().child("menu");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Menu menu = dataSnapshot1.getValue(Menu.class);
menuList.add(menu);
}
editMenuAdapter = new EditMenuAdapter(EditMenuActivity.this, menuList);
recyclerView.setAdapter(editMenuAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(EditMenuActivity.this, "Something went wrong", Toast.LENGTH_LONG).show();
}
});
My adapter class:
public class EditMenuAdapter extends RecyclerView.Adapter<EditMenuAdapter.MyViewHolder> {
Context context;
ArrayList<Menu> menuArrayList;
public EditMenuAdapter(Context c, ArrayList<Menu> menus) {
context = c;
menuArrayList = menus;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.menu_list_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.dishNameTextView.setText(menuArrayList.get(position).getDishName());
holder.dishPriceTextView.setText(menuArrayList.get(position).getDishPrice());
}
#Override
public int getItemCount() {
return menuArrayList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView dishNameTextView;
TextView dishPriceTextView;
Switch dishActiveSwitch;
public MyViewHolder(View view) {
super(view);
dishNameTextView = (TextView) view.findViewById(R.id.dishNameTextView);
dishPriceTextView = (TextView) view.findViewById(R.id.dishPriceTextView);
dishActiveSwitch = (Switch) view.findViewById(R.id.dishActiveSwitch);
}
}
}
The layout resource file is:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".EditMenuActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="397dp"
android:layout_height="599dp"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/doneButton"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:text="Done"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView" />
The log shows: E/RecyclerView: No adapter attached; skipping layout. No data is displayed.
Only the switch is being displayed on the screen. Please help!
Create instance of adapter in onCreate and attach it to RV:
protected void onCreate(Bundle savedInstanceState) {
...
editMenuAdapter = new EditMenuAdapter(this, new ArrayList<>());
recyclerView.setAdapter(adapter);
...
}
In the response of Firebase onDataChange:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
...
editMenuAdapter.setItems(menuList);
runOnUiThread(() -> editMenuAdapter.notifyDataSetChanged());
}

print all users list in android app using firebase

I am working on printing all users based on the UID, but I only get one user printed.
This is the result I am getting now.
Here is what the printingUserList(), this is a small function to retrieve all user information based on UID.
RecyclerView rv;
UserAdapter usrAdapter;
ArrayList<User> mUsrsList;
private void readUsrs(){
LinearLayoutManager LayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(LayoutManager);
mUsrsList = new ArrayList<>();
final FirebaseUser me = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUsrsList.clear();
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Log.d("TAG_", "A++" + dataSnapshot.getChildrenCount()); //prints 5, which exactly has five users in the database.
User all_usr = ds.getValue(User.class);
if (!all_usr.getUid().equals(me.getUid())) { //won't print itself
mUsrsList.add(all_usr);
}
}
System.out.println(mUsrsList.toString());
usrAdapter = new UserAdapter(RoomUser_Activity.this, mUsrsList);
rv.setAdapter(usrAdapter);
usrAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
}
and this is the recyclerview, should be correct otherwise it prints nothing
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private Context m_context;
private ArrayList<User> all_users;
public static final String EXTRA_HISUID = "NoHisUID";
public UserAdapter(Context context, ArrayList<User> all_users) {
this.m_context = context;
this.all_users = all_users;
}
#NonNull
#Override
public UserAdapter.UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(m_context);
View itemv = inflater.inflate(R.layout.layout_item_user, parent, false); //xml provide below
return new UserViewHolder(itemv);
}
public class UserViewHolder extends RecyclerView.ViewHolder{
public ImageView UserIcon; //default icon provided in xml
public TextView Username;
public UserViewHolder (View itemView){
super(itemView);
UserIcon = (ImageView)itemView.findViewById(R.id.usr_icon);
Username = (TextView)itemView.findViewById(R.id.tv_username);
}
}
public void onBindViewHolder(#NonNull UserAdapter.UserViewHolder holder, int position) {
User usr = all_users.get(position);
final String hisUID = usr.getUid();
holder.Username.setText(usr.getUsername());
if(usr.getIcon().equals("default_icon")){
holder.UserIcon.setImageResource(R.drawable.default_icon);
}
else{
Glide.with(m_context).load(usr.getIcon()).into(holder.UserIcon);
}
}
public int getItemCount() {
return all_users.size();
}
layout_item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="match_parent">
<ImageView
android:id="#+id/usr_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
android:layout_toEndOf="#+id/usr_icon"
android:layout_toRightOf="#+id/usr_icon"
android:text="username"
android:textSize="18sp" />
<TextView
android:id="#+id/lastMessageTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="The last message"
android:layout_marginStart="4dp"
android:maxLines="2"
android:layout_marginTop="3dp"
android:layout_toRightOf="#id/usr_icon"
android:layout_below="#id/tv_username"
android:layout_marginLeft="13dp" />
</RelativeLayout>
database:
users:
|-2NUPkQuHFRS49ZHDZzEtWiErIiv1
|-address: "920 West 4th Ave apt231"
|-city: "blank"
|-donut: 0
|-email: "not_busy#gmail.com"
|-full_name: "blank"
|-icon: "default_icon"
|-phone: "253353309"
|-state: "blank"
|-uid: "2NUPkQuHFRS49ZHDZzEtWiErIiv1"
|-username: "not_busy"
|-F0NRthr8uJPYMz2o129w2PAf30i1
|-GRJPA5hKA6aRgNl68sSxv3xruww1
|-W0PIUjUwRHXTkooztYFuhKuLItE3
|-cBzUNHceM2T47cr0zWX1tqgB2wA3
It must be a small bug, but I still cannot figure what problem is.. thank you in advance.

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.

Add a row to an empty recyclerview on execution time

I have an activity with an AutoCompleteTextView and a button, and below it, a hidden RecyclerView, that starts empty (with no rows).
With the AutoCompleteTextView, I select an object and what I want is, when I click the button, to add that object to the RecyclerView(and turn the visibility on for the recycler).
So far, I've managed to add the object to the recycler's DataSet, but it won't show any row on notifyDataSetChanged().
The layout:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:id="#+id/ib_add"
android:src="#drawable/ic_add_black"
android:onClick="onAddClick"/>
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/actv_input"
android:layout_toLeftOf="#+id/ib_add"
android:layout_toStartOf="#+id/ib_add"
android:hint="#string/name_hint"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
The Activity (just the relevant functions):
#Bind(R.id.rv) RecyclerView rv;
ArrayList<Ing> ings = new ArrayList<>();
ArrayList<Ing> selectedIngs = new ArrayList<>();
private void setupRecyclers() {
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(new RecyclerViewAdapter(selectedIngs));
}
public void onAddClick(View view) {
Ing ing = ings.get(selectedPosition);
rv.setVisibility(View.VISIBLE);
selectedIngs.add(ing);
((RecyclerViewAdapter)rv.getAdapter()).addIng(ing);
}
The RecyclerViewAdapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RViewHolder> {
ArrayList<Ing> ings;
public RecyclerViewAdapter(ArrayList<Ing> ings) {
this.ings = ings;
}
#Override
public RViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_ing, parent, false);
return new RViewHolder(row);
}
#Override
public void onBindViewHolder(RViewHolder holder, int position) {
Ing ing = ings.get(position);
holder.bindToView(ing);
}
#Override
public int getItemCount() {
return ings.size();
}
public void addIng(Ing ing) {
ings.add(ing);
notifyDataSetChanged();
}
public void setDataSet(ArrayList<Ing> ings) {
this.ings = ings;
notifyDataSetChanged();
}
}
The RecyclerViewHolder:
public class RViewHolder extends RecyclerView.ViewHolder {
Ing ing;
ImageView ivIcon;
TextView tvName;
ImageButton ibRemove;
TextView tvPercentage;
EditText etPercentage;
public RViewHolder(View row) {
super(row);
bindFields(row);
}
private void bindFields(View view) {
ivIcon = (ImageView) view.findViewById(R.id.iv_icon_type);
tvName = (TextView) view.findViewById(R.id.tv_ing);
ibRemove = (ImageButton) view.findViewById(R.id.btn_remove);
tvPercentage = (TextView) view.findViewById(R.id.tv_percentage);
etPercentage = (EditText) view.findViewById(R.id.et_percentage);
}
public void bindToView(Ing ing){
this.ing = ing;
tvName.setText(ing.getName());
ivIcon.setImageResource(R.drawable.icon);
tvName.setVisibility(View.VISIBLE);
ivIcon.setVisibility(View.VISIBLE);
ibRemove.setVisibility(View.VISIBLE);
tvPercentage.setVisibility(View.VISIBLE);
etPercentage.setVisibility(View.VISIBLE);
}
}
What am I missing?
Thanks!
Solved!
The first part, the recycler not showing even with an element inside, was fixed by the 23.2.0 support library's update, that introduced auto measurement for recyclerviews. Before that, if you had a recycler within a relative within a nested, it did some funny business and never initialized the rows inside the recycler.
The second part, the button not adding the row, was because even if you have some onclick event set in your image button, it looks that you have to put android:clickable = true or else it won't work.

Categories

Resources