Not displaying in ListView from Firebase

I am able to put data into Firebase database, but when I want to retrieve it and display it to ListView, it only displays blank screen.

BaseActivity class:

public class BaseActivity extends AppCompatActivity {

    @Bean
    OttoBus bus;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bus.register(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        bus.unregister(this);
    }
}

HomeActivity class:

@OptionsMenu(R.menu.signout)
@EActivity(R.layout.activity_home)
public class HomeActivity extends BaseActivity {

    private static final int LOGIN_REQUEST_CODE = 42;

    @ViewById
    ListView listView;

    @Bean
    ConversationAdapter conversationAdapter;

    @Bean
    UserDao userDao;

    @AfterViews
    void init() {
        // if no user is logged in
        if (FirebaseAuth.getInstance().getCurrentUser() == null) {
            LoginActivity_.intent(this).startForResult(LOGIN_REQUEST_CODE);
        } else {
            userDao.init();
        }

        listView.setAdapter(conversationAdapter);
    }

    @OnActivityResult(value = LOGIN_REQUEST_CODE)
    void loginSucceeded(int resultCode) {
        if (resultCode != RESULT_OK) {
            return;
        }
        userDao.init();
        conversationAdapter.resetConversationFlow();
    }

    @Subscribe
    public void usersLoaded(UsersLoadedEvent event) {
        final FirebaseUser firebaseUser = FirebaseAuth
                .getInstance().getCurrentUser();
        if (userDao.userExists(firebaseUser.getUid())) {
            userDao.setCurrentUser(userDao.getUserById(firebaseUser.getUid()));
        } else {
            final User user = new User(firebaseUser.getUid(),
                    firebaseUser.getDisplayName(),
                    firebaseUser.getPhotoUrl().toString());
            userDao.write(user);
            userDao.setCurrentUser(user);
        }
    }

    @ItemClick
    void listViewItemClicked(Conversation conversation) {
        ConversationActivity_.intent(this)
                .conversation(conversation)
                .start();
    }

    /**
     * When option item with id signOut is clicked.
     */
    @OptionsItem
    void signOut() {
        FirebaseAuth.getInstance().signOut();

        // restart this activity after user is logged out because if there is no user we will start
        // login activity
        final Intent intent = getIntent();
        finish();
        startActivity(intent);
    }

    /**
     * Called when button with id=fab is clicked.
     */
    @Click
    void fab() {
        CreateConversationActivity_.intent(this).start();
    }
}

activity_home.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.nemus.execomchatworkshop.activity.HomeActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_margin="@dimen/large_margin"
        android:src="@drawable/ic_add_black_24dp" />

</RelativeLayout>

ConversationItemView class:

@EViewGroup(R.layout.item_view_conversation)
public class ConversationItemView extends LinearLayout {

    @ViewById
    TextView title;

    public ConversationItemView(Context context) {
        super(context);
    }

    public void bind(Conversation conversation) {
        title.setText(conversation.getTitle());
    }
}

item_view_conversation.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="wrap_content"
    android:background="?android:attr/selectableItemBackground">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/conversationPhoto"
            android:layout_width="@dimen/image_large_size"
            android:layout_height="@dimen/image_large_size"
            android:layout_margin="@dimen/medium_margin" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/large_margin"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:textColor="@color/primary_text"
                android:textSize="@dimen/large_text" />

            <TextView
                android:id="@+id/conversationPreview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:textColor="@color/secondary_text"
                android:textSize="@dimen/medium_text" />

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>

ConversationDao class

@EBean(scope = EBean.Scope.Singleton)
public class ConversationDao {

    static final String CONVERSATION_TAG = "conversations";

    private FirebaseDatabase database = FirebaseDatabase.getInstance();

    private List<Conversation> conversations = new ArrayList<>();

    private Map<String, Conversation> conversationMap = new HashMap<>();

    @Bean
    OttoBus bus;

    /**
     * After this class is injected call this method.
     */
    @AfterInject
    public void init() {
        database.getReference(CONVERSATION_TAG).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                conversationMap = dataSnapshot.getValue(
                        new GenericTypeIndicator<Map<String, Conversation>>() {
                        });
                publish();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

    public void write(Conversation conversation) {
        final DatabaseReference databaseReference =
                database.getReference(CONVERSATION_TAG).push();

        conversation.setId(databaseReference.getKey());     // set unique key to our conversation
        databaseReference.setValue(conversation);           // push conversation to database
    }

    public List<Conversation> getConversations() {
        return conversations;
    }

    private void publish() {
        conversations.clear();
        if (conversationMap != null) {
            conversations.addAll(conversationMap.values());
        }

        // post to event bus
        bus.post(new ConversationsUpdateEvent());
    }

ConversationAdapter class:

@EBean
public class ConversationAdapter extends BaseAdapter {

    private List<Conversation> conversations = new ArrayList<>();

    @RootContext
    Context context;

    @Bean
    ConversationDao conversationDao;

    @Bean
    OttoBus bus;

    /**
     * This method is called after this class is injected.
     */
    @AfterInject
    void init() {
        bus.register(this);
    }

    public void resetConversationFlow() {
        conversationDao.init();
    }

    @Override
    public int getCount() {
        return conversations.size();
    }

    @Override
    public Conversation getItem(int position) {
        return conversations.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ConversationItemView conversationItemView;

        if (convertView == null) {  // if view item is not created
            conversationItemView = ConversationItemView_.build(context);
        } else {    // if view item was already created
            conversationItemView = (ConversationItemView) convertView;
        }

        // bind data to view
        conversationItemView.bind(getItem(position));

        return conversationItemView;
    }

    private void setConversations(List<Conversation> conversations) {
        this.conversations = conversations;

        // notify that data set changed so that the list is refreshed
        notifyDataSetChanged();
    }

    @Subscribe
    public void conversationsUpdated(ConversationsUpdateEvent event) {
        setConversations(conversationDao.getConversations());
    }
}

So, what am I missing here. Why is not displaying conversation title into ListView?

1 answer

  • answered 2017-06-17 18:24 Mohamed Yassin

    It's difficult to follow allow with all this code at once. You are more likely to get answers if you ask one small question, than one large one. This is what I would recommend for you to figure out how to solve this issue:

    1. Get familiar with the Debugger. It is essential and once you learn it you will become much better at solving any issues and coding in general.

    Setup breakpoints to stop after you've successfully retrieved your data. Then confirm that you actually received the data and it is currently stored in the variable you wish to use.

    1. Now that you've confirmed that your data exists, make sure you're setting up the list view correctly.

      Firstly, I would recommend you start out with RecylerView, as that is the much newer standard and has much more helpful tutorials online. They are fundamently the same thing but RecylerView is better. Then I would continue to use the debugger to check that my data is being passed in to the RecylerViewAdapter correctly, and that when the data is bounded, it is pointing it to the correct views.

    Here is a good tutorial for using the Android studio debugger.

    Here is a good tutorial by google for adding lists(Using recylerview)