Ok been stuck on this for literally weeks, sorry for long question.
Using Parse, making a workout app for Android.
Database tables and columns that are relevant to my problem are:
Exercises
ID| name | description | Musclegroup
Workouts
ID| workoutName| userID
WorkoutExercises (basically a join table between the two)
ID| workoutID (pointer) | exerciseID (pointer)
So a user will be able to create a workout and add in the exercises they want.
So far I've already done:
User can go to category, browse the muscle group, view the exercises in that group
signup/login/logout, update profile
list the current workouts (not the exercises in them) -
I have just entered some exercises into a workout on the db as have gotten stuck on querying current exercises in that workout before worrying about inserting new ones.
The problem:
I'm trying to do a nested query to get the exercise name so once a user clicks Eg. Back Workout it should bring up a list Eg. Deadlift, Rows, Chin ups
So basically in SQL I want to:
Select name
from Exercises
where ID in (select exerciseID from workoutexercises where WorkoutID=xxxx)
Things i'm struggling on:
Making a nested query for a pointer, from what I have read on the net I need to use query.include("exerciseID"); which will tell Parse to include a full Exercise item that I can then use to query? Correct me if wrong? Code below - have I done it correctly?
I've learnt from and been using methods from: http://www.michaelevans.org/blog/2013/08/14/tutorial-building-an-android-to-do-list-app-using-parse/ where query data is put into a custom adapter that lists the data. It uses getters
and setters to save/retrieve String/int values, do I still use the getters for getting a string from within a pointer?
EG.
public String getName()
{
return getString("name");
}
As in once i'm "through" that pointer and in the Exercise table im assuming i'm still just getting the String name value as oppose to getting a ParseObject?
Now so far I have been able to get the custom adapter to put 2 horizontal bars across the screen that shows it knows i've put 3 items in workoutExercises but just not bringing up the text from Exercise name that I need from the nested query
Have a look at my screenshots to see what I mean.
Thank you very much for the help in advance.
Query so far:
public void getcurrentExercisesInWorkout() {
//set progress bar
setProgressBarIndeterminateVisibility(true);
ParseQuery<WorkoutExercises> query = ParseQuery.getQuery("WorkoutExercises");
query.include("exerciseId");
query.whereEqualTo("workoutId", mWorkoutId);
query.findInBackground(new FindCallback<WorkoutExercises>() {
#Override
public void done(List<WorkoutExercises> workoutExercises, ParseException error) {
if (workoutExercises != null) {
mWorkoutExercisesAdapter.clear();
mWorkoutExercisesAdapter.addAll(workoutExercises);
} else {
Log.d("error", error.getMessage());
}
}
});
//stop progress bar
setProgressBarIndeterminateVisibility(false);
}
Custom list Adapter:
//constructor - get current state of parsed object and list of objects retrieved from workout
public WorkoutExercisesAdapter(Context context, List<WorkoutExercises> objects) {
super(context, R.layout.row_item, objects);
this.mContext = context;
this.mWorkoutExercises = objects;
}
public View getView(int position, View convertView, ViewGroup parent)
{
//put each item into the listview
if(convertView == null)
{
LayoutInflater mLayoutInflater = LayoutInflater.from(mContext);
convertView = mLayoutInflater.inflate(R.layout.row_item,null);
}
WorkoutExercises workoutExercises = mWorkoutExercises.get(position);
TextView nameView = (TextView) convertView.findViewById(R.id.row_name);
//this just calls a String getter - which isn't working - need it to get the Exercise name from within the pointer
nameView.setText(workoutExercises.getWorkoutExercise());
return convertView;
}
WorkoutExercises(stores the getters)
#ParseClassName("WorkoutExercises")
public class WorkoutExercises extends ParseObject {
public String exName;
public WorkoutExercises()
{
}
public String getWorkoutExercise()
{
return getString("name");
}
}
Running Android Studio in Debug mode I can literally see the data I am trying to put into the text field (see screenshot - how can I grab that value? See screenshot below
NOW WORKING - THE RESULT!
First, alter the WorkoutExercises object:
#ParseClassName("WorkoutExercises")
public class WorkoutExercises extends ParseObject {
//public String exName;
public static final String workoutID = "workoutID"
public static final String exerciseID = "exerciseID"
public Exercises getWorkoutExercise() {
return (Exercises)getParseObject(exerciseID);
}
public WorkoutExercises()
{
// not sure if it is allowed to define your own constructor?
// just a note
}
// WorkoutExercises does not have a 'name' col
//public String getWorkoutExercise()
//{
// return getString("name");
//}
}
I assume that Exercises at least contains something like:
#ParseClassName("Exercises")
public class Exercises extends ParseObject {
public static final String name = "name"
public String getName()
{
return getString(name);
}
}
Now, with the query on WorkoutExercises including workoutID, the Exercises object will be populated in the fetched query. This means you can do the following to get the name of the exercises object:
// workoutExercises returned from a query including workoutID
Exercises exercise = workoutExercises.getWorkoutExercise();
String name = exercise.getName();
// if Exercises has getters for description and Musclegroup
String description = exercise.getDescription();
String musclegroup= exercise.getMusclegroup();
Hope this sheds some light on the problem
Related
I'm writing Android app with Room Database. My database contains GroupVc entity with such code:
#Entity
public class GroupVc {
#ColumnInfo(name = "language")
private String language;
#NonNull
#PrimaryKey
#ColumnInfo(name = "name_group")
private String nameGroup;
public GroupVc(String language, String nameGroup) {
this.language = language;
this.nameGroup = nameGroup;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
#NonNull
public String getNameGroup() {
return nameGroup;
}
#NonNull
public void setNameGroup(String nameGroup) {
this.nameGroup = nameGroup;
}
}
As you can see my entity class contains two columns where nameGroup is my PrimaryKey. In my application I want to let the user to see the full list of groups and change the name of Group DialogFragments by entering new Group's names. To implement such function I've created the next DAO #Query method:
#Dao
public interface GroupVcDao {
#Query("UPDATE groupvc SET name_group= :newName WHERE name_group= :currentName")
void updateNameOfGroup(String currentName, String newName);
}
In this QUERY I want to change name of GroupVc by getting the existing name of GroupVc from RecyclerView (currentName param) and applying new one from DialogFragment (newName param).
My problem is that this QUERY doesn't bring any effect and doesn't update the name. Although I don't get any errors or exceptions. So I need to know: does such QUERY correct? Is it possible to write Update queries where primary key is changeable value and condition at the same time?
Here is the link to my complete project on GitHub
https://github.com/LAHomieJob/VocaNote
I can't be sure, but my guess would be that your query is working, but since you're changing the primary key your database is left with an instance of the old object as well as the new one. Try checking to see if you have an object with both the old name_group and the new name_group. Also if you're looking to allow your users to change the group name, it may make sense to move your primary key to a UUID or some other key that doesn't change.
I have the following RealmObject:
public class City extends RealmObject {
private String cityId;
private RealmList<Street> streets;
public String getId() {
return cityId;
}
public void setCityId(String cityId) {
this.cityId = cityId;
}
public RealmList<Street> getStreets() {
return streets;
}
public void setStreets(RealmList<Street> streets) {
this.streets = streets;
}
}
Now having a cityId I need to query streets of particular city. How to do that? What I did try was:
Realm.getInstance(context).where(City.class).equalTo("cityId", someCityId, false)
.findFirst().getStreets().where().findAll()
But this leads into an Exception. I need to display streets in a ListView implementing filtering so I need streets to be RealmResults to use RealmBaseAdapter<Street>.
The proper way would be to have an open Realm instance either opened in your Activity in onCreate() and closed in onDestroy(), or in your custom application class.
Then you can use this realm instance to query the realm
City city = realm.where(City.class).equalTo("cityId", cityId).findFirst();
Then you can access the RealmList<T> like any other list
RealmList<Street> streets = city.getStreets();
Then you can use a recyclerview to get the view for a given index within your streets list.
I'm pretty new to the Android developer. I'm currently making an simple message app. so i want to store all the text message I received from node server. I don't really now how should i do this.
the msg I received from node server is JSONObject like:
{"name":"XX", "id":"XX","message":"xxxxxxxx"}
and I'm using a Custom ArrayAdepter to display the text:
public class ChatArrayAdapter extends ArrayAdapter<Text> {
private TextView text,avatar;
private List<Text> msgcontx = new ArrayList<Text>();
private LinearLayout wrapper;
#Override
public void add(Textobject){
msgcontx.add(object);
super.add(object);
}
public ChatArrayAdapter(Context context,int textViewResourceId) {
super(context, textViewResourceId);
}
public int getCount(){
return this.msgcontx.size();
}
public Text getItem(int index){
return this.msgcontx.get(index);
}
public View getView(int position,View convertView,ViewGroup parent){
View row = convertView;
if(row == null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.chat_listview, parent,false);
}
wrapper = (LinearLayout)row.findViewById(R.id.wrapper);
Text comment = getItem(position);
avatar = (TextView)row.findViewById(R.id.avatar);
avatar.setText(comment.userID);
avatar.setVisibility(comment.left? View.VISIBLE: View.GONE);
text = (TextView)row.findViewById(R.id.comment);
text.setText(comment.comment);
// chat background to be changed
text.setBackgroundResource(comment.left ? R.drawable.bg_chat_recipient : R.drawable.bg_chat_sender );
wrapper.setGravity(comment.left? Gravity.START : Gravity.END);
return row;
}
public Bitmap decodeToBitmap(byte[] decodedByte){
return BitmapFactory.decodeByteArray(decodedByte, 0,decodedByte.length );
}
}
now I don't know how should I store those msg I received from node server at local storage, and when i open the app, I want to also display the msg history.
should I use SQL? but how should I store the msg? put them in different rows?
I know it might be a dumb question, But I really don't know how to store the msg to local storage and read them again.
Anyone can give a brief introduction? Thanks a lot!
You should use some kind of database.I recommend an sql db with an orm - it lets you create a database based on classes and eliminates the need in ton of sql.
I like active android, but also take a look at sugar orm.
You should have a messages table, and each row in the table will be a message.In an orm you define the message using a class. example code (using ActiveAndroid orm):
#Table(name="Messages")
class Message extends Model {
String name;
String id;
String message;
//the empty consructor is required by active android
public Message(){
super();
}
}
to actually enter the messages into the databse you will need to parse the json and create Messages objects from them, then save them.To parse the json into the Message object you can use Gson or logan square.
I have a ListView, actually generated by parsing a XML file downloaded from Internet.
This XML file contains data about a person: IdNumber, Name, Age, PhotoURL, Birthday, Phone numbers, Email account, etc.
I get all the XML data when generating the ListView, but on each row I show some values of the person (not all), just name, age, photo (from the PhotoURL) and email.
I would like to get the "IdNumber" to parse it to the Activity that shows all the info, this activity should read the "IdNumber", get all the data of only that person and show it.
How can I parse a value that I'm not using on my ListView?
Thanks in advance,
Herni
For each row in the listView create an Object with all the fields you've originally parsed.
You will create a model that like this:
public class Person
{
String idNumber,Name,Email;
public void SetIdNumber(String p_value)
{
this.idNumber = p_value;
}
public void SetName(String p_value)
{
this.Name= p_value;
}
public void SetEmail(String p_value)
{
this.Email= p_value;
}
//Get Methods
public String GetIdNumber()
{
return idNumber;
}
public String GetName()
{
return Name;
}
public String GetEmail()
{
return Email;
}
When you parse your xml you will create an ArrayList list; and fill after the 'list' you will use this everywhere you want.
For example when you click your first item of your listview you could ;
Person p = list.get(position that clicked your listview);
Now you will use your Person model. This is simple object oriant man.
When the user clicks on a button, a new ListFragment is displayed. This fragment will contain the list of the albums with their associated Artist's name.
I've created my own class AlbumItem (String name, String artist) with name being the Album's title and artist the corresponding artist name :
public class AlbumItem {
private String AlbumName;
private String AlbumArtist;
public AlbumItem(){
}
public AlbumItem(String name, String artist){
this.AlbumName = name;
this.AlbumArtist = artist;
}
public String getAlbumName() {
return AlbumName;
}
public void setAlbumName(String AlbumName) {
this.AlbumName = AlbumName;
}
public String getAlbumArtist() {
return AlbumArtist;
}
public void setAlbumArtist(String AlbumArtist) {
this.AlbumArtist = AlbumArtist;
}
}
Then I wrote my custom adapter which associates the Album's name and Artist's name with the correct TextView in my ListView's row.
So then I can declare an ArrayList of AlbumItem and fill it like this :
ArrayList<AlbumItem> arrayList;
arrayList.add(new AlbumItem ("Album's title", "Artist");
Now I have few questions :
1) Am I going the appropriate way ? I've always learnt to fill listviews like that and I'm very comfortable using this technique (Custom Item class + ArrayList + CustomAdapter), but I'm doing a Music player and I'd like to query the list of Albums and update the listview asynchronously so that the UI is not blocked. I don't know if it is possible to do it by loading data in a ArrayList the way I do it.
2) How to fill up this ArrayList asynchronously ? With LoaderManager/CursorLoader or Asyntask or something else ? (I'm targeting Android 4.0)
Thanks for your advice.
CursorLoader is a convenient way of loading your list, especially if you get the data from a database or another local data source. If your data comes from the network, it may be easier to get the data with an asynctask and load it in the list adapter. If you are familiar with one of these, use that.