Not displaying in UI after code refactoring - android

I am trying to refactor my Android Firebase project, to move code for inserting data into database and for displaying UI from MainActivity to MessageDao class.
This is my MessageDao class:
public class MessageDao {
private FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
private DatabaseReference mMessagesDatabaseRef = mFirebaseDatabase.getReference().child("messages");;
private List<Message> messages = new ArrayList<>();
private MessageAdapter mMessageAdapter = new MessageAdapter(messages);
public void write(Message message){
mMessagesDatabaseRef.push().setValue(message);
}
public void updateList(){
mMessagesDatabaseRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
messages.add(dataSnapshot.getValue(Message.class));
mMessageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Message msg = dataSnapshot.getValue(Message.class);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
And MainActivity class:
public class MainActivity extends AppCompatActivity {
.....
private MessageDao mesageDao;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSendButton = (Button) findViewById(R.id.sendButton);
mesageDao = new MessageDao();
.....
// Send button sends a message and clears the EditText
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Message message = new Message(mMessageEditText.getText().toString(), mUsername, null);
mesageDao.write(message);
mMessageEditText.setText("");
}
});
mesageDao.updateList();
}
}
When I click mSendButton button, it writes into database, but it's not displaying in my UI. When childEventListener is in MainActivity it all works fine, but when I move it to MessageDao and call it in MainActivity onCreate method with mesageDao.updateList() it's not working. So, what am I missing here ?

To solve this, your MessageDao class in which you have moved the code, needs to extends Application like this:
public class MessageDao extends Application {...}
Hope it helps.

Related

Failed to convert value of type java.util.HashMap to String and app crashes

public class MainActivity extends AppCompatActivity {
//points to the root node of the database
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mConditionRef = mRootRef.child("condition");
TextView content;
Button sunny, foggy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
content = (TextView) findViewById(R.id.condition);
sunny = (Button) findViewById(R.id.sunny);
foggy = (Button) findViewById(R.id.foggy);
}
#Override
protected void onStart() {
super.onStart();
mConditionRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String text = dataSnapshot.getValue(String.class);
content.setText(text);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
sunny.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mConditionRef.setValue("Sunny");
mRootRef.child("condition").push().setValue("Abhijeet Jain2");
}
});
foggy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mConditionRef.setValue("Foggy");
}
});
}
}
The string gets added in the realtime database with a automatic made id but the app crashes as soon as I press the button "sunny".
What could be the reason and the solution?

Can't populate listview from firebase database but toast works

I am trying to update a listview realtime from my firebase database. The data uploads to database without any issues and a toast which displays the newly added data also works. But I could not get the listview to work. Here is my code:
public class MainActivity extends AppCompatActivity {
private ListView list;
private Button btnadd;
private EditText ettext;
private DatabaseReference mDatabase;
private ArrayList<String> arrayList= new ArrayList<>();
private ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list=findViewById(R.id.liston);
list.setAdapter(adapter);
btnadd=findViewById(R.id.button);
ettext=findViewById(R.id.ed);
btnadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDatabase.push().setValue(ettext.getText().toString());
}
});
mDatabase= FirebaseDatabase.getInstance().getReference();
adapter= new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arrayList);
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String string =dataSnapshot.getValue(String.class);
arrayList.add(string);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(),
"Name: " + dataSnapshot.getValue(), Toast.LENGTH_LONG)
.show();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
String string =dataSnapshot.getValue(String.class);
arrayList.remove(string);
adapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
The updation of the database also happens from within the app using an "edittext" and a button.

stop listening when moving to another page

I want to leave the page when listening is stopped.
FirebaseDatabase firebaseDatabase;
DatabaseReference myRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_showcomments);
}
private void callFireBase()
{
firebaseDatabase = FirebaseDatabase.getInstance();
myRef = firebaseDatabase.getReference();
myRef.child(id).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Toast.makeText(showcomments.this, "" + dataSnapshot.child("comment").getValue().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(showcomments.this, "hey", Toast.LENGTH_SHORT).show();
}
});
}
#Override
protected void onPause() {
super.onPause();
myRef.removeEventListener(firebaseDatabase);
}
when I go to another page I come out of the application I want to stop listening I tried a lot and searched for themes on the same site but not found nothing useful
Implement ChildEventListener into your Activity then remove it when going out of Activity.
public class MyActivity extends Activity implements ChildEventListener {
FirebaseDatabase firebaseDatabase;
DatabaseReference myRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_showcomments);
}
private void callFireBase() {
firebaseDatabase = FirebaseDatabase.getInstance();
myRef = firebaseDatabase.getReference();
myRef = myRef.child(id);
myRef.addChildEventListener(this);
}
#Override
public void onDestroy() {
super.onDestroy();
myRef.removeEventListener(this);
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Toast.makeText(showcomments.this, "" + dataSnapshot.child("comment").getValue().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(showcomments.this, "hey",
Toast.LENGTH_SHORT).show();
}
}
Please do like this and save your DatabaseReference accordingly from which you want to removeListener

Why I'm getting duplicated data from firebase database?

public class Post {
private String title;
private String massage;
public Post() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMassage() {
return massage;
}
public void setMassage(String massage) {
this.massage = massage;
}
}
public class Posts extends AppCompatActivity {
private DatabaseReference databaseReference, barRoomsCoordinates;
private FirebaseDatabase firebaseDatabase;
private List<Post> postList;
private List<String> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
postList = new ArrayList<>();
list = new ArrayList<>();
showAllMyPosts();
}
private void getPosts(List<String> posts) {
for (int i = 0; i < posts.size(); i++) {
databaseReference = firebaseDatabase.getReference().child("Posts").child(posts.get(i));
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Post posts = dataSnapshot.getValue(Post.class);
Post post = new Post();
post.setTitle(posts.getTitle());
post.setMassage(posts.getMassage());
postList.add(post);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
private void showAllMyPosts() {
FirebaseApp.initializeApp(Posts.this);
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
barRoomsCoordinates = firebaseDatabase.getReference().child("Posts");
barRoomsCoordinates.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterator iterator = dataSnapshot.getChildren().iterator();
while (iterator.hasNext()) {
list.add(((DataSnapshot) iterator.next()).getKey());
}
getPosts(list);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
};
handler.post(runnable);
}
}
This is my database structure
Posts
Post1
message1:
"abc + something"
title1:
"abc"
Post2
message2:
"def + something"
title2:
"def"
Post3
message3:
"ghi + something"
title3:
"ghi"
I'm getting duplicated array and can't understand why
please help me.
I also tried delete one reference and make a call but in this way I can't access the children of the JSON.
This is happening because of your for loop. You are creating a new databaseReference every time you loop. Take the databaseReference out of your loop and it will solve your problem or try to change the logic of getting the data from your Firebase database.
Hope it helps.
public class Posts extends AppCompatActivity {
private DatabaseReference databaseReference, barRoomsCoordinates;
private FirebaseDatabase firebaseDatabase;
private List<Post> postList;
private List<String> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
postList = new ArrayList<>();
list = new ArrayList<>();
getPosts();
}
private void getPosts() {
databaseReference = firebaseDatabase.getReference().child("Posts");
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Iterator iterator = dataSnapshot.getChildren().iterator();
while (iterator.hasNext()) {
Post post = new Post();
post.setTitle((String) ((DataSnapshot)iterator.next()).getValue());
post.setMassage((String) ((DataSnapshot)iterator.next()).getValue());
postList.add(post);
}
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Hello all,
I solved my problem with one reference to the database instead of two calls as i did before and with addChildEventListener.
Thanks

JUnit testing on class with firebase

I'm trying to JUnit test this class:
public class WeekListActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private ArrayList<String> weekList = new ArrayList<>();
private ArrayAdapter<String> adapter;
ListView weekListView;
Button AddWeekButton;
EditText InsertWeekEditText;
String weekNumber;
String subjectName;
String subjectCode;
User user;
DatabaseReference mDatabase;
DatabaseReference mRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_week_list);
FirebaseApp.initializeApp(this);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
Intent moveToDetailIntent = this.getIntent();
subjectName = moveToDetailIntent.getExtras().getString("Subject");
subjectCode = moveToDetailIntent.getExtras().getString("Fagkode");
mDatabase = FirebaseDatabase.getInstance().getReference().child("Studentfag").child(subjectCode).child("Week");
mRef = FirebaseDatabase.getInstance().getReference().child("Users").child(firebaseUser.getUid()).child("User info");
weekListView = (ListView) findViewById(R.id.WeekListView);
AddWeekButton = (Button) findViewById(R.id.AddWeekButton);
InsertWeekEditText = (EditText) findViewById(R.id.InsertWeek);
String userID = firebaseUser.getUid();
mRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
user = dataSnapshot.getValue(User.class);
if (user.isStudent){
View a = weekListView;
a.setMinimumHeight(80);
View b = AddWeekButton;
b.setVisibility(View.GONE);
View c = InsertWeekEditText;
c.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, weekList);
weekListView.setAdapter(adapter);
weekListView.setOnItemClickListener(this);
AddWeekButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
weekNumber= InsertWeekEditText.getText().toString();
mDatabase.child(weekNumber).child("id").setValue(weekNumber);
}
});
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String week = dataSnapshot.getKey().toString();
weekList.add("Week: " + week);
adapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
//Urelevante metoder for oss.
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
The problem is that when I build a new activity in my setup method it complains because this sentence:
mRef = FirebaseDatabase.getInstance().getReference().child("Users").child(firebaseUser.getUid()).child("User info");
is not able to build, when we don't have a firebase user.
Therefore I tried to Mock a firebaseuser in my testclass. The question is, how can I tell the class that it should use the mocked firebaseuser in onCreate? Is there a way to "send" the mocked object over? Thanks!
The beginning of my setup method:
#Before
public void setUp() throws Exception {
Intent i = new Intent();
i.putExtra("Subject", "Matematikk 1");
i.putExtra("Fagkode", "TMA4100");
FirebaseUser mockFirebaseUser = mock(FirebaseUser.class);
when(mockFirebaseUser.getUid()).thenReturn("uTZpVPPz8NT2LOvP4ufjs1L6r3P2");
Activity activity = Robolectric.buildActivity(WeekListActivity.class).withIntent(i).create().get();
}
As usual, I suggest everybody to not mix presentation and storage code. And this is a question for another topic.
And here the trick how you can achieve what you want.
First, extract method for Firebase initialisation and providing FirebaseAuth:
#VisibleForTest
#NonNull
FirebaseAuth initAndReturnFirebaseAuth() {
FirebaseApp.initializeApp(this);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
}
Second, create test activity and override this method:
public class TestWeekListActivity extends WeekListActivity {
#Override
#NonNull
FirebaseAuth initAndReturnFirebaseAuth() {
FirebaseAuth authMock = mock(FirebaseAuth.class);
when(authMock.getCurrentUser()).thenReturn(mockFirebaseUser);
return authMock;
}
}
And then use test activity in test instead of you real activity.
Hope it helps!

Categories

Resources