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.
Related
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 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
So I have a piece of code that look like this
floorList = new ArrayList<String>();
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, floorList);
arrayAdapter.setNotifyOnChange(true);
floorSpinner.setAdapter(arrayAdapter);
floorList.add("a");
Call<ParkourResponse<ParkingPlaceResponseObject>> getPlaceDetailCall = Helper.getParkourService().getPlaceDetail(placeID);
getPlaceDetailCall.enqueue(new Callback<ParkourResponse<ParkingPlaceResponseObject>>() {
#Override
public void onResponse(Call<ParkourResponse<ParkingPlaceResponseObject>> call, Response<ParkourResponse<ParkingPlaceResponseObject>> response) {
ParkingPlaceResponseObject placeDetail = response.body().getRespObject();
Floor[] floorArray = placeDetail.getFloor();
floorList.clear();
arrayAdapter.notifyDataSetChanged();
for(int i = 0; i < floorArray.length; i++){
floorList.add(Integer.toString(floorArray[i].getNumber()));
}
}
#Override
public void onFailure(Call<ParkourResponse<ParkingPlaceResponseObject>> call, Throwable t) {
}
});
So when I tried to add "a" that is not part of the Retrofit service, the spinner is updated.
But everything that I do to floorList inside the onResponse() does not update the adapter and spinner.
I tried to clear it on the onResponse() and then call the notifyDataSetChanged(), even that does not delete the "a" option from the spinner.
Anyone know how to fix this?
Note the comments by Selvin and Gautam while following this answer, as they are correct and will help you to understand why the code should look like the following:
floorList = new ArrayList<String>();
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, floorList);
arrayAdapter.setNotifyOnChange(true);
floorSpinner.setAdapter(arrayAdapter);
arrayAdapter.add("a"); //I would jsut pass this into the adapter's constructor
Call<ParkourResponse<ParkingPlaceResponseObject>> getPlaceDetailCall = Helper.getParkourService().getPlaceDetail(placeID);
getPlaceDetailCall.enqueue(new Callback<ParkourResponse<ParkingPlaceResponseObject>>() {
#Override
public void onResponse(Call<ParkourResponse<ParkingPlaceResponseObject>> call, Response<ParkourResponse<ParkingPlaceResponseObject>> response) {
ParkingPlaceResponseObject placeDetail = response.body().getRespObject();
Floor[] floorArray = placeDetail.getFloor();
arrayAdapter.clear(); //update the adapter, not the external list
arrayAdapter.setNotifyOnChange(false); //we'll only update after list is full, for efficiency
for(int i = 0; i < floorArray.length; i++){
arrayAdapter.add(Integer.toString(floorArray[i].getNumber()));
}
arrayAdapter.setNotifyOnChange(true);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<ParkourResponse<ParkingPlaceResponseObject>> call, Throwable t) {
}
});
I load a recyclerview based on Firebase data via the following method:
#Override
public void onStart() {
super.onStart();
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String newPollEpoch = dataSnapshot.getKey();
if (mNewPollsAray.contains(newPollEpoch)) {
Log.v("POLL_ADDED", "POLL ADDED: " + newPollEpoch);
} else {
Log.v("Child_Added", "The new child is " + newPollEpoch);
String newPollImageURL = dataSnapshot.child(IMAGE_URL).getValue(String.class);
//TODO: On additional devices, numbesr are not appearing as the question
String newPollQuestion = dataSnapshot.child(QUESTION_STRING).getValue(String.class);
String convertedQuestion = newPollQuestion.toString();
mNewPollsAray.add(0, new Poll(convertedQuestion, newPollImageURL, newPollEpoch));
mNewPollsAdapter.notifyDataSetChanged();
Log.v("OnChildChanged", "OnCHILDCHANGEDCALLED " + dataSnapshot.getKey());
}
}
#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) {
}
};
mPollsRef.addChildEventListener(mChildEventListener);
}
#Override
public void onStop() {
super.onStop();
mPollsRef.removeEventListener(mChildEventListener);
}
Here is the method I call when an item in the recyclerview is clicked:
#Override
public void onClick(View view) {
view.getId();
int itemPosition = getAdapterPosition();
String passEpoch = mNewPollsAray.get(itemPosition).getPollID();
Log.v("PASSED_ID", "The passed ID is " + passEpoch);
Intent toPoll = new Intent(getActivity(), PollHostActivity.class);
toPoll.putExtra("POLL_ID", passEpoch);
startActivity(toPoll);
}
The fragment I am loading it from is part of a TabLayout. When I navigate between the tabs the recyclerview loads correctly.
However, when I click an item in the recyclerview (which takes me to a new activity) and then navigate back to the fragment containing the recyclerview, items get duplicated and the recyclerview items are all out of order. I think it has to do with onStart() being called multiple times and essentially "stacking" new items onto the recyclerview instead of replacing them, but I was hoping to confirm.
This happens because you add a listener, but never remove it. So the next time when you enter the view, you add a second listener and thus get two calls to onChildAdded() for each item in the database.
The solution is to remove the listener when you exit the view. Since you attach the listener in onStart(), you should remove it again in onStop():
#Override
public void onStop() {
mPollsRef.removeEventListener(mChildEventListener);
}
You can try with code, I was facing similar issue got resolved with bellow changes.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(mMainLayout == null)
{
mMainLayout = inflater.inflate(R.layout.fragment_main, container,false);
...
}
return mMainLayout;
}
When mMainlayout is not null, it mean that your fragment instance has already one instance of the mMainLayout and already added to ViewGroup container no need to add it again. You may be facing issue as you are adding same view again to same container.
By Clear the data set you can avoid loading of similar items again in Recycler View. It worked for me.
listOftrailers.clear();
try {
JSONObject jsonObject = new JSONObject(data);
JSONArray jsonArray = jsonObject.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
MovieTrailer item = new MovieTrailer();
JSONObject js = jsonArray.getJSONObject(i);
item.setVideoID(js.getString("id"));
item.setVideoName(js.getString("name"));
item.setVideoKey(js.getString("key"));
item.setVideoSite(js.getString("site"));
item.setVideoType(js.getString("type"));
String name = item.getVideoName();
if (name.contains("Official Trailer") ||
name.startsWith("Official"))
listOftrailers.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
videosadapter = new TrailerListAdapter(listOftrailers.size(),
listOftrailers, MoviePage.this);
recyclerView.setAdapter(videosadapter);
I am using FirebaseRecyclerAdapter that comes with FirebaseAndroid-UI library and I assume that when the data will change on Firebase it will automatically refresh and update the RecyclerView.
My code is simple:
Firebase firebasePicturesRef = new Firebase(FIREBASE_URL);
mAdapter = new FirebaseRecyclerAdapter<Image, ImageViewHolder>(
Image.class, R.layout.pictures_grid_item,
ImageViewHolder.class, firebasePicturesRef) {
#Override
protected void populateViewHolder(ImageViewHolder viewHolder, Image model, int position) {
super.populateViewHolder(viewHolder, model, position);
Glide.with(getActivity()).load(model.getThumbnailUrl()).into(viewHolder.mImageView);
}
};
I have also tried to manually refresh the adapter using notifyDatasetChanged in the the onDataChange method:
firebasePicturesRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (mAdapter != null)
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Am I doing something wrong? What is the fix?
I found the problem, i was calling mAdapter.cleanup(); in onStop() of the fragment. Removing it fixed the problem.
Instead of doing cleanup in onStop(); it should be called in onDestroy()
As suggested by Frank:
In general you should call cleanup() in the "opposite" method from where you create the adapter. So onCreate()<->onDestroy(), onStart()<->onStop(), onPause()<->onResume()