How to show single value if multiple duplicate values exists? - android

I am using firebase database for storing data and firebase recycler adapter for showing the data.
RecyclerView recyclerView;
static String SelectedCode;
DatabaseReference root;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_get_data);
Firebase.setAndroidContext(this);
recyclerView=(RecyclerView)findViewById(R.id.recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
root = FirebaseDatabase.getInstance().getReference();
Query query = root.child("download").orderByChild("subjectCode");
FirebaseRecyclerAdapter<CourseStorage, GetData.MessageViewHolder> adapter = new FirebaseRecyclerAdapter<CourseStorage, GetData.MessageViewHolder>(
CourseStorage.class,
android.R.layout.two_line_list_item,
GetData.MessageViewHolder.class, query
) {
#Override
protected void populateViewHolder(MessageViewHolder viewHolder, final CourseStorage model, int position) {
viewHolder.textView.setText(model.getSubjectCode());
}
};
recyclerView.setAdapter(adapter);
}
public static class MessageViewHolder extends RecyclerView.ViewHolder{
TextView textView;
View mview;
public MessageViewHolder(View itemView) {
super(itemView);
textView=(TextView)itemView.findViewById(android.R.id.text1);
mview=itemView;
}
}
The getSubjectCode function in CourseStorage class is
public String getSubjectCode () {
return subjectCode;
}
My database is
I am getting output as
I dont want same subjectCode to be displayed twice. How can i achieve it?

There is no GROUP BY clause in the Firebase Database query language. As is quite often the case when using a NoSQL database, the solution is to store the data in the way your app wants to access it.
In your case, since you're showing a list of subject codes, I'd store a list of subject codes in the database (in addition to your current data). For example:
latestItemKeyPerSubjectCode
"COEG301": "-KM...38N"
"COEG341": "-KM...vd-"
...
The exact value that you store really depends on your needs. In this case I stored the key of the most recent item with that subject code, but you could also store the file name (if you'd like to display that in your app) or simply true if you have no need for a meaningful value.

Related

Can i get documents from collecions i have on Firestore

I have my fire store set up and connected to my app. There are these categories and I want when I click on one category to fetch all subcategory from that category. Can someone explain to me step by step how to do that?
public class BeautyIzbornik extends Activity {
ImageButton imageButton;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference firemRef = db.collection("beauty");
private FirmeAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firmeinfo);
setUpRecyclerView();
}
private void setUpRecyclerView(){
Query query= firemRef.orderBy("logo",Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Firme> options = new FirestoreRecyclerOptions.Builder<Firme>()
.setQuery(query,Firme.class)
.build();
adapter= new FirmeAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
my Fire store looks like this
This is my main category and subcategories:
This are subcollection from one subcategory:
And now in my Main activity, I open the main category and I want when I press on subcategory(whic are all displeyed in my main activity) I want to open new activity and fill it with items from that subcategory... I have more subcategories and items but I hope you understand what I want to show.
so i want to have my Main activity filled with categoriys,secnd activity to fill with subcategorys and third activity where i will display data of some items that is clicked in secnd activity i hope you understand me my englis is bad :D
It would be more useful if you provided the database schema. But the idea is the same on all schemas.
Query query= firemRef.document("myDocumentHERE");
...
You can get the collection of the "myDocumenthere" by doing the following
Query query= firemRef.document("myDocumentHERE").collection("myCollection");
I'd recommend reading the official documentation, there's code examples there and its explained much better.
Source
Can i get documents from collecions i have on Firestore
yes you can! do you want to display your data in recycler?
Try this. Watch Now
to retrieve your beauty in document table, please use this:
firebaseFirestore...
String postId = doc.getDocument().getId(); //retrieving 'beauty` in document table
MyContent myContent = doc.getDocument().toObject(MyContent.class.withId(postId));
in Adapter class you will retrieve it again using this:
final String postId = contentList.get(position).PostId;
firebaseFirestore.collection("kategorije").document(postId).collection("beauty").addSnapshotListener(new EventListener<QuerySnapshot>() ...
please see his videos for details.

How to fix a List<> that become null inside OnCreateView()

I am trying to retrieve data from Firebase realtime-database and put it on a CardView inside a RecyclerView inside a Fragment.
But the Fragment shown is blank white with no error. I retrieve the data inside OnCreate method and add it into a List.
While debugging the application, found out that even after assigning the retrieved data inside the onCreate method, the list is still NULL inside the onCreateView method.
Fragment Dashboard List Class:
public class fragment_dashboard_list extends Fragment {
List<ibu> ibu_ibu;
FirebaseDatabase database;
DatabaseReference myRef ;
String a;
public fragment_dashboard_list() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ibu_ibu = new ArrayList<>();
database = FirebaseDatabase.getInstance();
myRef = database.getReference("Guardian");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
ibu value = dataSnapshot1.getValue(ibu.class);
ibu ibu_val = new ibu();
String alamat = value.getAlamat();
String foto = value.getFoto();
String hp = value.getHp();
String ktp = value.getKtp();
String nama = value.getNama();
String privilege = value.getPrivilege();
String ttl = value.getTtl();
ibu_val.setAlamat(alamat);
ibu_val.setFoto(foto);
ibu_val.setHp(hp);
ibu_val.setKtp(ktp);
ibu_val.setNama(nama);
ibu_val.setPrivilege(privilege);
ibu_val.setTtl(ttl);
// Here the List ibu_ibu is not NULL
ibu_ibu.add(ibu_val);
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w("Hello", "Failed to read value.", error.toException());
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_dashboard_list, container, false);
RecyclerView myrv = (RecyclerView) view.findViewById(R.id.dashboard_recycler_view);
//Here the List ibu_ibu is null
adapter_list_ibu myAdapter = new adapter_list_ibu(ibu_ibu);
LinearLayoutManager LinearLayoutManager = new LinearLayoutManager(getContext());
myrv.setLayoutManager(LinearLayoutManager);
myrv.setAdapter(myAdapter);
return view;
}
}
I expected the List to be not NULL inside OnCreateView so the Fragment wont Blank
Firebase APIs are asynchronous, which means that onDataChange() method returns immediately after it's invoked, and the callback will be called some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available.
Because that method returns immediately, your ibu_val list that you're trying to use it outside the onDataChange() method, will not have been populated from the callback yet and that's why is always empty.
Basically, you're trying to use a value of variable synchronously from an API that's asynchronous. That's not a good idea, you should handle the APIs asynchronously as intended.
A quick solve for this problem would be to notify the adapter once you got all elements from the database using:
myrv.notifyDatasetChanged();
So add this line of code right after where the for loop ends.
If you intent to use that list outside the callback, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Retrieve posts from firebase database using a field within the child

project tree image in this link
I am developing a social media app
In the Firebase database,
There will be Users node,posts node,likes node and request type nodes
Users nodes contains fields which represents users details and it has a uid which is like a key
Under the posts node, there will be a postskey within it there will be the details of the posts like uid,profileimage,postimage, description,date,time,fullname
The uid in the posts node is the uid in the Users node
I successfully uploaded images into the firebase storage and its url would be in the postimage field within the child node
To retrieve the particular users posts and display it in the particular users profile I tried this code which I enclosed in the images
But the posts of the user doesn't shows and white blank activity only shows up
Can u guide me to achieve my expected result
I am not good in English
Sorry,if you cannot understand my question because of my poor English
within OnCreate ,
mAuth=FirebaseAuth.getInstance();
currentUserID=mAuth.getCurrentUser().getUid();
PostsRef=FirebaseDatabase.getInstance().getReference().child("Posts");
myPostsList=(RecyclerView)findViewById(R.id.my_all_posts_list);
myPostsList.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
myPostsList.setLayoutManager(linearLayoutManager);
DisplayMyAllPosts();
within Displaymyallposts method
private void DisplayMyAllPosts() {
Query myPostsQuery=PostsRef.orderByChild("uid").startAt(currentUserID).endAt(currentUserID+"\uf8ff");
FirebaseRecyclerOptions<Posts> options=new FirebaseRecyclerOptions.Builder<Posts>().setQuery(myPostsQuery,Posts.class).build();
FirebaseRecyclerAdapter<Posts,MyPostsViewHolder> firebaseRecyclerAdapter=new FirebaseRecyclerAdapter<Posts, MyPostsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull MyPostsViewHolder holder, int position, #NonNull Posts model) {
holder.fullname.setText(model.getFullname());
holder.date.setText(model.getDate());
holder.time.setText(model.getTime());
holder.description.setText(model.getDescription());
Picasso.get().load(model.getProfileimage()).into(holder.profileimage);
Picasso.get().load(model.getPostimage()).into(holder.postImage);
}
#NonNull
#Override
public MyPostsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.all_posts_layout,viewGroup,false);
MyPostsViewHolder viewHolder=new MyPostsViewHolder(view);
return viewHolder;
}
};
myPostsList.setAdapter(firebaseRecyclerAdapter);
}
public static class MyPostsViewHolder extends RecyclerView.ViewHolder{
TextView fullname,date,time,description;
CircleImageView profileimage;
ImageView postImage;
public MyPostsViewHolder(#NonNull View itemView) {
super(itemView);
fullname=itemView.findViewById(R.id.post_user_name);
date=itemView.findViewById(R.id.post_date);
time=itemView.findViewById(R.id.post_time);
description=itemView.findViewById(R.id.post_description);
profileimage=itemView.findViewById(R.id.post_profile_image);
postImage=itemView.findViewById(R.id.post_image);
}
}
The post is retrieved
it's because of my silly mistakes
I forgot to give startlistening
That's the reason for not been able to retrieve the post
But there is an another problem
Except the image all other fields are displaying
But not the image
The image is still blank

Recycler View Retrieving Childs of different Nodes

[
I am planning to retrieve data for a recycler view from the node "movies" and "tickets". I am using Android Studio.
Till now I have a code to retrieve data just from the node "movies".
Is there a possibility to add something to the code to be able to retrieve data from "tickets" also in the same RecycleView?
Thanks for your help :)
RecyclerView mRecyclerView;
FirebaseDatabase mFirebaseDatabase;
DatabaseReference mRef;
// send query to firebaseDatabase
mFirebaseDatabase = FirebaseDatabase.getInstance();
// the following line i suppose needs to change to "Cities"
mRef = mFirebaseDatabase.getReference().child("Cities/movies");
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Movie, MovieViewHolder> firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<Movie, MovieViewHolder>(
Movie.class,
R.layout.movies_all,
MovieViewHolder.class,
mRef
){
#Override
protected void populateViewHolder(MovieViewHolder viewHolder, Movie movie, int position){
viewHolder.setDetails(getApplicationContext(),
// the following line(s) again needs to change, but I don't know to what
movie.getTickets(),
movie.getKino(),
movie.getTime();
}
Edit: Or do I need a second "ViewHolder.class" and a second "FirebaseRecyclerAdapter" to retrieve from different nodes?

ParseQueryAdapter; using class in Android

I feel like a broken record.
After many attempts, I have failed at getting a listview through Parse data to display a specific set of information.
Here is my model...this is all data from users:
#ParseClassName("Midwifefirm")
public class Midwifefirm extends ParseObject {
public Midwifefirm() {
// A default constructor is required.
}
//practice name
public String getPracticeName() {
return getString("practicename");
}
public void setPracticeName(String practicename) {
put("practicename", practicename);
}
//education
public String getEducation() {
return getString("education");
}
public void setEducation(String education) {
put("education", education);
}
//years in practice
public String getYearsinPractice() {
return getString("yearsinpractice");
}
public void setYearsinPractice(String yearsinpractice) {
put("yearsinpractice", yearsinpractice);
}
//practice philosophy
public String getPracticePhilosophy() {
return getString("practicephilosophy");
}
public void setPracticePhilosophy(String practicephilosophy) {
put("practicephilosophy", practicephilosophy);
}
I have this adapter; I am wondering what to place in the query section, as I just want to pull the data into the ListView that is defined in the data model:
public class CustomMidwifeAdapter extends ParseQueryAdapter<Midwifefirm> {
public CustomMidwifeAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery("Midwives");
return query;
}
});
}
#Override
public View getItemView(Midwifefirm midwifefirm, View view, ViewGroup parent) {
if (view == null) {
view = View.inflate(getContext(), R.layout.activity_midwife_result_list, null);
}
//use midwifefirm as item view/list
super.getItemView(midwifefirm, view, parent);
// find in layout the practice name
TextView titleTextView = (TextView) view.findViewById(R.id.practicename);
//in the midwifefirm data model, call getPracticename
titleTextView.setText(midwifefirm.getString("practicename"));
// Add education view
TextView EducationView = (TextView) view.findViewById(R.id.education);
EducationView.setText(midwifefirm.getString("education"));
// Add yearsexperience view
TextView ExperienceView = (TextView) view.findViewById(R.id.yearsinpractice);
ExperienceView.setText(midwifefirm.getString("yearsinpractice"));
//Add practice philosophy view
TextView PracticePhilosophyView = (TextView) view.findViewById(R.id.practicephilosophy);
PracticePhilosophyView.setText(midwifefirm.getString("practicephilosophy"));
return view;
}
}
And here is the Main Activity:
public class MidwifeResultList extends ListActivity {
private ParseQueryAdapter<ParseObject> mainAdapter;
private CustomMidwifeAdapter midwifeListAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize main ParseQueryAdapter
mainAdapter = new ParseQueryAdapter<ParseObject>(this, Midwifefirm.class);
//which keys in Midwife object
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
// Initialize the subclass of ParseQueryAdapter
midwifeListAdapter = new CustomMidwifeAdapter(this);
// Default view is all meals
setListAdapter(mainAdapter);
}
Every time I run this, I get no results.
Thanks in advance for any help
Michael
I can tell you why I think it fails now and I can tell you why I'm very sure it will fail after you sort out the current issue.
It seems that you're trying to use different classes
#ParseClassName("Midwifefirm")
public class Midwifefirm extends ParseObject {
and
ParseQuery query = new ParseQuery("Midwives");
You need to be consistent and use the same name. Either use Midwives or Midwifefirm for both. Let's assume you picked the latter. You're also saying
all that is stored in the user table...wasn't sure if I needed to create new tables.
The query above wants to get all entries of type Midwives. If there's no such type, it'll return nothing. So you have two options:
In you Parse dashboard, reate a class Midwifefirm (don't forget to update the String inside #ParseClassName above) and store your Midwifefirm data in there. You don't need to change your query for this.
Add a column to your ParseUser class, such as type, that you can set to Midwifefirm or whatever if that user is a Midwifefirm or whatever. Then in your query you need to add:
ParseQuery query = new ParseQuery("Midwives");
query.whereEquals("type", "Midwifefirm");
I greatly prefer the former.
Anyway, once your done that, the issue is that you're not using a custom view for this. You're relying on the one provided by Android by default for ListActivity. I am fairly sure it doesn't have any of the fields you're after, so you should create a custom view for this, then at the top of onCreate in your Activity make sure you use it
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_custom_view);
By the way, the following are redundant if you populate then in getItemView anyway:
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
One final advice: if you're still having issues, set breakpoints and do some investigations first. What you need to check is:
Whether you get anything at all from Parse when you do your query. Your adapter has an useful addOnQueryLoadListener that you may use to check whether anything's been retrieved at all.
If stuff is retrieved successfully, you need to check whether the list view is populated correctly. Again, use breakpoints, this time in getItemView maybe.
I'm going to do a wild guess here using the lovely brainwrecking API help of Parse.com about ParseQueryAdapters
Before continuing, may I mind you that my experience with ParseQueryAdapters is a minimum but I think I have a basic knowledge about them + I have some experience with Parse on its own. ANYHOW,
As an example they use both these
final ParseQueryAdapter adapter = new ParseQueryAdapter(this, "Midwives");
adapter.setTextKey("name");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
and
// Instantiate a QueryFactory to define the ParseQuery to be used for fetching items in this
// Adapter.
ParseQueryAdapter.QueryFactory<ParseObject> factory =
new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("Midwives");
return query;
}
};
// Pass the factory into the ParseQueryAdapter's constructor.
ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, factory);
adapter.setTextKey("name");
// Perhaps set a callback to be fired upon successful loading of a new set of ParseObjects.
adapter.addOnQueryLoadListener(new OnQueryLoadListener<ParseObject>() {
public void onLoading() {
// Trigger any "loading" UI
}
public void onLoaded(List<ParseObject> objects, ParseException e) {
// Execute any post-loading logic, hide "loading" UI
}
});
// Attach it to your ListView, as in the example above
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
To start of, the reason why I think nothing is loading inside your list has to do with a little mixup between the initilization of your ParseQueryAdapter and your custom adapter.
You configure the basic adapter, and also initialize a custom adapter but you don't do anything with the custom adapter, tho the custom adapter seems to contain the logics to load your data model.
I think what you're looking for is something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize main ParseQueryAdapter
mainAdapter = new CustomMidwifeAdapter<ParseObject>(this);
//which keys in Midwife object
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
// Default view is all meals
setListAdapter(mainAdapter);
}
All you need to pass is the context (aka "this"), and the constructor of your custom class will handle the factory internal
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery("Midwives");
return query;
}
});
Tho to be honest since you do:
new ParseQueryAdapter<ParseObject>(this, Midwifefirm.class);
I wonder if you'd need to change your "QueryFactory" to
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery(MidWifefirm.class);
return query;
}
});
Where you pass a class to the the query rather than the tableName, but I could be wrong on that one.
Either way I hope this has helped in some way!

Categories

Resources