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.
Related
I'm building a book reader app and currently having some issues on how to move to next or previous chapter.
The fragment that is in charge of showing a list of chapter (basically a ListView). I capture the item with onItemClick:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity().getApplicationContext(),ReaderActivity.class);
intent.putExtra("name",adapter.getItem(i).getName());
intent.putExtra("url",adapter.getItem(i).getUrl());
startActivity(intent);
}
});
It will start the ReaderActivity and display the content of the book. Now the ReaderActivity has 2 buttons for moving to next/previous chapter. How can I get the data (the name and url) from the ListView?
At the moment I'm thinking of two methods:
Calling finish() on ReaderActivity and override the onDestroy() method to call a method to get the next/previous data in the fragment that holds the ListView.
Passing the whole ArrayList of chapters to ReaderActivity so it can retrieve the item it wants (probably not a good solution since there are too many chapters).
Is there a better way?
There are way to many ways to get the best one.
Some of them:
Use your Application.java to share in-memory data (data stores) from any place. Example:
public final Application extends android.app.Application {
private List<Chapter> chapters;
public void setChapters(List<Chapter> chapters) {
this.chapters = chapters != null ? chapters : Collections.<Chapter>epmtyList();
}
public List<Chapter> get Chapters() {
return chapters;
}
}
// from any place which has context (or is context)
List<Chapter> chapters = ((Application) getContext().getApplicationContext()).getChapters();
Make your list a static member with a public static getter and then reference is from your ReaderActivity
public final ApplicationActivity extends Activity {
private static List<Chapter> chapters;
....
public static List<Chapter> getChapters() {
return chapters;
}
Store the list in shared preferences so any activity can reference it
Include the list of chapters in your intent extras and pass it to your ReaderActivity
I think your ReaderActivity needs to deal with the whole book rather a single chapter. Which means approach (4) is most likely a good candidate.
I would put the list data in the Application class (or another singleton), and then the ReaderActivity would be able to query it for the next chapter. Actually then it could just get the details of the next chapter and update its contents accordingly, without needing to create a new activity at all.
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
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.
I'm sorting an array of custom objects (ListData[]) on two fields. I want it to be sorted by theme, and them by name. I thought i made a nice comparator in the custom object class and that i could use Arrays.sort(ld) to make my code working and sorting my array. But apparently im doing something wrong...
my custom object:
public class ListData implements Comparable<ListData>{
public int venueID;
public String name;
public String photoUrl;
public String tip;
public String theme;
#Override
public int compareTo(ListData ld0) {
return this.venueID- ld0.venueID;
}
public static Comparator<ListData> ListDataThemeAndNameComparator = new Comparator<ListData>() {
#Override
public int compare(ListData ld1, ListData ld2) {
String compareTheme1 = ld1.theme.toUpperCase();
String compareTheme2= ld2.theme.toUpperCase();
String compareName1 = ld1.name.toUpperCase();
String compareName2= ld2.name.toUpperCase();
//ascending
int comp = compareTheme1.compareTo(compareTheme2); // comp themes
if(comp==0){ // same theme
comp= compareName1.compareTo(compareName2); // compare names
}
return comp;
}
};
}
And in my main activity i have:
ListData ld[]= new ListData[jsonResponse.size()];
(some code filling my ListData array)
Arrays.sort(ld, ListData.ListDataThemeAndNameComparator); // compare by theme and then by name
Does anyone know what i'm doing wrong?
I edited my code But still it fails, now on a nullpointerexception on the compareTheme1 = ld1.theme.toUpperCase();. But i am sure my array is not empty, i logged it the line before sorting it and its filled with about 500 items.
Your ListData object should implements Comparable not Comparator interface.
EDIT:
To make things clear, you can sort an array by Array.sort(). To make custom sort, you can specify your comparator in Array.sort(), if you don't do that, array will be sorted in natural order which you can define by implementing Comparable interface. So you have two options how to custom sort:
by using custom comparator and specifying it in Array.sort()
by implementing Comparable interface to your items
I would suggest you to go with implementing Comparable. You save memory by not creating new comparator objects and Comparator is useful if you are comparing objects of different types which is not your case.
How can i read the categories education and work in a android ListView? Now on clicking any category its childs Google,IBM,etc. are shown in a new screen. How can it be implemented?
You have to follow the following steps to get your work done
Step-1 You need to parse the xml. see http://xmlpull.org/v1/src/java/samples/MyXmlPullApp.java
Step-2 Create a bean class for Category. means all the category related data will be stored in that bean class
Step-3 Create an arraylist of that bean class
Step-4 Create a list view using that arraylist ( the list view will display only name of categories)
Step-5 Implement on itemclik listener on the list view. get the position. retrieve the data pass to the intent call second activity
Step-6 In the second activity create a listview and display the data whatever is passed by first activity
NetworkBean
public class NetWorkBean {
String name;
int id;
NetWorkBean(String name, int id){
this.name = name;
this.id = id;
}
public String getNetWorkName(){
return name;
}
public int getNetWorkId(){
return id;
}
}
CategoryBean
import java.util.ArrayList;
public class CategoryBean {
String name;
ArrayList<NetWorkBean> networkList;
public CategoryBean(String name, ArrayList<NetWorkBean> networkList){
this.name = name;
this.networkList = networkList;
}
public String getNetWorkName(){
return name;
}
public ArrayList<NetWorkBean> getNetWorkList(){
return networkList;
}
}
you can see this
http://www.androidpeople.com/android-xml-parsing-tutorial-%E2%80%93-using-domparser
After parsing the data set it to the list view.Then in the list onclick event implement
what you need.You can call an another activity and sending the corresponding address in a
bundle then retrieving that on the activity you can show in webview