I'm trying to retrieve data to a RecyclerView
from Firebase. But I am experiencing a NullPointerException
. I have input the necessary children to be able to retrieve the data but I am not able to. What could be wrong? Below is my code...
ChatActivity
package com.dreamlazerstudios.gtuconline;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ServerValue;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChatActivity extends AppCompatActivity {
private DatabaseReference rootRef, messagesRef;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private String userID;
private String mChatUser;
private ImageButton chat_add_btn, chat_send_btn;
private EditText enter_message;
List<DataSnapshot> listData;
RecyclerView recyclerView;
ChatActivity.MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recyclerView = findViewById(R.id.messages_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
messagesRef = FirebaseDatabase.getInstance().getReference();
listData = new ArrayList<>();
adapter = new ChatActivity.MyAdapter(listData);
adapter.setHasStableIds(true);
chat_add_btn = findViewById(R.id.chat_add_btn);
chat_send_btn = findViewById(R.id.chat_send_btn);
enter_message = findViewById(R.id.chat_message_view);
loadMessages();
rootRef = FirebaseDatabase.getInstance().getReference();
mAuth = FirebaseAuth.getInstance();
final FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
mChatUser = getIntent().getStringExtra("user_id");
String username = getIntent().getStringExtra("user_name");
setTitle(username);
rootRef.child("Chat").child(userID).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.hasChild(mChatUser)) {
Map chatAddMap = new HashMap();
chatAddMap.put("seen", false);
chatAddMap.put("timestamp", ServerValue.TIMESTAMP);
Map chatUserMap = new HashMap();
chatUserMap.put("Chat/" + userID + "/" + mChatUser, chatAddMap);
chatUserMap.put("Chat/" + mChatUser + "/" + userID, chatAddMap);
rootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("CHAT_LOG", databaseError.getMessage().toString());
}
}
});
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
chat_send_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendMessage();
}
});
}
private void loadMessages() {
messagesRef = FirebaseDatabase.getInstance().getReference().child("gtuconline").child("messages").child(userID).child(mChatUser);
messagesRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Messages messages = dataSnapshot.getValue(Messages.class);
listData.add(dataSnapshot);
recyclerView.setAdapter(adapter);
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void sendMessage() {
String message = enter_message.getText().toString();
if (!TextUtils.isEmpty(message)) {
String current_user_ref = "messages/" + userID + "/" + mChatUser;
String chat_user_ref = "messages/" + mChatUser + "/" + userID;
DatabaseReference user_message_push = rootRef.child("messages").child(userID).child(mChatUser).push();
String push_id = user_message_push.getKey();
Map messageMap = new HashMap();
messageMap.put("message", message);
messageMap.put("seen", false);
messageMap.put("type", "text");
messageMap.put("time", ServerValue.TIMESTAMP);
Map messageUserMap = new HashMap();
messageUserMap.put(current_user_ref + "/" + push_id, messageMap);
messageUserMap.put(chat_user_ref + "/" + push_id, messageMap);
enter_message.setText("");
rootRef.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("CHAT_LOG", databaseError.getMessage());
}
}
});
}
}
public class MyAdapter extends RecyclerView.Adapter<ChatActivity.MyAdapter.ViewHolder> {
List<DataSnapshot> list;
public MyAdapter(List<DataSnapshot> List) {
this.list = List;
}
@Override
public void onBindViewHolder(@NonNull final ChatActivity.MyAdapter.ViewHolder holder, final int position) {
final DataSnapshot studentSnapshot = list.get(position);
final Messages students = studentSnapshot.getValue(Messages.class);
assert students != null;
holder.messageText.setText(students.getMessage());
}
@NonNull
@Override
public ChatActivity.MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_single_layout, parent, false);
return new ChatActivity.MyAdapter.ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText, userName;
public ViewHolder(View itemView) {
super(itemView);
messageText = itemView.findViewById(R.id.user_single_message);
timeText = itemView.findViewById(R.id.user_single_time);
userName = itemView.findViewById(R.id.user_single_name);
}
}
@Override
public int getItemCount() {
return list.size();
}
}
}
My Model Class
package com.dreamlazerstudios.gtuconline;
/**
* Created by Gabriel Hagan on 23/05/2018 at 17:18.
*/
public class Messages {
private String message, type;
private long time;
private boolean seen;
public Messages(String message, String type, long time, boolean seen) {
this.message = message;
this.type = type;
this.time = time;
this.seen = seen;
}
public Messages() {
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public boolean isSeen() {
return seen;
}
public void setSeen(boolean seen) {
this.seen = seen;
}
}
My xml layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".ChatActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/messages_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/text_layout">
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:id="@+id/text_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:weightSum="100">
<ImageButton
android:id="@+id/chat_add_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="20"
android:background="@color/white"
android:contentDescription="@string/image"
android:src="@drawable/ic_add_black_24dp" />
<EditText
android:id="@+id/chat_message_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="60"
android:background="@color/white"
android:ems="10"
android:hint="Send a message"
android:inputType="none"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:paddingTop="5dp"
android:textSize="17sp" />
<ImageButton
android:id="@+id/chat_send_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="20"
android:background="@color/white"
android:contentDescription="@string/send"
android:src="@drawable/ic_send_black_24dp" />
</LinearLayout>
</RelativeLayout>
Layout for the recyclerview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:weightSum="1"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="5dp"
android:padding="2dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:textStyle="bold"
android:id="@+id/user_single_name"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:text="@string/full_name"
android:textColor="@android:color/background_dark"
android:textSize="16sp"/>
<TextView
android:id="@+id/user_single_time"
android:layout_width="60dp"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:text="00:00"
android:textColor="@android:color/background_dark"
android:layout_marginStart="10dp"/>
</LinearLayout>
<TextView
android:id="@+id/user_single_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginStart="10dp"
android:text="Message Text"
android:textSize="12sp" />
<View
android:id="@+id/first_view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5dp"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:background="@color/lightgrey" />
</LinearLayout>
</LinearLayout>
I honestly don't know what could be the problem. Maybe someone has eagle eyes to identify the error and help me solve it.
Stack trace of the problem is as follows.
05-24 07:51:43.697 19173-19173/com.dreamlazerstudios.gtuconline E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dreamlazerstudios.gtuconline, PID: 19173
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dreamlazerstudios.gtuconline/com.dreamlazerstudios.gtuconline.ChatActivity}: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2984)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at com.google.firebase.database.DatabaseReference.child(Unknown Source)
at com.dreamlazerstudios.gtuconline.ChatActivity.loadMessages(ChatActivity.java:121)
at com.dreamlazerstudios.gtuconline.ChatActivity.onCreate(ChatActivity.java:67)
at android.app.Activity.performCreate(Activity.java:6956)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
This is the previous activity I am getting the string extra from
package com.dreamlazerstudios.gtuconline;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import de.hdodenhof.circleimageview.CircleImageView;
import static android.content.ContentValues.TAG;
public class StudentsList extends AppCompatActivity {
DatabaseReference databaseReference;
ProgressDialog progressDialog;
List<DataSnapshot> listData;
RecyclerView recyclerView;
StudentsList.MyAdapter adapter;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private FirebaseDatabase mFirebaseDatabase;
private String userID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_students_list);
setTitle("List of Students");
recyclerView = findViewById(R.id.students_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
listData = new ArrayList<>();
adapter = new StudentsList.MyAdapter(listData);
adapter.setHasStableIds(true);
GetDataFirebase();
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading Data...");
progressDialog.show();
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
final FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
}
void GetDataFirebase() {
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child("Students");
databaseReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Students students = dataSnapshot.getValue(Students.class);
listData.add(dataSnapshot);
recyclerView.setAdapter(adapter);
progressDialog.dismiss();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
public class MyAdapter extends RecyclerView.Adapter<StudentsList.MyAdapter.ViewHolder> {
List<DataSnapshot> list;
public MyAdapter(List<DataSnapshot> List) {
this.list = List;
}
@Override
public void onBindViewHolder(final StudentsList.MyAdapter.ViewHolder holder, final int position) {
final DataSnapshot studentSnapshot = list.get(position);
final Students students = studentSnapshot.getValue(Students.class);
final String list_user_id = studentSnapshot.getKey();
holder.news_topic.setText(students.getName());
holder.news_body.setText(students.getProgramme());
if (students.getOnline() == true) {
holder.online.setVisibility(View.VISIBLE);
} else {
holder.online.setVisibility(View.INVISIBLE);
}
Picasso.with(holder.news_image.getContext()).load(students.getThumb_image()).placeholder(R.drawable.student_icon_17870).into(holder.news_image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent chat_intent = new Intent(StudentsList.this, ChatActivity.class);
chat_intent.putExtra("user_id", list_user_id);
chat_intent.putExtra("user_name", students.getName());
startActivity(chat_intent);
}
});
}
@NonNull
@Override
public StudentsList.MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.users_list_layout, parent, false);
return new StudentsList.MyAdapter.ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView news_topic, news_body;
CircleImageView news_image;
ImageView online;
public ViewHolder(View itemView) {
super(itemView);
news_topic = itemView.findViewById(R.id.user_single_name);
news_body = itemView.findViewById(R.id.user_single_status);
news_image = itemView.findViewById(R.id.user_single_image);
online = itemView.findViewById(R.id.online_status_icon);
}
}
@Override
public int getItemCount() {
return list.size();
}
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
}