How to display List View Items by column, from Json - java

I am currently retrieving data from an online MySQL database and displaying it with in the application, but i have been having trouble formatting it to even a basic standard.
Code Snippet below showing the JSON Objects being retrieved and cycled through, then applied to a list view adapter.
private void showJSON(String response){
String CurrentUser="";
String Benchpress="";
String Squat="";
String Deadlift="";
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray result = jsonObject.getJSONArray(ConfigLeaderboard.JSON_ARRAY);
JSONObject leaderboards;
for(int i = 0; i<result.length(); i++) {
leaderboards = result.getJSONObject(i);
CurrentUser = leaderboards.getString(ConfigLeaderboard.KEY_CURRENTUSER);
Benchpress = leaderboards.getString(ConfigLeaderboard.KEY_BENCHPRESS);
Squat = leaderboards.getString(ConfigLeaderboard.KEY_SQUAT);
Deadlift = leaderboards.getString(ConfigLeaderboard.KEY_DEADLIFT);
dataList.add(CurrentUser + " " + Benchpress );
adapter.notifyDataSetChanged();
Log.d("JSONArray length ",result.length() + "");
}
}
catch (JSONException e) {
e.printStackTrace();
}
ListView lv = (ListView) findViewById(R.id.list);
lv.setAdapter(adapter);
ArrayAdapter<String> adapter =new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, dataList);
}
#Override
public void onClick(View v) {
getLeaderboardData();
The main thing im really stuck on is actually just obtaining a basic layout where the retrieved data is separated neatly almost like columns. Now for this i understand a custom listview adapter would be required, but would a data model also be required? Given that im retreiving data from Json would this still apply. I just feel so fustrated and stuck
Any help would be much appreciated
Thank you!

The preferred solution is a combination of the following
A custom "row" layout to replace android.R.layout.simple_list_item_1 because that will only get you a single String item, not aligned columns
A simple Java class (commonly known as a POJO), to "bind" this JSON data to that view
An Adapter that extends ArrayAdapter<Foobar> where Foobar is the name of the class from step 2
Now, you could just add tabs to your string data to simulate columns, however you can't guarantee the data will align vertically.

Related

How to delete Item from firestore in android with auto-generated document ID

I have a Firestore database with the following structure in a hierarchical form:
collection("notes") > document(currentUserId) > collection("mynotes") > document(auto-generated-key) > items...
I have added data to the Firestore as follows :
mAuth = FirebaseAuth.getInstance();
database = FirebaseFirestore.getInstance();
//here scheduleModel is a model class with constructor(String, boolean, String) with getters and
//setters for three of them
scheduleNoteModel = new ScheduleNote(noteTitle, isImp, strDate);
I have added the note item like this.
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document() //generated id automatically...
.set(scheduleNoteModel)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(getContext(), "data added ...", Toast.LENGTH_SHORT).show();
etNoteTitle.setText("");
//dismiss (hide) the bottom sheet after adding item
BottomSheetScheduleFragment.this.dismiss();
//refresh the fragment
}
});
The problem is getting that id back while deleting the item. I know there are many questions similar to this, some of them were good but I couldn't figure out to solve them. I had a look at this link solution but I wasn't able to solve
In adapter
holder.deleteNoteIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteNote(noteModel);
}
});
Method to delete
private void deleteNote(ScheduleNote note, int itemPosition, View view) {
mAuth = FirebaseAuth.getInstance();
database = FirebaseFirestore.getInstance();
//getting the doc id of auto-generated code in Firestore.
String id = database.collection("notes").document(mAuth.getUid()).collection("mynotes").document().getId();
Toast.makeText(context, "position " + itemPosition + "doc id " + id, Toast.LENGTH_SHORT).show();
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
//.document("72NMkKY73CXHVN7DFE8W") get that id automatically
.document(id)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
//notifyDataSetChanged();
Snackbar snackbar = Snackbar.make(view, "Note Deleted successfully", Snackbar.LENGTH_SHORT);
snackbar.show();
}
});
}
id in the above variable isn't matching the real id. How to get that id?
I basically want two information for this :
How to get the document Id before adding it to the Firestore so that I can attach this to my model class and later on delete based on that ID, has any solution?
Or, just get the document Id by the Model Class that I pass when clicking on the item in RecyclerView?
I actually did a lot of research but couldn't figure it out. Any quick help would be appreciated, thanks.
It doesn't seem to mee, that you are following this link solution. First of all, as also #Frank van Puffelen mentioned in his comment, "document().getId()" will always generate a brand new ID each time is called. So you should save that ID into a variable for later use, so you can delete the desired document right from the adapter. Your "ScheduleNote" class, besides the "noteTitle", "isImp", and "strDate" fields, should also contain a field called "id". So your declaration class should look like this:
class ScheduleNote {
public String noteTitle, strDate, id;
public boolean isImp;
public ScheduleNote() {}
public ScheduleNote(String noteTitle, String strDate, String id, boolean isImp) {
this.noteTitle = noteTitle;
this.strDate = strDate;
this.id = id;
this.isImp = isImp;
}
}
Now, in your particular case, the following lines of code for adding the object to Firestore will do the trick:
CollectionRefference mynotes = database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
String docId = mynotes.document().getId();
To create an object of "ScheduleNote" type, please use:
ScheduleNote scheduleNoteModel = new ScheduleNote(noteTitle, strDate, docId, isImp);
// ^
// newly added
To actually write the data to Firestore, please use:
mynotes.document(docId).set(scheduleNoteModel).addOnSuccessListener(/* ... */);
// ^
To be able to delete that document, you should use the following lines of code:
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document(id)
.delete(note.id)
.addOnSuccessListener(/* ... */);
And this is because, the following line generates again a new ID, which is not correct, as you need to use the one that was generated earlier:
String id = database.collection("notes").document(mAuth.getUid()).collection("mynotes").document().getId();
First of all add document to your collection without any data in it.
DocumentReference addedDocRef =database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document();
log.i("Added document with ID: " + addedDocRef.getId());
Then add document id to your model class for later use.
Now, set data for document using your model class.
addedDocRef.set(scheduleNoteModel)

Scrolling the listview to position of the newly added item

I have a custom adapter with a listview. I query the items from SQL Server and display them as a list using my listview. I have item click listener on my list view in order to get the item position.
public void getData() {
String query = "SELECT * FROM Table";
List<Map<String, String>> data = new ArrayList<>();
data = filterData(query);
adapter = new ContactListAdapter(this, data, R.layout.items, from, to);
listView.setAdapter(adapter);
listView.invalidateViews();
listView.setOnItemClickListener((adapterView, view, i, l) -> {
HashMap<String, String> retreive = (HashMap<String, String>) adapterView.getAdapter().getItem(i);
callerID = retreive.get("CallerDetailID");
.
.
});
}
I store the values using hashmap strings in a list as follows.
// filter the contact details from sql server
List<Map<String, String>> filterData(String query) {
List<Map<String, String>> contact_details = new ArrayList<>();
try {
connect = connectionClass.CONN(); // Connect to database
Statement stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
Map<String, String> datanum = new HashMap<>();
datanum.put("CallerDetailID", rs.getString("CallerID"));
.
.
.
contact_details.add(datanum);
}
} catch (Exception e) {
e.printStackTrace();
}
return contact_details;
}
I am aware that I can get the items to the position by clicking on it (since I already use setOnItemClickListener). But my question here is how can I scroll to the newly added item's position in my list view, without clicking the item?
Once I get the position of the item, I can use one of the following methods in the listview to scroll.
listView.smoothScrollToPosition();
listView.smoothScrollToPosition();
listView.smoothScrollToPositionFromTop();
Is it possible to get the item's to position without clicking on the item in the listview? Any ideas folks.
To achieve the behaviour you need to add a property to scroll listview automatically.
android:transcriptMode="alwaysScroll"
You just have to call notifyDataSetChanged() and your list will be auto scrolled.

Accessing SQLite database values in an activity android

I am working on a book app and I save the book contents in SQLite database which I placed in my assets folder in Android Studio. But now I want to retrieve the values in the database in an activity in my app, but with the method I have seen online I can only retrieve one value from the database.
Please bear with me because I don't know if I'm properly explaining what I want but let me show the code so I can explain better.
listItem = new ArrayList<>();
database = new Database(this);
// song = String.valueOf(database.getChapter());
SQLiteDbHelper dbHelper = new SQLiteDbHelper(this);
dbHelper.openDatabase();
modelArrayList = dbHelper.getDetails();
adapter = new SongAdapter(modelArrayList);
chapFind = findViewById(R.id.chap_find);
chapGo = findViewById(R.id.chap_go);
String tokenID = FirebaseInstanceId.getInstance().getToken();
Model count = modelArrayList.get(0);
final String chap = String.valueOf(count.getIds());
Toast.makeText(MainActivity.this,chap,Toast.LENGTH_LONG).show();
mDatabasse = FirebaseDatabase.getInstance().getReference().child("Token");
chapGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String num = chapFind.getText().toString();
if (num.equals(chap)){
Toast.makeText(MainActivity.this,"very good!",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(MainActivity.this,"very bad",Toast.LENGTH_LONG).show();
}
}
});
}
So what I am trying to do with this code - is to get user input of the chapter they would like to read. Then - check if that chapter exists in the database and if it does app will send user to another activity where it will fully display the content of that chapter

android parse query only gets newest data on the column

final String name = getIntent().getStringExtra("name");
ParseQuery<ParseObject> query = ParseQuery.getQuery("Info");
query.whereEqualTo("user", name);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null){
ArrayList<String> barbers = new ArrayList<String>();
for (ParseObject object : objects){
barbers.add(String.valueOf(object.get("times")));
}
ArrayAdapter arrayAdaptar = new ArrayAdapter<String>(Barbers.this, android.R.layout.simple_list_item_1, barbers);
list.setAdapter(arrayAdaptar);
}
}
});
I am making a app where people put times and then other people can see all their times when they click their name. I have made this query to get all the times from that certain person that they clicked on but when the app runs it only gets me the newest time and if the person that you clicked is not the newest will not retrieve anything. Thank you, here are some screenshots of my Parse Server and of the query.

Is it possible to update a Listview on real-time when we use Json?

I'm a Newbie, so, there are a lot of things that I don't know.
I'm building my first application, using PHP and Java, and my
Database is allocated on Phpmyadmin.
To get the data that I want, I have to create a PHP Query, and output
everything using Json. To get the Json Data I use Java.
I have been searching about my question for hours, and unfortunately,
I couldn't find a specific way to what I want, in my situation. I
would like to update my ListView automatically when a new record is
inserted into my Database.
Lets imagine that you are watching a Listview, and when the owner
from the application inserts a new record on the table that shows the
Listview data, automatically the Listview shows a new record.
My problem is that I am using Json to get the Data, and I can't
change that. And I would like to find a solution for that.
So, I would like to know if it is possible or not to do that. I will
post my full code here:
Json Tags - Calling the URL and the Json Tags here:
public class ListUsersActivity extends ListActivity {
private ProgressDialog pDialog;
private ImageView img;
// URL to get contacts JSON
private static String url = "http://192.168.1.67/example/db_config.php";
// JSON Node names
private static final String TAG_CONTACTS = "contacts";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_IMAGE = "pic_url";
private static final String TAG_USERID = "user_id";
private static final String TAG_BIRTH_DATE = "birth_date";
// contacts JSONArray
JSONArray contacts = null;
// Hashmap for ListView
ArrayList<HashMap<String, String>> contactList;
OnCreate - Calling the Asynctask function, and creating a new arraylist for my Contact list
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lobby);
contactList = new ArrayList<HashMap<String, String>>();
ListView lv = getListView();
// Calling async task to get json
new GetContacts().execute();
}
Asynctask - Getting all the Data json
private class GetContacts extends AsyncTask {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(ListUsersActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
NewSession app = (NewSession) getApplication();
String username = app.getUsername();
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url + "?id=" + username, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
contacts = jsonObj.getJSONArray(TAG_CONTACTS);
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
String user_id = c.getString(TAG_USERID);
String birth_date = c.getString(TAG_BIRTH_DATE);
String pic_url_get = c.getString(TAG_IMAGE);
HashMap<String, String> contact = new HashMap<String, String>();
// adding each child node to HashMap key => value
contact.put(TAG_ID, id);
contact.put(TAG_USERID, user_id);
contact.put(TAG_BIRTH_DATE, getAge(birth_date) + " anos");
contact.put(TAG_IMAGE, "http://*****/images/" + user_id + "/" + pic_url_get);
// adding contact to contact list
contactList.add(contact);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
Calling the adapter
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
costumeadapter adapter = new costumeadapter(
ListUsersActivity.this,
contactList,
R.layout.list_row,
new String[]{ TAG_NAME, TAG_BIRTH_DATE, TAG_USERID},
new int[]{ R.id.name,R.id.email, R.id.id });
setListAdapter(adapter);
}
}
I tried so far
To build a Timer and refresh my GetContacts calling class every
second, but it doesn't work because the user is not able to scroll, and the application crashes
I tried to use notifyDataSetChanged but I didn't work because I dont know exactly how can i implement that.
I hope you guys can help me.
Thanks.
Of course it is possible.
To build a Timer and refresh my GetContacts calling class every
second, but it doesn't work because the user is not able to scroll,
and the application crashes
Because you're doing it on the main thread. Do it in an AsyncTask or a separate thread, that should work.
I tried to use notifyDataSetChanged but I didn't work because I dont
know exactly how can i implement that.
It's simple, you call it in the adapter: adapter.notifydatasetchanged() after you update it (more detail here).
Just use
adapter.notifydatasetchanged()
You have to add it after setListAdapter() like:
setListAdapter(adapter);
adapter.notifydatasetchanged();

Categories