I'm quite new to programming and was looking quite a while now for a solution - but as I am not sure what exactly I am looking for, I decided to ask you.
Depending on the Data on Firebase I was looking to build a button including text and an image.
So for example I have a Database including:
User
Max (with the fields: University, Age, City)
Lena (with the fields: University, Age, City)
Is it possible to build a button with this Data but only if the Users are in the Database? So as there are 2 users - build 2 buttons including all the text (University, Age, City), if there would be 3 users - build 3 buttons.
Edit: Using Android Studio
I would recommend using recycler view and implementing onClick for recycler view.
This would take a lot of code:
Create xml for each item of recycler view
recycler_view_item.xml
Add recycler view to xml of current activity
3.Create a class MyUser.java like below:
public class MyUser {
private String University, City, Age;
public User(){}
public User(String University, String City) {
this.University = University;
this.City = City;
this.Age = Age;
}
public String getUniversity() { return University;}
public void setUniversity(String University) {
this.University = University;
}
public String getCity() {
return City;
}
public void setCity(String City) {
this.City = City;
}
public String getAge() {
return Age;
}
public void setAge(String Age) {
this.Age = Age;
}
}
Create adapter and view holder class
5.get user details from database in current activity :
private List<Book> userList;
userList = new ArrayList<>();
mRef = database.getReference().child("users");
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> bookData = dataSnapshot.getChildren();
for(DataSnapshot d : bookData){
MyUser myUser = d.getValue(User.class);
userList.add(myUser);
mAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Initialise the adapter with context and the userList
mAdapter = new MyRecyclerAdapter(getContext(), userList);
I have left out a lot of things like the adapter and view holder.
comment if u are stuck
Related
Lets say I have 100 documents with fields
Name
Age
Address
Now suppose my business model is change and I want to add new field call PhoneNumber.
How to add field PhoneNumber in all 100 documents ?
Is is possible to such stuff on NoSQL database?
You will have to write code to iterate all the documents to update, then actually update a new value in each one of them. Firestore has no similar command as "update tablename set x=y where ..." in SQL.
Is is possible to such stuff on NoSQL database?
Yes it is! Assuming you have a User model class that look like this:
public class User {
private String name;
private int age;
private String address;
private String phoneNumber; //Property that is newly added
public User() {}
public User(String name, int age, String address, String phoneNumber) {
this.name = name;
this.age = age;
this.address = address;
this.phoneNumber = phoneNumber;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getPhoneNumber() { return phoneNumber; }
public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; }
}
To actually add a new property and update it accordingly, you need to use setters. If you are setting the values directly onto the public fields, the setters are not mandatory.
How to add field PhoneNumber in all 100 documents?
As also #Doug Stevenson mentioned in his answer, to solve this, you need to iterate all the documents within your users collection. So please use the following lines of code:
db.collection("users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
User user = document.toObject(User.class);
user.setPhoneNumber("+1-111-111-111"); //Use the setter
String id = document.getId();
db.collection("users").document(id).set(user); //Set user object
}
}
}
});
The result of this code would be to add the phoneNumber property to all you User objects with a default value of +1-111-111-111. You can also set the value to null if it's more convenient for you. At the end, the updated object is set right on the corresponding reference.
If you are not using a model class, please see my answer from this post.
I have the following database data which I intend to display on a ListView with FirebaseListAdapter
My problem is creating a Query since the child elements after date are anonymous. Here is the query code
Query query = FirebaseDatabase.getInstance().getReference().child("Updates").child(refMail).child(day)
.orderByKey();
refMail and day are user email address and date respectively.
Here is also my Data Model Class
public class NotesDataModel {
private String Note;
private String uid;
private String time;
public NotesDataModel(){
}
public NotesDataModel(String Note, String uid, String time){
this.Note=Note;
this.uid=uid;
this.time=time;
}
public String getNote() {
return Note;
}
public void setNote(String note) {
Note = note;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}}
and finally the adapter initialization
FirebaseListOptions<NotesDataModel> options = new FirebaseListOptions.Builder<NotesDataModel>()
.setQuery(query, NotesDataModel.class)
.setLayout(R.layout.notes_cell_layout)
.build();
mAdapter = new FirebaseListAdapter<NotesDataModel>(options) {
#Override
protected void populateView(View view, NotesDataModel note, int position) { //some code }}; notesList.setAdapter(mAdapter);
Previous version worked like this
ref = FirebaseDatabase.getInstance().getReferenceFromUrl(FactoryDaftari.firebaseURL + "Updates/" + refMail + "/" + day);
And the Adapter initialization
mAdapter = new FirebaseListAdapter<NotesDataModel>(this, NotesDataModel.class, R.layout.notes_cell_layout, ref) {
#Override
protected void populateView(View view, NotesDataModel note, int position) { }};
You won't be able to make this query with the way your data is structured. It's common in NoSQL databases to make copies of data, structured for the purpose of specialized querying. So, if you want to query a list of notes, you'll need a structure where all the notes are children of the same parent, then make your query against that structure.
(Also, organizing your notes by a node with a date, like you have now, may not even be the best general structure in the first place.)
Is there any way I can display multiple components(like CheckBox, Label etc.) to a single cell of a Vaadin Grid? The Grid displays data populated dynamically by a GeneratedPropertyContainer.
Thanks in advance.
If you search the Vaadin directory you will find a few extensions, such as ComponentRenderer add-on which allow you to have such features in a somewhat painless way. Below you can see a code sample based on Vaadin v7.7.3 and v1.0.2 of the before-mentioned add-on. Please remember to update and recompile your widgetset.
public class GridWithMultiComponentRenderer extends VerticalLayout {
private static final String BUTTONS_ID = "buttons";
public GridWithMultiComponentRenderer() {
// basic grid setup
Grid grid = new Grid(new BeanItemContainer<>(Person.class));
grid.setSizeFull();
addComponent(grid);
// add the decorator
ComponentGridDecorator<Person> gridDecorator = new ComponentGridDecorator<>(grid, Person.class);
// generate the column which will display the components
gridDecorator.addComponentColumn(BUTTONS_ID, person -> new HorizontalLayout(
new Button("Get name", event -> Notification.show(person.getName())),
new Button("Get surname", event -> Notification.show(person.getSurname())),
new Button("Get age", event -> Notification.show(String.valueOf(person.getAge())))
));
// set column order
grid.setColumns("name", "surname", "age", BUTTONS_ID);
// add some dummy data
Random random = new Random();
for (int i = 0; i < 10; i++) {
gridDecorator.add(new Person("Name " + i, "Surname " + i, random.nextInt(99) + 1));
}
}
// POJO for simple binding
public static class Person {
private String name;
private String surname;
private int age;
public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
Result:
I need to order the list of items based on a field say starredAt
I am loading the data in the recyclerview from Realm DB using RealmRecyclerView by thorbenprimke
The field changes it value on user's action i.e when user presses star button the item should be moved to top.
For this I am just updating the starredAt field of the object.
The items are already sorted by starredAt so realm loads the updated list but it randomly adds one more item to the recyclerview.
CheatSheet.java
public class CheatSheet extends RealmObject {
#PrimaryKey
private String id;
private RealmList<Item> items;
private String title;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public RealmList<Item> getItems() {
return items;
}
public void setItems(RealmList<Item> items) {
this.items = items;
}
}
Item.java
public class Item extends RealmObject {
#PrimaryKey
private String id;
private String description;
private Date starredAt;
public Item() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getStarredAt() {
return starredAt;
}
public void setStarredAt(Date starredAt) {
this.starredAt = starredAt;
}
}
CheatSheetActivity.java
public class MainActivity extends AppCompatActivity {
RealmRecyclerView revItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setData();
}
private void setData() {
rvItems = (RealmRecyclerView) findViewById(R.id.rev_items);
RealmResults<Item> items = Realm.getDefaultInstance().where(CheatSheet.class)
.equalTo("id", "some-id").findFirst().getItems()
.where()
.findAllSorted("starredAt", Sort.DESCENDING);
ItemRealmListAdapter itemRealmListAdapter =
new ItemRealmListAdapter(this, items,
true, true);
rvItems.setAdapter(itemRealmListAdapter);
}
ItemRealmListAdapter.java
public class ItemRealmListAdapter extends RealmBasedRecyclerViewAdapter<Item,
ItemRealmListAdapter.ItemViewHolder> {
RealmResults<Item> mItems;
public ItemRealmListAdapter(Context context, RealmResults<Item> realmResults,
boolean automaticUpdate, boolean animateResults) {
super(context, realmResults, automaticUpdate, animateResults);
this.mItems = realmResults;
}
#Override
public ItemViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int i) {
return new ItemViewHolder(LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_layout_cs_text, viewGroup, false));
}
public Item getItem(int position) {
return mItems.get(position);
}
#Override
public void onBindRealmViewHolder(ItemViewHolder itemViewHolder, int position) {
itemViewHolder.txtBody.setText(getItem(position).getDescription());
if (getItem(position).getStarredAt() != null) {
itemViewHolder.imvStar.setImageResource(R.drawable.ic_star_yellow);
}
itemViewHolder.imvStar.setOnClickListener(v -> handleStarClick(v,position));
}
private void handleStarClick(View v, int position) {
if (getItem(position).getStarredAt() != null) {
((ImageView) v).setImageResource(R.drawable.ic_star);
CheatSheetStorage.unStarItem("some-id", getItem(position));
} else {
((ImageView) v).setImageResource(R.drawable.ic_star_yellow);
CheatSheetStorage.starItem("some-id", getItem(position));
}
}
public static class ItemViewHolder extends RealmViewHolder {
#Bind(R.id.txt_cheat_sheet)
TextView txtBody;
#Bind(R.id.img_star)
ImageView imvStar;
public ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
CheatSheetStorage.java
public class CheatSheetStorage {
public static void unStarItem(String cheatSheetId, Item item) {
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
CheatSheet cheatSheet = getCheatSheetById(cheatSheetId);
Item itemDB = cheatSheet.getItems().where().equalTo("id", item.getId()).findFirst();
itemDB.setStarredAt(null);
realm.commitTransaction();
}
public static void starItem(String cheatSheetId, Item item) {
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
CheatSheet cheatSheet = getCheatSheetById(cheatSheetId);
Item itemDB = cheatSheet.getItems().where().equalTo("id", item.getId()).findFirst();
itemDB.setStarredAt(new Date());
realm.commitTransaction();
}
}
Please refer following screenshots for clearer idea :
Screenshot before starring
Screenshot after starring the sixth item
#Rohan-Peshkar - You will have to provide a animateExtraColumnName value to the adapter. For the animations, the adapter keeps track of the items and since that item's id doesn't change, the list isn't updated. With an additional column (in your case that should be the starredAt column - as long as it is stored as an Integer), the diffing algorithm will detect a change and the order is updated.
For reference: https://github.com/thorbenprimke/realm-recyclerview/blob/2835a543dce20993d8f98a4f773fa0e67132ce52/library/src/main/java/io/realm/RealmBasedRecyclerViewAdapter.java#L177
You can also check out the MainActivity in the example folder. The example changes a row's text from "ABC" to "Updated ABC" and the list recognizes the change because both the primary key and the quote field are used to basically create a composite key for diffing purposes.
How do I use the JdbcTemplate.query()/queryForList() to run a query using namedParameter and store the result set into a List of 'User's?
User Class:
public class User {
String name = null;
String id = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return name;
}
public void setId(String id) {
this.id = id;
}
}
Query:
SELECT name, id FROM USERS where email=:email
I'm looking for something like:
ArrayList<User> userList = jdbcTemplate.query(sql_query,
...some_mapper..., etc);
Seems like the answer to the question is not available at one place, on the Internet. Here's what I found out:
For adding the resultset into a List<>, we can use the NamedParameterJdbcTemplate.query() function:
NamedParameterJdbcTemplate jdbcTemplate;
ArrayList<User> usersSearchResult = (ArrayList<User>) jdbcTemplate.query(
USER_LIST_TP_query,
namedParameters,
new RowMapperResultSetExtractor<User>(new UserRowMapper(), 20));
We also have to define a custom RowMapperResultSetExtractor so that JDBC can understand how to convert each row in the result set to the type User.
private class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getString("ID"));
user.setName(rs.getString("NAME"));
return user;
}
}