I want to retrieve data from firebase to show in a ListView but when i run the app, the ListView does not show any data. I see the ListView but there is no data. Can you tell me why and what can i do? I had the same problem when i tried with spinner.
public class CitiesList extends AppCompatActivity {
DatabaseReference databasePaths;
private ListView ListViewCities;
private ArrayList<String> ArrayListCities;
private ArrayAdapter<String> adapterCities;
Paths info;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cities_list);
ListViewCities = (ListView) findViewById(R.id.ListViewCities);
ArrayListCities = new ArrayList<>();
databasePaths = FirebaseDatabase.getInstance().getReference("Paths");
databasePaths.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot items: dataSnapshot.getChildren())
{
info = items.getValue(Paths.class);
ArrayListCities.add(info.city);
}
adapterCities = new ArrayAdapter<>(CitiesList.this, android.R.layout.simple_list_item_1);
ListViewCities.setAdapter(adapterCities);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}}
You need to set new list to adapter, which you are not doing into your current code. Modify below line
adapterCities = new ArrayAdapter<>(CitiesList.this, android.R.layout.simple_list_item_1);
ListViewCities.setAdapter(adapterCities);
as
adapterCities = new ArrayAdapter<>(CitiesList.this, android.R.layout.simple_list_item_1, ArrayListCities);
ListViewCities.setAdapter(adapterCities);
As a side note, try to follow coding style guidelines.
You need to pass in Adapter the TextView from where the adapter will set the data.
So after R.layout.XXXX, you need to pass:
android.R.id.text1
Related
i noticed that my app uses alot of memory so i used the profiler and found that as soon as the app starts and splash screen appear the app get over 150+MB even on splash before opening main or anyother activity.
Update: i solved all memory leaks, yet my app still my app uses on my real phone nearly 300+ MB of ram just while browsing the MainActivity with recycleview.
LeakCanary and i keeps giving me error that this is a cause of memory leaks so anyone please tell me how to solve it >
if you clicked any recyclerview items:
[]
Activity Code:
public class WorkDetailsActivity extends AppCompatActivity {
ArrayList<String> imagesFromURL = new ArrayList<String>();
ActivityWorkDetailsBinding binding;
DatabaseReference databaseReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityWorkDetailsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
String workUid_details = getIntent().getExtras().getString("UID_Details");
String title = getIntent().getExtras().getString("name");
String description = getIntent().getExtras().getString("description");
String location = getIntent().getExtras().getString("location");
String path = getIntent().getExtras().getString("path");
databaseReference = FirebaseDatabase.getInstance().getReference().child("Work").child(path);
databaseReference.child(workUid_details).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
binding.workDetailsTitle.setText(title);
binding.workDetailsDescription.setText(description);
binding.workDetailsLocation.setText(location);
binding.getUIDDetails.setText(workUid_details);
for (DataSnapshot dataSnapshot : snapshot.child("images").getChildren()) {
String value = String.valueOf(dataSnapshot.child("image").getValue());
imagesFromURL.add(value);
//Log.i("Value", String.valueOf(imagesFromURL));
}
initRecyclerView();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void initRecyclerView(){
binding.workDetailsImage.setNestedScrollingEnabled(false);
binding.workDetailsImage.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
binding.workDetailsImage.setHasFixedSize(true);
PrivateRecyclerAdapter adapter = new PrivateRecyclerAdapter(this, imagesFromURL);
binding.workDetailsImage.setAdapter(adapter);
binding.progressBar.setVisibility(View.VISIBLE);
/* //Add Divider between recyclerView items
DividerItemDecoration itemDecorator = new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL);
binding.workDetailsImage.addItemDecoration(itemDecorator);
final int radius = getResources().getDimensionPixelSize(R.dimen.radius);
final int dotsHeight = getResources().getDimensionPixelSize(R.dimen.dots_height);
final int color = ContextCompat.getColor(this, R.color.green);
binding.workDetailsImage.addItemDecoration(new DotsIndicatorDecoration(radius, radius * 2, dotsHeight, color, color));
binding.workDetailsImage.setOnFlingListener(null);
new PagerSnapHelper().attachToRecyclerView(binding.workDetailsImage);*/
}
#Override
protected void onDestroy() {
super.onDestroy();
imagesFromURL = null;
binding.workDetailsImage.setAdapter(null);
binding.workDetailsTitle.setText(null);
binding.workDetailsLocation.setText(null);
binding.workDetailsDescription.setText(null);
binding.getUIDDetails.setText(null);
binding.workDetailsImage.setAdapter(null);
}
The problem with the above code is that you are registering value event listener as anonymous implementation. Which will hold the reference of the activity. And based on the LeakCanary stack trace your activity was in destroyed state but due to the listener the activity instance is not being able to be garbage collected and hence it is being leaked. What you need to do is add and remove the listener as below.
Create the instance of ValueEventListener and store it in variable
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
binding.workDetailsTitle.setText(title);
binding.workDetailsDescription.setText(description);
binding.workDetailsLocation.setText(location);
binding.getUIDDetails.setText(workUid_details);
for (DataSnapshot dataSnapshot : snapshot.child("images").getChildren()) {
String value = String.valueOf(dataSnapshot.child("image").getValue());
imagesFromURL.add(value);
//Log.i("Value", String.valueOf(imagesFromURL));
}
initRecyclerView();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Register it in the onStart method of your activity lifecycle using
#Override
protected void onStart() {
databaseReference.child(workUid_details).addValueEventListener(valueEventListener);
}
Remove the listener in onStop method of your activity lifecycle using
#Override
protected void onStop() {
databaseReference.child(workUid_details).removeEventListener(valueEventListener);
}
I have a Spinner in which I want value from Firebase Database. I try what I Know since I am new to Android but the value in Spinner is not coming as i want it is coming like this.
When i am passing String Array directly it is coming Properly but it is doing problem when the String Array fill with the Firebase data.Here is also my Database.
final String[] batcht = {"1903f","343","33323"};
XML
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/stubatch"
/>
JAVA
public class Student extends AppCompatActivity {
DatabaseReference ref;
Spinner spinner;
List<String> store;
String[] batchlist;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student);
spinner = findViewById(R.id.stubatch);
store =new ArrayList<>();
Student_ID =getIntent().getStringExtra("Student_Id");
ref = FirebaseDatabase.getInstance().getReference("Batch");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot batches : dataSnapshot.getChildren()){
String a= batches.getValue().toString();
store.add(a);
}
batchlist = new String[store.size()];
for(int i=0;i<batchlist.length;i++){
batchlist[i]=store.get(i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(getApplicationContext(),android.R.layout.simple_spinner_item,batchlist);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
spinner.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}}
I don't know what I am doing wrong.
When you are fetching data you are doing some mistake. You are not fetching according to ur insertion technique try this
In for loop of datasnapshot use this code:
String a = batches.child("1710f").getValue().toString()
By doing this only data with the 1710f key will be picked for other values you have listed out all the keys.
Hopefully, this will workout
Actually the problem was that I was Storing the Data in the Firebase the wrong way.
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String batchdata = edit.getText().toString();
ref = FirebaseDatabase.getInstance().getReference("Batch").child(User_Id);
ref.child(batchdata).setValue(batchdata);
Toast.makeText(getApplicationContext(), "Successful", Toast.LENGTH_SHORT).show();
Intent i = new Intent(getApplicationContext(),Faculty.class);
i.putExtra("User_Id",User_Id);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
});
I Just have to remove the .child(User_Id);.
Now it is working Fine.
I'm creating a ListView by populating an ArrayList in open activity and opening it as a ListView in another activity.
When I open the second activity My ListView only populates when I open the activity, the Get_Issue activity opens blank. When I go back and re-enter the activity (Calling the Get_Issue.class for the second time). Then the ListViewis populated.
I guess the screen is loading before the listView is created/populated?
How can I improve my code so that the listView is populate the first time I call the Get_Issue activity. I do not want to open an empty activity.
class ProfileActivity extends AppCompatActivity implements View.OnClickListener {
DatabaseReference databaseIssue;
public static List<Issue> issueList = new ArrayList<>();
public static List<Issue> getIssueList() {
return issueList;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
getData = (Button) findViewById(R.id.getData);
databaseIssue = FirebaseDatabase.getInstance().getReference("Issue");
}
private void getTheData(){
databaseIssue.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
issueList.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Issue getData = postSnapshot.getValue(Issue.class);
issueList.add(getData);}}
});
}
public void onClick(View view) {
if(view == getData){
getTheData();
startActivity(new Intent(this, Get_Issue.class));
}
}
}
The adapter class
public class Get_Issue extends AppCompatActivity {
public void populateListView() {
List<Issue> issues = ProfileActivity.getIssueList();
ArrayAdapter<Issue> adapter = new ArrayAdapter<>(
this,
R.layout.da_item,
issues);
ListView list = findViewById(R.id.listView);
list.setAdapter(adapter);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.issue_list);
populateListView();
}
}
i am trying to read a specific child in Firebase which i named Tags. the problem is, i just can't put the object from tags (dados.getValue) into a ArrayList to later populate in my ListView.
I know is simple, sorry about that, ut i am new here in android
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_taglist);
tags = new ArrayList<>();
tagList = (ListView) findViewById(R.id.tagsList);
tagsRefs = FirebaseConfig.getFireBase();
tagsRefs.child("tags").child("categorias");
tagsRefs.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dados : dataSnapshot.child("tags").getChildren()) {
System.out.println("tag EXTRAIDA NO taglist " + dados.getValue());
dados.getValue(); //HOW CAN I PUT THIS INTO AN ARRAY TO LATER ADD IN MY ArrayList tags??
String tagS = dados.getValue(String.class);
tags.addAll(tagS);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
tagAdapter = new ArrayAdapter(getBaseContext(), android.R.layout.simple_list_item_2,
android.R.id.text1,
tags);
tagList.setAdapter(tagAdapter);
tagList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedTag = (String) tagList.getItemAtPosition(position);
setSelectedTag(selectedTag);
}
});
}
here is my database:
h
This is happening because onDataChange() method is called asynchronously. This means that the statement that adds tags to your list is executed before onDataChange() method has been called. That's why your list is empty outside that method. So in order to use that lists, you need to use it inside the onDataChange().
For other approach, please visit this post and this post.
Hope it helps.
I wanna add items to my list but it only shows the first one:
public class MainActivity extends Activity {
Server server;
TextView infoip, msg;
TextView usersTitle;
String[] array = {"a"};
ArrayList<String> lst;
ArrayAdapter<String> adapter;
ListView userList;
#Override
public void onCreate(Bundle savedInstanceState) {
lst = new ArrayList<String>(Arrays.asList(array));
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst);
userList = (ListView) findViewById(R.id.userList);
userList.setAdapter(adapter);
From this other class method, everytime it is called I want the text to go below the first one. The method certainly runs but it does not put the text below the previous one. It just shows "a"! Anyone knows why?
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.lst.add(message);
activity.adapter.notifyDataSetChanged();
}
});
I have also tried:
adapter.insert(String, int);
lst.add(int, String);
And even added in the onCreate method this:
lst.add(1, "2");
adapter.notifyDataSetChanged();
And still doesnt add the "2"!!
If you are adding items to Arraylist from another class ,you have to declare your Arraylist Static.So that it can hold items in memory.
Replace ArrayList lst with public static ArrayList
Here is the solution to your Problem.I have created an Activity class and Tests java class.
public class MainActivity extends Activity {
String[] array = {"a"};
public static ArrayList<String> lst;
ArrayAdapter<String> adapter;
ListView userList;
Tests tests = new Tests();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userList = (ListView) findViewById(R.id.userList);
lst = new ArrayList<String>(Arrays.asList(array));
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst);
userList.setAdapter(adapter);
tests.callThread();
}
}
Here is the Tests.java Class
public class Tests {
int i = 0;
String message = "";
Thread runOnUiThread;
public void callThread()
{
new Thread(new Runnable() {
#Override
public void run() {
try {
while (i < 10) {
i = i + 1;
message = String.valueOf(i);
//Create a server socket object and bind it to a port
MainActivity.lst.add(message);
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
}
Just call your service inside this thread where I have incremented variable i and by this way you can populate the list in right order.
Can you tell whether the other class is Activity or Fragment ?
And while adding the data into Arraylist, you don't need the Thread to be run in order to insert new data to Arraylist
Try to make "lst" and "adapter" both static.
I'm suspicious about the runOnUiThread. Can you provide more information why did you use this function? Also i highly recommend using RecyclerView
Also you can refer to this post for adding items to RecyclerView