0

Help, SomeBody Help Me..

Here is the database Structure

enter image description here

and Here is my MainActivity onCreate method

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    activity_main = (RelativeLayout) findViewById(R.id.activity_main);
    input = (EditText)findViewById(R.id.inputmessage);
    fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(this);

    mAuth = FirebaseAuth.getInstance();
    if(mAuth.getCurrentUser() != null)
    {
        Toast.makeText(MainActivity.this, "Welcome "+mAuth.getCurrentUser().getEmail(), Toast.LENGTH_SHORT).show();
    }
    else{
        finish();
        Intent intent = new Intent(MainActivity.this, Sign_in_form.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    }
    chatlist = new ArrayList<>();
    listofMsg = (ListView) findViewById(R.id.list_of_messange);
    databaseChat = FirebaseDatabase.getInstance().getReference("chatyoutubemajta");
    databaseChat.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
           // Toast.makeText(MainActivity.this, "onChildAdded:" + dataSnapshot.getKey(), Toast.LENGTH_SHORT).show();
            String id = dataSnapshot.getKey();
            ChatMsg chatmsg = dataSnapshot.child(id).getValue(ChatMsg.class);

            chatlist.add(chatmsg);

            DaftarChat adapter = new DaftarChat(MainActivity.this,chatlist);
            listofMsg.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) {

        }
    });

}

Here is Daftarchat class:

public class DaftarChat extends ArrayAdapter<ChatMsg> {
private Activity context;
private List<ChatMsg> daftarchat;

public DaftarChat(Activity context,List<ChatMsg> daftarchat){
    super(context,R.layout.list_item,daftarchat);
    this.context = context;
    this.daftarchat = daftarchat;
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    View listViewItem = inflater.inflate(R.layout.list_item,null,true);


    TextView txttext = (TextView)listViewItem.findViewById(R.id.message_text);
    TextView txtuser = (TextView)listViewItem.findViewById(R.id.message_user);
    TextView txttime = (TextView)listViewItem.findViewById(R.id.message_time);

    ChatMsg sampel = daftarchat.get(position);
    txttext.setText(sampel.getMsgText());
    txtuser.setText(sampel.getMsgUser());
    txttime.setText(sampel.getMsgTime());

    return listViewItem;

}

}

The problem is it keeps crashing whenever it starts:

when i remove this statement (inside DaftarChat class) :

txttext.setText(sampel.getMsgText());
    txtuser.setText(sampel.getMsgUser());
    txttime.setText(sampel.getMsgTime());

it shows nothing, but the program can run, but i still cant retrieve the data.

logcat below:

FATAL EXCEPTION: main
                                                                           Process: com.example.chatapplication, PID: 4384
                                                                           java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.chatapplication.ChatMsg.getMsgText()' on a null object reference
                                                                               at com.example.chatapplication.DaftarChat.getView

Please Help, I cant figure it out..

Thanks

Helwa

KENdi
  • 7,576
  • 2
  • 16
  • 31
Helwa
  • 1
  • 4
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Vladyslav Matviienko Mar 02 '18 at 08:30

4 Answers4

0

ChatMsg.getMsgText()' on a null object reference

sampel.getMsgText() is null. add some null checks to prevent app from crashing like:

txttext.setText(sampel.getMsgText()!=null?sampel.getMsgText():INSERT_DEFAULT_VALUE_HERE);
John
  • 3
  • 6
  • I suggest follow @Dimitar Dihanov enhancement. And as for null problem I think you have a problem here: String id = dataSnapshot.getKey(); ChatMsg chatmsg = dataSnapshot.child(id).getValue(ChatMsg.class); try debugging chatmsg first – John Mar 02 '18 at 08:51
0

Alright so there might be some problems:

Set the adapter only once in onCreate:

DaftarChat adapter = new DaftarChat(MainActivity.this, new ArrayList<>());
listofMsg.setAdapter(adapter);

And in the onChildAdded method:

@Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
           // Toast.makeText(MainActivity.this, "onChildAdded:" + dataSnapshot.getKey(), Toast.LENGTH_SHORT).show();
            String id = dataSnapshot.getKey();
            for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
                ChatMsg msg = dataSnapshot.child(id).getValue(ChatMsg.class);
                if(msg != null){
                  listOfMsg.getAdapter().addMsg(chatmsg);
                }
             }
        }

And then in the Adapter class add this method:

public void addMsg(ChatMsg chatmsg){
this.daftarchat.add(chatmsg);
notifyDataSetChanged();
}

And also modify your getView method:

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    View listViewItem = inflater.inflate(R.layout.list_item,null,true);


    TextView txttext = (TextView)listViewItem.findViewById(R.id.message_text);
    TextView txtuser = (TextView)listViewItem.findViewById(R.id.message_user);
    TextView txttime = (TextView)listViewItem.findViewById(R.id.message_time);


    ChatMsg sampel = daftarchat.get(position);
    if(sampel != null){
      txttext.setText(sampel.getMsgText());
      txtuser.setText(sampel.getMsgUser());
      txttime.setText(sampel.getMsgTime());
    }
    return listViewItem;
}
jazz
  • 29
  • 4
  • Hi, i tried your code, sampel is null is the problem, but still i dont know how to solve it – Helwa Mar 02 '18 at 08:38
  • this code also return null ChatMsg chatmsg = dataSnapshot.child(id).getValue(ChatMsg.class); – Helwa Mar 02 '18 at 08:43
  • Okay I think that in this case this: String id = dataSnapshot.getKey(); ChatMsg chatmsg = dataSnapshot.child(id).getValue(ChatMsg.class); is returning null. So since this method is a callback, the child might not have been added yet when you try to see it, or the .getValue method is wrong somehow. – jazz Mar 02 '18 at 08:44
  • Yess.. I think so, I am still checking in google... if you have any idea, please tell me example of the code, so i can try it.. – Helwa Mar 02 '18 at 08:53
  • Can you debug and see if FirebaseAuth.getInstance() returns null or not? – jazz Mar 02 '18 at 08:55
  • I can get the dataSnapshot.getKey() when I Toast it, so .getValue method probably is the mistake.. – Helwa Mar 02 '18 at 08:57
  • I found this answer for you: https://stackoverflow.com/a/44811640/9429555 Try iterating over the values. I will edit my answer to how it must look. – jazz Mar 02 '18 at 09:04
  • I Have tried that, it should use onDataChange instead of onChildAdded. when I use onDataChange, all data will be downloaded, in my case i need only the added child to be downloaded.. Any other idea??? – Helwa Mar 02 '18 at 09:07
  • Hmm in this case when you iterate in the for each you need to add a check to see if the List in the adapter contains the item, and if it doesn't then add it. I honestly don't see a workaround. If that doesn't work just use onDataChange – jazz Mar 02 '18 at 09:11
  • Ok Then, I will search on google first, if no other way, then I will use onDataChange.. onDatachange will work 100%.. – Helwa Mar 02 '18 at 09:31
0

Assuming that all those messages are direct childs of your Firebase database root, in order to make it work, please use the following more simpler code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<ChatMsg> chatlist = new ArrayList<>();
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            ChatMsg chatmsg = dataSnapshot.getValue(ChatMsg.class);
            chatlist.add(chatmsg);
        }
        ListView listofMsg = (ListView) findViewById(R.id.list_of_messange);
        DaftarChat adapter = new DaftarChat(MainActivity.this, chatlist);
        listofMsg.setAdapter(adapter);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
rootRef.addListenerForSingleValueEvent(eventListener);
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Hi Alex,Sorry for late Reply.. I want to use onChildAdded Method instead of onDataChange. I managed to retrieve data from firebase when I use onDataChange, but it keeps downloading all the data. so it consumes too much data, although if i use .clear() method. What I want is to retrieve data for the last saved one. and I think that could be solved by using onChildAdded Method.. Do you Think So?? – Helwa Mar 02 '18 at 13:59
  • It's much easier, because `onDataChange()` method will handle all events for you. When `onChildAdded`, `onChildChanged`, `onChildRemoved` and `onChildMoved`. That's why I said it's a more simpler way. But if you still want to use those methods, just use it in the same way as in my answer. – Alex Mamo Mar 02 '18 at 14:03
0

I Just Found The Answer, We Should use Iterator Method for this case.

Here is the great article I found from the internet:

onChildAdded Method with iterator

Helwa
  • 1
  • 4