Problem with Parcel // ArrayList - java

I am currently trying to pass an ArrayList of objects from one activity to another. After much searching, I saw that you could pass things as parcels. Here is what I ended up doing:
public class PartsList extends ArrayList<Part> implements Parcelable {
public PartsList(){
}
public PartsList(Parcel in){
}
#SuppressWarnings("unchecked")
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public PartsList createFromParcel(Parcel in) {
return new PartsList(in);
}
public Object[] newArray(int arg0) {
return null;
}
};
private void readFromParcel(Parcel in) {
this.clear();
// read the list size
int size = in.readInt();
// order of the in.readString is fundamental
// it must be ordered as it is in the Part.java file
for (int i = 0; i < size; i++) {
Part p = new Part();
p.setDesc(in.readString());
p.setItemNmbr(in.readString());
p.setPrice(new BigDecimal(in.readString()));
this.add(p);
}
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel arg0, int arg1) {
int size = this.size();
arg0.writeInt(size);
for (int i = 0; i < size; i++) {
Part p = this.get(i);
arg0.writeString(p.getDesc());
arg0.writeString(p.getItemNmbr());
arg0.writeString(p.getPrice().toString());
}
}
}
And here is the part Object:
public class Part implements Parcelable{
private String desc;
private String itemNmbr;
private BigDecimal price;
public Part(){
}
public Part(String i, String d, BigDecimal p){
this.desc = d;
this.itemNmbr = i;
this.price = p;
}
It also has getters/setters of course.
This is where the list is created:
for (String i : tempList){
Matcher matcher = pattern.matcher(i);
while (matcher.find()){
// getting matches
String desc = matcher.group(6);
String item = matcher.group(9);
BigDecimal price = new BigDecimal(matcher.group(12).toString());
// adding the new part to the parts list
parts.add(new Part(item, desc, price));
}
}
Now, here is where it is received:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get extras (list)
Bundle b = getIntent().getExtras();
parts = b.getParcelable("parts");
// Part[] PARTS = (Part[]) parts.toArray();
final Part[] PARTS = new Part[] {
new Part("desc", "item id", new BigDecimal(0))
};
final String[] COUNTRIES = new String[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra"
};
setListAdapter(new ArrayAdapter<Part>(this, R.layout.list_item, PARTS));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
}
If I don't use the parcel, and just use the array - it works fine. I commented out my test list and it worked fine, otherwise it crashed.
// parts.add(new Part("desc", "item id", new BigDecimal(0)));
// parts.add(new Part("desc2", "item id2", new BigDecimal(1)));
// parts.add(new Part("desc3", "item id3", new BigDecimal(2)));
// create a new bundle
Bundle b = new Bundle();
// put the list into a parcel
b.putParcelable("parts", parts);
Intent i = new Intent(SearchActivity.this, Results.class);
// put the bundle into the intent
i.putExtras(b);
startActivity(i);
Did I do something wrong with the implementation of the Parcel? I can't figure this out. If anyone could help me ASAP - that would be amazing.

In your implementation of Parcelable.Creator, this looks sketchy:
public Object[] newArray(int arg0) {
return null;
}
I believe it should be:
public Object[] newArray(int arg0) {
return new PartsList[arg0];
}
You also need to define your CREATOR object for Part if you're going to declare it to implement Parcelable (although I'm not sure why it needs to).

Related

How do I iterate through an ArrayList of custom objects from Intent and add them into LinearLayout?

I have an ArrayList of custom FlightData objects within the intent. I load the intent and get the arraylist as null, and the foreach loop also forces me to use Object as type.
Saving arraylist into intent:
intent.putParcelableArrayListExtra("FlightDataList", (ArrayList<? extends Parcelable>) flightDataList);
Loading of intent:
Intent intent = getIntent();
LinearLayout layout_datasheet = findViewById(R.id.layout_datasheet);
List flightDataList = intent.getParcelableArrayListExtra("FlightDataList");
if (flightDataList == null){
Log.d("flightDataList_size", "FlightDataList is null"); // this fires
}
assert flightDataList != null;
for (Object data : flightDataList){
data = (FlightData) data; // items in list are of type FlightData
TextView tv = new TextView(this);
tv.setText(data.toString());
layout_datasheet.addView(tv);
}
My custom class' parcelable functions (x,y,time, has getters-setters):
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeDouble(x);
dest.writeDouble(y);
dest.writeDouble(time);
}
public static final Creator<FlightData> CREATOR = new Creator<FlightData>() {
#Override
public FlightData createFromParcel(Parcel in) {
return new FlightData(in);
}
#Override
public FlightData[] newArray(int size) {
return new FlightData[size];
}
};
1.First Implement Parceable in your FlightData object model / pojo / class
2.val flightDataList= ArrayList<FlightData>()
3.val args = Bundle()
4.args.putParcelableArrayList("FlightDataList", flightDataList)
5.intent.putExtra(args)
Then to get list
val flightDataList = context.getIntent().getExtras().getParcelableArrayList("FlightDataList")
I doubt that you have implemented Parcable in FlightData
https://medium.com/techmacademy/how-to-implement-and-use-a-parcelable-class-in-android-part-1-28cca73fc2d1
It should work. The only thing that I am missing in your example is the constructor. It could explain the null your are getting.
Try adding this constructor for FlightData
public FlightData(Parcel in) {
x = in.readDouble();
y = in.readDouble();
time = in.readDouble();
}
did you try creating a datastructure that implements parcelable?
public class flightDataList implements Parcelable{
String dataThingyString;
int dataThingyInt;
public flightDataList(String dataThingyString, int dataThingyInt){
this.dataThingyString = dataThingyString;
this.dataThingyInt = dataThingyInt;
}
public flightDataList(Parcle in){
this.dataThingyString = in.readString();
this.dataThingyInt = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags){
dest.writeString(dataThingyString);
dest.writeInt(dataThingyInt);
}
public static final Creator<flightDataList> CREATOR = new Creator<flightDataList>(){
#Override
public flightDataList createFromParcel(Parcel source){
return new flightDataList(source);
}
#Override
public flightDataList[] newArray(int size){
return new flightDataList[size];
}
}
public void setdataThingyString(String stringData){
this.dataThingyString = stringData;
}
public void setdataThingyInt(int intData){
this.dataThingyInt = intData;
}
public String getdataThingyString(){
return dataThingyString;
}
public int getdataThingyInt(){
return dataThingyInt;
}
#Override
public int describeContents(){
return 0;
}
}

ParcelableArraylist may produce nullpointerexception in fragment

I want to pass ArrayList<Palatte_Model> from one Activity to another fragment. I am using ParcelableArraylist. Here I attached my code
public class Palette_Model implements Parcelable{
public String data_format_value;
public int data_format_id;
public Palette_Model(String data_format_value, int data_format_id) {
this.data_format_value = data_format_value;
this.data_format_id = data_format_id;
}
public String getData_format_value() {
return data_format_value;
}
public void setData_format_value(String data_format_value) {
this.data_format_value = data_format_value;
}
public int getData_format_id() {
return data_format_id;
}
public void setData_format_id(int data_format_id) {
this.data_format_id = data_format_id;
}
protected Palette_Model(Parcel in) {
data_format_value = in.readString();
data_format_id = in.readInt();
}
#Override
public int describeContents() {
return this.hashCode();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(data_format_value);
dest.writeInt(data_format_id);
}
public void readfromParcel(Parcel source){
data_format_id = source.readInt();
data_format_value = source.readString();
}
public static final Creator<Palette_Model> CREATOR = new Creator<Palette_Model>() {
#Override
public Palette_Model createFromParcel(Parcel in) {
return new Palette_Model(in);
}
#Override
public Palette_Model[] newArray(int size) {
return new Palette_Model[size];
}
};
}
here i attached my activity class code. to send arraylist to fragment
Platte_fragment dFragment = new Platte_fragment();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("arraylist", strQuestion);
dFragment.setArguments(bundle);
// dFragment.show(fragmentManager, "array list");
FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
fts.replace(R.id.questContFragId, dFragment);
fts.addToBackStack(dFragment.getClass().getSimpleName());
fts.commit();
here I mentioned my fragment class code:
I fetch the ArrayList from Activity. it shows a null value
ArrayList<Palette_Model> strQuestion ;
strQuestion = new ArrayList<>();
try {
Bundle bundle = this.getArguments();
strQuestion = bundle.getParcelableArrayList("arraylist");
}catch (NullPointerException e){
Log.e("er",e.getMessage());
}
The shown method may produce NullpointerException.
I had a similar problem. After some research, I found out somewhere in my code ArrayList<Type> list is pointing to nothing(NullpointerException).
What helped me was to check if Bundle extras is null:
ArrayList<Category> categories = new ArrayList<Category>(); // you initialize it here
Bundle extras = getIntent().getExtras();
if (extras != null) {
categories = extras.getParcelableArrayList("categories");
}
So if retrieved data is null it won't attach null pointer to ArrayList.
Check this link for more info about NullPointerException

Using SharedPreferences with for loop

To newcomers reading this, skip down to the part where I stop trying to use the SharedPreferences. It could have worked but apparently Gson started throwing security exceptions so I needed to start using intents. I'm still clueless.
I'm trying to save an arraylist of objects into a SharedPreferences file, by storing all of the object variables in the file. Here is some of the code exhibiting that.
SharedPreferences.Editor editor = getSharedPreferences(prefName, MODE_PRIVATE).edit();
editor.putInt("lorBucks", lorandBucks[0]);
editor.commit();
//But wait there's more!
SharedPreferences.Editor editor2 = getSharedPreferences("BoughtStuff", MODE_PRIVATE).edit();
System.out.println("IS THIS THE CULPRIT: BOUGHTITEMS SIZE: " + boughtItems.size());
editor2.putInt("Items Amount", boughtItems.size());
editor2.apply();
for(int i = 0; i<boughtItems.size(); i++) {
editor2.putString(Integer.toString(i) + " name", boughtItems.get(i).name);
editor2.putInt(Integer.toString(i) + " price", boughtItems.get(i).price);
editor2.putString(Integer.toString(i) + " image", boughtItems.get(i).imageName);
}
editor2.commit();
}
Now, this code obviously leaves out a lot of the action, but the important part is how it is saving values into the file. In a for(i) loop, it goes through an array of objects to save their variables under different identifiers.
Some of this code looks messy I know, but that's because of all of the debugging I've been doing trying to sort this problem out.
Now, here is an example of how I try to call these values:
//Loading and Creating Bought Items
SharedPreferences sps = getSharedPreferences("BoughtStuff", MODE_PRIVATE);
for(int i = 0; i<sps.getInt("Items Amount", 0); i++){
System.out.println("Items Amount: " + sps.getInt("Items Amount", 0));
boughtItems.add(new StoreItem(sps.getInt(Integer.toString(i) + " price", -1), sps.getString(Integer.toString(i) + " name", " "), sps.getString(Integer.toString(i) + " image", " "), layout, this));
System.out.println(sps.getString("0 name", "DAMNIT!!"));
System.out.println(boughtItems.get(i).name);
System.out.println("NUMBER OF BOUGHT ITEMS: " + boughtItems.size());
}
So I'm pretty screwed here, because somewhere along the way all of those values got lost (I've tried to display the object using toString()). But this is the soft blow, the entire app manages to crash at a later portion, when I'm actually calling these values into action. Here:
#Override
public void onResume(){
super.onResume();
showItems();
}
The showItems method:
public void showItems(){
for(int i = 0; i<boughtItems.size(); i++){
boughtItems.get(i).setUpShop();
//final StoreItem[] stores = new StoreItem[1];
// stores[0] = boughtItems.get(i);
// final int[] c = new int[1];
// boughtItems.get(i).getIb().setOnClickListener(new View.OnClickListener(){
// #Override
// public void onClick(View v){
// c[0] = 1;
// }
// });
// if(c[0] == 1){
// boughtItems.remove(i);
// }
}
}
And last but not least, the StoreItem.setUpShop() method, which works perfectly fine as long as it gets a good image file, but since the data isn't flowing properly it crashes the whole app. Here it is:
public void setUpShop() {
ib.setImageResource(getResourceID(imageName, "drawable", act.getApplicationContext()));
ib.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1200));
ib.setScaleType(ImageView.ScaleType.CENTER_CROP);
TextView shopLabel = new TextView(act);
shopLabel.setText(name + ": " + price + " Love Bucks");
shopLabel.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
shopLabel.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100));
layout.addView(shopLabel);
layout.addView(ib);
}
Now, I assume I'm just being very stupid with how I'm storing the data here (I'm an extreme beginner at coding apps and data persistence in general) so please let me know what I can do to make this work and what I should use in the future. I've tried my best to explain the whole situation but if there are any questions I would be happy to answer them.
So, I changed my approach and I now have a class here:
package com.example.lorand.saimibutton;
import android.os.Parcel;
import android.os.Parcelable;
public class StoreArrayHolder implements Parcelable {
String price = "";
String name = "";
String image = "";
protected StoreArrayHolder(Parcel in) {
price = in.readString();
name = in.readString();
image = in.readString();
}
public static final Creator<StoreArrayHolder> CREATOR = new Creator<StoreArrayHolder>() {
#Override
public StoreArrayHolder createFromParcel(Parcel in) {
return new StoreArrayHolder(in);
}
#Override
public StoreArrayHolder[] newArray(int size) {
return new StoreArrayHolder[size];
}
};
public StoreArrayHolder(){
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(price);
dest.writeString(name);
dest.writeString(image);
}
}
I use this to store the variables my objects need passed.
This is how I try to use the array between classes. I put this code in the onStop and onPause methods.
private void sendIntent() {
ArrayList<StoreArrayHolder> aList = new ArrayList<>();
for (int i = 0; i < boughtItems.size(); i++) {
StoreArrayHolder temp = new StoreArrayHolder();
temp.setPrice(Integer.toString(boughtItems.get(i).price));
temp.setName(boughtItems.get(i).name);
temp.setImage(boughtItems.get(i).imageName);
aList.add(temp);
}
Intent i = new Intent(this, PouchActivity.class);
i.putExtra("list", aList);
startActivity(i);
}
This is retrieving the array, I put this code in the onStart method.
private void getArrayList() {
if (getIntent().getExtras() != null) {
if (getIntent().hasExtra("list")) {
itemsInfo = getIntent().getParcelableExtra("list");
System.out.println("FUCK YEAH IT WORKED!!!! " + itemsInfo.get(1).getName());
}
}
}
Now I get a nullpointer error meaning that none of the data got transferred, even though the list intent was technically sent!
Initialize shared preference
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME,PRIVATE_MODE);
SharedPreferences.Editor editor;
Method to store array list in to preference (Here i use Gson to convert object in to json)
public void setListToPreferance(String key, ArrayList<OBJECT_OF_MODELCLASS> list) {
Gson gson = new Gson();
String json = gson.toJson(list);
editor = prefs.edit();
editor.putString(key, json);
editor.apply();
}
Method to get list from preference (It will returns the ArrayList)
so you can directly get list from this method
public ArrayList<OBJECT_OF_MODELCLASS> getListProductModel(String key) {
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<OBJECT_OF_MODELCLASS>>() {
}.getType();
ArrayList<OBJECT_OF_MODELCLASS> list = gson.fromJson(prefs.getString(key, ""), type);
if (list == null) {
list = new ArrayList<OBJECT_OF_MODELCLASS>();
}
return list;
}
Pass ArrayListfrom one activity to another activity using Intent
1.Create a Model of array list with Parcelable implemantation
public class DemoModel implements Parcelable{
String price = "";
String totla_amount = "";
protected DemoModel(Parcel in) {
price = in.readString();
totla_amount = in.readString();
}
public static final Creator<DemoModel> CREATOR = new Creator<DemoModel>() {
#Override
public DemoModel createFromParcel(Parcel in) {
return new DemoModel(in);
}
#Override
public DemoModel[] newArray(int size) {
return new DemoModel[size];
}
};
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getTotla_amount() {
return totla_amount;
}
public void setTotla_amount(String totla_amount) {
this.totla_amount = totla_amount;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(price);
dest.writeString(totla_amount);
}
}
Inside the From activity from where you want to send data
private void sendIntent() {
ArrayList<DemoModel> list = new ArrayList<>();
//Add data in to this list or use your list which you want to send
Intent intent = new Intent(this, ConatctsModelActivity.class);
intent.putExtra("list", list);
startActivity(intent);
}
Retrieve array list in To second activity.
ArrayList<DemoModel> list_in_second_activity = new ArrayList<>();
private void getArrayLis() {
if (getIntent().getExtras() != null) {
if (getIntent().hasExtra("list")) {
list_in_second_activity =
getIntent().getParcelableExtra("list");
}
}
}

Convert JSON values from Integer to String

I am using an AsyncTask to connect to the following URL:
https://api.themoviedb.org/3/movie/upcoming?api_key=6572f232190d6b55ec917726dab87783
One of the values I am having trouble with is the genre_id. As it is a JSONArray I add the values to an ArrayList. I then later want to convert these values to the String correspondence which are found here:
http://api.themoviedb.org/3/genre/movie/list?api_key=6572f232190d6b55ec917726dab87783
// Genre is json array
JSONArray genreArry = obj.getJSONArray("genre_ids");
ArrayList<Integer> genre = new ArrayList<Integer>();
for (int j = 0; j < genreArry.length(); j++) {
genre.add(genreArry.optInt(j));
}
I'm just wondering what is the best way to do this? I am a displaying a ListView of all the information and for each row all the information is correct. I just need to convert the Genre id into the corresponding String. I have tried the code below but the TextView is always overwritten by the last value. Does anyone know of a better way to do this?
private void getGenre(int genre) {
for (int i = 0; i < genreList.size(); i++) {
Log.d("THE", "THE GENRE ADAPTER RETRIEVED IS" + i + genreList.get(i).getId() + genreList.get(i).getName());
if (genreList.get(i).getId() == genre) {
String name = genreList.get(i).getName();
mGenre.setText(name);
}
}
Solved.
I managed to get this working by doing a check in the onPostExecute of my AsyncTask
try {
JSONObject json = new JSONObject(result);
JSONArray movies = json.getJSONArray("results");
for (int i = 0; i < movies.length(); i++) {
JSONObject obj = movies.getJSONObject(i);
//Create Movie Object
Movie movie = new Movie();
//get values from JSON
movie.setTitle(obj.getString("original_title"));
movie.setPopularity(obj.getString("popularity"));
movie.setYear(obj.getString("release_date"));
movie.setThumbnailUrl(obj.getString("poster_path"));
movie.setOverView(obj.getString("overview"));
// Genre is json array
JSONArray genreArry = obj.getJSONArray("genre_ids");
ArrayList<Integer> genre = new ArrayList<Integer>();
ArrayList<String> genreName = new ArrayList<String>();
for (int j = 0; j < genreArry.length(); j++) {
genre.add(genreArry.optInt(j));
for (int zz = 0; zz < myGenreList.size(); zz++) {
if (myGenreList.get(zz).getId() == genre.get(j)) {
String name = myGenreList.get(zz).getName();
genreName.add(name);
}
}
}
movie.setGenre(genre);
movie.setGenreName(genreName);
I prefer Volley instead of AsyncTask for simplicity, but you are more than welcome to use either. Note, AsyncTask will require quite a bit more work.
From what I have provided here, you should be able to get my screenshot after building the ListView item XML.
I loosely followed this guide to get started quickly.
Screenshot
Movie.java - Model Object
public class Movie {
private int id;
private String title;
private List<String> genres;
public Movie() {
this(-1, null);
}
public Movie(int id, String title) {
this.id = id;
this.title = title;
this.genres = new ArrayList<String>();
}
public void addGenre(String s) {
this.genres.add(s);
}
public String getTitle() {
return title;
}
public List<String> getGenres() {
return genres;
}
}
MovieAdapter.java - ListView adapter
public class MovieAdapter extends ArrayAdapter<Movie> {
private final int layoutId;
public MovieAdapter(Context context, List<Movie> objects) {
super(context, 0, objects);
layoutId = R.layout.item_movie;
}
private static class ViewHolder {
TextView title;
TextView genres;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Movie movie = getItem(position);
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layoutId, parent, false);
viewHolder.title = (TextView) convertView.findViewById(R.id.movie_title);
viewHolder.genres = (TextView) convertView.findViewById(R.id.movie_genres);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
viewHolder.title.setText(movie.getTitle());
viewHolder.genres.setText(String.valueOf(movie.getGenres()));
// Return the completed view to render on screen
return convertView;
}
}
MainActivity.java
public class MainActivity extends Activity {
private static final String GENRES_URL = "http://api.themoviedb.org/3/genre/movie/list?api_key=6572f232190d6b55ec917726dab87783";
private static final String MOVIES_URL = "https://api.themoviedb.org/3/movie/upcoming?api_key=6572f232190d6b55ec917726dab87783";
private HashMap<Integer, String> genreMap = new HashMap<Integer, String>();
private List<Movie> movies = new ArrayList<Movie>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv = (ListView) findViewById(R.id.listView);
final MovieAdapter movieAdapter = new MovieAdapter(this, movies);
lv.setAdapter(movieAdapter);
// Build the genres map
JsonObjectRequest request1 = new JsonObjectRequest(GENRES_URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray genres = response.getJSONArray("genres");
for (int i = 0; i < genres.length(); i++) {
JSONObject genre = genres.getJSONObject(i);
int id = genre.getInt("id");
String name = genre.getString("name");
genreMap.put(id, name);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Network error", error.getMessage());
}
}
);
VolleyApplication.getInstance().getRequestQueue().add(request1);
JsonObjectRequest request2 = new JsonObjectRequest(MOVIES_URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
movieAdapter.clear();
try {
JSONArray results = response.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
int movieId = result.getInt("id");
String title = result.getString("original_title");
Movie movie = new Movie(movieId, title);
JSONArray genreIds = result.getJSONArray("genre_ids");
for (int j = 0; j < genreIds.length(); j++) {
int id = genreIds.getInt(j);
String genre = genreMap.get(id);
movie.addGenre(genre);
}
movieAdapter.add(movie);
}
} catch (JSONException e) {
Log.e("JSONException", e.getMessage());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Network error", error.getMessage());
}
}
);
VolleyApplication.getInstance().getRequestQueue().add(request2);
}
}

Sorting a ListView with ArrayAdapter<String>

I have a custom ListView, each list item has four TextViews showing bank name, amount, date and time. This data is stored in a database. The idea is that on the Activity there is a quick action dialog which opens on clicking the sort button. The Dialog has three options as "Sort by bank name" ascending order, "Sort by Date" newest first and "Sort by amount" larger amount in the top of the list. I don't have any idea of how to proceed with the sorting task to be written in onItemClick(int pos). Can anyone please help me on this?
public class TransactionMenu extends Activity implements OnItemClickListener, OnActionItemClickListener {
String[] TransId ;
String[] mBankName;
String[] mAmount;
String[] mDate;
String[] mTime;
Button SortButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transaction_screen);
SortButton = (Button)findViewById(R.id.sortKey);
//Bank Name action item
ActionItem bName = new ActionItem();
bName.setTitle("Bank Name");
bName.setIcon(getResources().getDrawable(R.drawable.bank_256));
//Amount action item
ActionItem amt = new ActionItem();
amt.setTitle("Amount");
amt.setIcon(getResources().getDrawable(R.drawable.cash));
//date action item
ActionItem date = new ActionItem();
date.setTitle("Date");
date.setIcon(getResources().getDrawable(R.drawable.calender));
//create quickaction
final QuickAction quickAction = new QuickAction(this);
quickAction.addActionItem(bName);
quickAction.addActionItem(amt);
quickAction.addActionItem(date);
quickAction.setOnActionItemClickListener(this);
SortButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
quickAction.show(v);
//quickAction.setAnimStyle(QuickAction.ANIM_REFLECT);
}
});
DBAdapter lDBAdapter = new DBAdapter(this);
lDBAdapter.open();
/* getTransDetails() returns all the detials stored in the transaction table*/
Cursor mCursor =lDBAdapter.getAllTransDetails();
System.out.println("cur..........."+mCursor);
lDBAdapter.close();
if (mCursor != null) {
int size = mCursor.getCount();
if (mCursor.moveToFirst()) {
TransId = new String[size];
mAmount = new String[size];
mBankName = new String[size];
mDate = new String[size];
mTime = new String[size];
for (int i = 0; i < size; i++, mCursor.moveToNext()) {
TransId[i] = mCursor.getString(0);
mAmount[i] = mCursor.getString(1);
mBankName[i] = mCursor.getString(3);
mDate[i] = mCursor.getString(2);
mTime[i] = mCursor.getString(4);
}
}
}
for (int i = 0; i < mCursor.getCount(); i++) {
System.out.println("TransId is+++++++++++++++ "+TransId[i]);
System.out.println("amount is+++++++++++++++ "+mAmount[i]);
System.out.println("bankName is+++++++++++++++ "+mBankName[i]);
System.out.println("date is+++++++++++++++ "+mDate[i]);
System.out.println("time is+++++++++++++++ "+mTime[i]);
}
ListView myListView = (ListView) findViewById(R.id.transactionListView);
MyBaseAdapter myAdapterObj = new MyBaseAdapter(TransactionMenu.this, R.layout.list_item, TransId);
myListView.setAdapter(myAdapterObj);
myListView.setOnItemClickListener((OnItemClickListener) this);
}
private class MyBaseAdapter extends ArrayAdapter<String> {
public MyBaseAdapter(Context context, int textViewResourceId, String[] transId) {
super(context, textViewResourceId, transId);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.list_item, parent, false);
TextView label = (TextView)row.findViewById(R.id.textview1);
label.setText("Amount: "+mAmount[position]);
TextView label1 = (TextView) row.findViewById(R.id.textview2);
label1.setText("Bank Name: "+mBankName[position]);
TextView label2 = (TextView) row.findViewById(R.id.textview3);
label2.setText("Date: "+mDate[position]);
TextView label3 = (TextView) row.findViewById(R.id.textview4);
label3.setText("Time: "+mTime[position]);
return row;
}
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
System.out.println("arg2 is++++++++++++++"+arg2);
int lRowId = Integer.parseInt(TransId[arg2]);
}
public void onItemClick(int pos) {
MyBaseAdapter myAdapterObj = new MyBaseAdapter(TransactionMenu.this, R.layout.list_item, TransId);
if (pos == 0) {
Toast.makeText(TransactionMenu.this, "Bank name item selected", Toast.LENGTH_SHORT).show();
}
else if (pos ==1) {
Toast.makeText(TransactionMenu.this, "amount item selected", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(TransactionMenu.this, "Date item selected", Toast.LENGTH_SHORT).show();
}
}
}
I will give you the way i would do this, not the best probably but it will work fine.
Fisrt of all as user7777777777 said it's better to keep related infos into the same object so i'd define BankInfo class as shown below:
private class BankInfo{
String TransId ;
String mBankName;
String mAmount;
String mDate;
String mTime;
public BankInfo(String TransId,String mBankName,String mAmount,String mDate,String mTime)
{
//fields init
}
}
once you have this you will define an Array of this object BankInfo[] trans. In the adapter you can use this array to bind values into views.
then to manage to implement the sorting function the thing i would do is to put a static variable into the BankInfo class and override the CompareTo() method to use that field:
static int AMMOUNT = 0;
static int DATE = 1;
static int NAME = 2;
static public int sort_by;
public int compareTo(BankInfo info){
switch (sorty_by){
case(AMMOUNT):
return //compare by ammount
case(DATE):
return //compare by date
case(NAME):
return //compare by name
}
}
with this inside of BankInfo you will have only to add your array to a TreeSet<BankInfo> and all your item will be sortet using the compareTo() method.
Inside the adapter put this method to sort elements in the adapter
public void sort_datas(int sort_by);
{
//set the type of sort you want
BankInfo.sortBy = sort_by;
//build a Sorted treeSet by the BankInfo array
TreeSet<BankInfo> sorted_info = new TreeSet<BankInfo>();
list.addAll(Arrays.asList(trans));
//replace the BankInfo array with the new sorted one
trans = (BankInfo[])sorted_info.toArray();
//notify to the adapter that the data set changed
notifyDataSetChanged();
}
You can use the following code. You need to maintain the bank info in a BankInfo object. Create an ArrayList of BankInfo objects and then you can use this code. Its not a good practice to keep related info into separate arrays.
Collections.sort(mBankInfoArrayList, new Comparator<BankInfo>() {
int compare(BankInfo obj1, BankInfo obj2) {
return obj1.getBankName().compareToIgnoreCase(obj2.getBankName());
}
});

Categories