Update an object passed through Parcelable intent - android

I'm new to Android and i'm still learning. I currently have a ListView which allows you to click on an item. Clicking on an item will open a new intent displaying extra information about the item.
The thing i'm tripping up on is figuring out how to get the updated values back into my custom object and update the values in array at the correct index.
For example:
I'll add an item and set it's quantity to 2. This will appear in my ListView. Great. I decide i need 3 instead of 2, so i click the item to open the new activity, see 2 sitting in quantity, update it to 3 and hit save. On the save click i want to go back to my listview and have the updated quantity value displaying there and also updated in the array at the index.
Code for segments:
Onclick method for the listview in ItemList class
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
bean = (CustomObject) listview.getItemAtPosition(arg2);
Intent in1 = new Intent(Itemlist.this, SingleItem.class);
in1.putExtra("ActivityObject", bean);
startActivity(in1);
}
});
Adding an item the array in my ItemList class. this contain the listview.
else {
objects.add(new CustomObject(roomname.getText().toString() + " - " + resultSet.get(namecount), resultSet.get(partno), itemq, "$" + resultSet.get(rrpcol), resultSet.get(glcode), resultSet.get(desc)));
adapter.notifyDataSetChanged();
SingleItem class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_singleitem);
siname = (TextView) findViewById(R.id.siname);
sipartno = (TextView) findViewById(R.id.sipartno);
siquantity = (EditText) findViewById(R.id.siq);
sirrp = (EditText) findViewById(R.id.sirrp);
siglcode = (TextView) findViewById(R.id.siglcode);
sidesc = (EditText) findViewById(R.id.sidesc);
update = (Button) findViewById(R.id.siupdate);
Bundle b = getIntent().getExtras();
CustomObject itemInfo = b.getParcelable("ActivityObject");
siname.setText(itemInfo.getItemName());
sipartno.setText(itemInfo.getItemPartNo());
siquantity.setText(itemInfo.getItemQuantity());
sirrp.setText(itemInfo.getItemPrice());
siglcode.setText(itemInfo.getItemGLCode());
sidesc.setText(itemInfo.getItemDesc());
}
Custom Object class
public class CustomObject implements Parcelable {
private String itemName;
private String itemPartNo;
private String itemQuantity;
private String itemPrice;
private String itemGLCode;
private String itemDesc;
public CustomObject(Parcel source){
/*
* Reconstruct from the Parcel
*/
//Log.v(TAG, "ParcelData(Parcel source): time to put back parcel data");
//id = source.readInt();
itemName = source.readString();
itemPartNo = source.readString();
itemQuantity = source.readString();
itemPrice = source.readString();
itemGLCode = source.readString();
itemDesc = source.readString();
}
public CustomObject(String prop1, String prop2, String prop3, String prop4, String prop5, String prop6) {
this.itemName = prop1;
this.itemPartNo = prop2;
this.itemQuantity = prop3;
this.itemPrice = prop4;
this.itemGLCode = prop5;
this.itemDesc = prop6;
}
public String getItemName() {
return itemName;
}
public String getItemPartNo() { return itemPartNo; }
public String getItemQuantity() {
return itemQuantity;
}
public String getItemPrice() {
return itemPrice;
}
public String getItemGLCode() {return itemGLCode;}
public String getItemDesc() {return itemDesc;}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(itemName);
dest.writeString(itemPartNo);
dest.writeString(itemQuantity);
dest.writeString(itemPrice);
dest.writeString(itemGLCode);
dest.writeString(itemDesc);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public CustomObject createFromParcel(Parcel in) {
return new CustomObject(in);
}
public CustomObject[] newArray(int size) {
return new CustomObject[size];
}
};
}
I want to be able to change the quantity in the SingleItem class, click the Update button, and then have it load up the itemlist class with the updated values in the item list.

It'd be more efficient to use Fragments with your own callback interfaces defined for the activity. But, if you want to go the Activity approach, use startActivityForResult() and have your detail Activity send back a result Intent with any updates object contents.

Related

Click on ListView item not opening new Activity

I have a ListView "resultList", but clicking on an item is not opening the new (detailed) Activity. What's my mistake?
Thank you!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.resultList = (ListView) findViewById(R.id.resultList) ;
this.dataSource = MyExpenseOpenHandler.getInstance(this).readAllExpenses();
this.adapter = new ExpenseOverviewAdapter(this, dataSource);
this.resultList.setAdapter(adapter);
this.resultList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> adapterView, View view, final int i, final long l) {
Object element = adapterView.getAdapter().getItem(i);
if (element instanceof Expense) {
Expense expense = (Expense) element;
Intent intent = new Intent(MainActivity.this, ExpenseDetailActivity.class);
intent.putExtra(ExpenseDetailActivity.EXPENSE_KEY, expense);
startActivity(intent);
}
Log.e("Click on List: ", element.toString());
}
});
}
Your code seems alright .I think the problem is that your if condition may be returning false and the code inside the if statement is not being executed.You can put a log message inside the if statement to check if the code is being executed.
if (element instanceof Expense) {
Log.d(YOUR_LOG_TAG,"The if condition not executed")
Expense expense = (Expense) element;
Intent intent = new Intent(MainActivity.this, ExpenseDetailActivity.class);
intent.putExtra(ExpenseDetailActivity.EXPENSE_KEY, expense);
startActivity(intent);
}
If you see the log message in your android monitor you can be sure that the code inside your if condition is not executed and hence your activity is not starting.
Did you implement Parcelable on your class Expense ?
Something like this
public class Expense implements Parcelable{
private String id;
private String name;
private String grade;
// Constructor
public Expense(String id, String name, String grade){
this.id = id;
this.name = name;
this.grade = grade;
}
// Getter and setter methods
.........
.........
// Parcelling part
public Expense(Parcel in){
String[] data = new String[3];
in.readStringArray(data);
// the order needs to be the same as in writeToParcel() method
this.id = data[0];
this.name = data[1];
this.grade = data[2];
}
#Оverride
public int describeContents(){
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {this.id,
this.name,
this.grade});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Expense createFromParcel(Parcel in) {
return new Expense(in);
}
public Expense[] newArray(int size) {
return new Expense[size];
}
};
}
what kind of view in the list, if the child view get the focus like button may lead to item click not work well.
you can try to add android:descendantFocusability="beforeDescendants" in you listview.

ListView and Custom Adapter

With putDate method in main, I have a method called updateStudentDate in dbManager class that get id and date, and when I click on save button the ids that i got from database and current date is sent to updateStudentDate.
but error occur.
This is main activity.
public class StartAttendance extends AppCompatActivity implements View.OnClickListener{
private DBManager dbManager;
private List<UserModel> students;
private String studentSubjectId;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_attendance);
final Button save = (Button) findViewById(R.id.save);
final Button cancel = (Button) findViewById(R.id.cancel);
final ListView listOfTakeAtt = (ListView) findViewById(R.id.listOfTakingAttendance);
Intent intent = getIntent();
studentSubjectId = intent.getStringExtra("studentSubjectId");
dbManager = new DBManager(StartAttendance.this);
dbManager.open();
ArrayList arrayList2 = dbManager.getAllStudentsName(Integer.valueOf(studentSubjectId));//Get the names from database.
students = new ArrayList<>();
setData(arrayList2);
final CustomLayoutOfTakingAttendance adapter = new CustomLayoutOfTakingAttendance(this, students);
listOfTakeAtt.setAdapter(adapter);
listOfTakeAtt.setDividerHeight(17);
cancel.setOnClickListener(this);
save.setOnClickListener(this);
listOfTakeAtt.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
UserModel model = students.get(i);
int y=model.isSelected?1:0;
model.setSelected(true);
students.set(i, model);
if(y==1){
model.setSelected(false);
}
adapter.updateRecords(students);
}
});
}
public void setData(ArrayList arrayList2){
for(int i=0;i<arrayList2.size();i++){
students.add(new UserModel(false, (String) arrayList2.get(i)));
}
}
#Override
public void onClick(View v){
switch (v.getId()){
//When save button is clicked i want to see present radioButton is checked or not for each item.
//if checked save current date into database for this id.
case R.id.save:
putDate();
break;
case R.id.cancel:
Intent i=new Intent(StartAttendance.this,ContentOfEachSubject.class);
i.putExtra("studentSubjectId",studentSubjectId);
startActivity(i);
break;
}
}
public void putDate(){
SimpleDateFormat DateFormat=new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault());
Date d=new Date();
String date=DateFormat.format(d);
boolean isUpdated=false;
UserModel model;
ArrayList arrayList1 = dbManager.getAllStudentsId(Integer.valueOf(studentSubjectId));//Get the ids from the database.
for(int i=0;i<students.size();i++)
{
model = students.get(i);
if(model.isSelected){
dbManager = new DBManager(StartAttendance.this);
dbManager.open();
isUpdated = dbManager.UpdateStudentDate((Integer) arrayList1.get(i), date);
}
}
if(isUpdated){Toast.makeText(StartAttendance.this,"You took attendance successfully..",Toast.LENGTH_SHORT);}
else {Toast.makeText(StartAttendance.this,"Fail while getting attendance!!",Toast.LENGTH_SHORT);}
}
}
UserModel class
public class UserModel {
boolean isSelected;
String name;
public UserModel(boolean isSelected,String name) {
this.isSelected = isSelected;
this.name=name;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
public String getStudentName() {
return name;
}
public void setStudentName(String name) {
this.name = name;
}
}
dbManager class
public boolean UpdateStudentDate(int id,String date){
ContentValues cv=new ContentValues();
cv.put(DatabaseHelper.KEY_STUDENT_DATE,date);
long result=database.update(DatabaseHelper.STUDENT_TABLE,cv,DatabaseHelper.KEY_STUDENT_ID+" = "+id,null);
databaseHelper.close();
if(result==-1){return false;}
else return true;
}
You have an error in implementation of getAllStudentsId(int id) method.
If your IDs are suppose to be of type Integer, I'd suggest you to change signature of method to return not ArrayList, but ArrayList<Integer>. It would be even better to return some generic type of list, such as List<Integer> is.
However, the main issue is, that within this method you are adding to collection String instances, instead of Integers.
arrayList.add(cursor.getString(cursor.getColumnIndex(Databas‌​eHelper.KEY_STUDENT_‌​ID)));
I don't know how data are persisted in DB, whether your IDs are numeric or varchar format, but I guess it should be enough to change cursor.getString(...) to cursor.getInt(...)
Then, implementation of this method could be like
public List<Integer> getAllStudentsId(int id){
List<Integer> result =new ArrayList<>();
String[] columns = new String[]{DatabaseHelper.KEY_STUDENT_ID};
Cursor cursor = database.query(DatabaseHelper.STUDENT_TABLE, columns, D‌​atabaseHelper.KEY_ST‌​UDENT_SUBJECT_ID + " = " + id, null, null,null,null);
while(cursor.moveToNext()){
result.add(cursor.getInt(cursor.getColumnIndex(Databas‌​eHelper.KEY_STUDENT_‌​ID)));
}
return result;
}
Also, don't forget to change type of your list within StartAttendance.java class.
List<Integer> arrayList1 = dbManager.getAllStudentsId(Integer.valueOf(studentSubjectId));//Get the ids from the database.

How to load Json data into a spinner in Android?

I can get the data from the server loaded into a List<>, but can't get the specific items.
Json data looks like this.
[
{"subscriptionType":"1234,
"typeName":"stuff",
"name":"Alpha"},
{"subscriptionType":"1234,
"typeName":"stuff",
"name":"Beta"},
]
and so on...
I have a class that that I load the data into from a Presenter calling a Fetch event. All that seems to be working because I get a Log for the data loaded into the Array
public class AppEntitySubscriptions implements Parcelable {
public AppEntitySubscriptions(ApiSubscription apiSubscription) {
this.subscriptionType = apiSubscription.getSubscriptionType();
this.typeName = apiSubscription.getTypeName();
this.name = apiSubscription.getName();
}
private int subscriptionType;
private String typeName;
private String name;
public
int getSubscriptionType() {
return subscriptionType;
}
public String getTypeName() {
return typeName;
}
public String getName() {
return name;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.subscriptionType);
dest.writeString(this.typeName);
dest.writeString(this.name);
}
#SuppressWarnings("ResourceType")
protected AppEntitySubscriptions(Parcel in) {
this.subscriptionType = in.readInt();
this.typeName = in.readString();
this.name = in.readString();
}
public static final Creator<AppEntitySubscriptions> CREATOR = new Creator<AppEntitySubscriptions>() {
#Override
public AppEntitySubscriptions createFromParcel(Parcel in) {
return new AppEntitySubscriptions(in);
}
#Override
public AppEntitySubscriptions[] newArray(int size) {
return new AppEntitySubscriptions[size];
}
};
Now here is where I am getting lost. I just want to get the data for "name" elements into a spinner
Spinner spinner = (Spinner) findViewById(R.id.spinner);
List<AppEntitySubscriptions> userSubscriptions;//data is here
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.toolbar_spinner_item, "what goes here"???);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
I don't know how to get the name into a string array of it's own and loaded into the spinner. Any suggestions would be helpful.
Thanks.
You could not use this list in Spinner
private List<AppEntitySubscriptions> subscriptionsList = new ArrayList<>();
Create new list
private List subscriptionsStrings = new ArrayList<>();
and fill it
for (int i=0; i<subscriptionsList.size(); i++) {
subscriptionsStrings.add(subscriptionsList.get(i).getTypeName());
}
and then
ArrayAdapter<ArrayList<String>>(this, R.layout.toolbar_spinner_item, subscriptionsStrings);

Issue with passing a Custom ArrayList through Intent with Serialize

I am attempting to pass an array List of Custom objects through from one class to the other. I used a wrapper class to pass over the array List:
package perks;
import java.io.Serializable;
import java.util.ArrayList;
public class PerkWrapper implements Serializable {
private ArrayList<Perk> parliaments;
public PerkWrapper(ArrayList<Perk> perks) {
this.parliaments = perks;
}
public ArrayList<Perk> getParliaments() {
return this.parliaments;
}
}
I pass it like this:
i.putExtra("perks", player.perks);
Where player.perks is the arrayList containing teh Perk object
And i retrieve it like so:
PerkWrapper pw = (PerkWrapper) getIntent().getSerializableExtra("perks");
plrPerks = pw.getParliaments();
player.perks = plrPerks;
When i run the app, i get the following error:
Unable to start activity.. ClassCastException ArrayList cannot be cast to
perks.perkwrapper
Here is my Perk class: (The object in the array List):
package perks;
public class Perk implements Parcelable {
public String name;
public String desc;
public int cost;
public int roundReq;
public int rankReq;
public int minusDec;
public int plusInc;
public int autoClick;
public int rewardBonus;
public Perk() {
this.name = "";
this.desc = "";
this.cost = 0;
this.roundReq = 1;
this.rankReq = 1;
this.minusDec = 1;
this.plusInc = 1;
this.autoClick = 1;
this.rewardBonus = 1;
}
public Perk(Parcel in) {
name = in.readString();
desc = in.readString();
cost = in.readInt();
roundReq = in.readInt();
rankReq = in.readInt();
minusDec = in.readInt();
plusInc = in.readInt();
autoClick = in.readInt();
rewardBonus = in.readInt();
}
public static final Parcelable.Creator<Perk> CREATOR = new Parcelable.Creator<Perk>() {
public Perk createFromParcel(Parcel in) {
return new Perk(in);
}
public Perk[] newArray(int size) {
return new Perk[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(desc);
dest.writeInt(cost);
dest.writeInt(roundReq);
dest.writeInt(rankReq);
dest.writeInt(minusDec);
dest.writeInt(plusInc);
dest.writeInt(autoClick);
dest.writeInt(rewardBonus);
}
}
How can i prevent this error from happening or are there any alternatives to passing array Lists simply? Thank you for your time
You are passing player.perks which is an ArrayList of Perk and in your other activity you are getting PerkWrapper and hence it is giving you error.You will need to do something like this
ArrayList<Perk> perks = (ArrayList<Perk>) getIntent().getSerializableExtra("perks");
Reply to #amit singh's Answer (My reputation not yet upto comment
level)
The method specified is possible possible only for arraylist of the format ArrayList. For custom objects, this is not applicable.
To pass arraylist between activities, use-
Intent intent = new Intent(this, secondActivity.class);
intent.putStringArrayListExtra("list", samplelist);
startActivity(intent);
In your receiving intent you need to do:
Intent i = getIntent();
stock_list = i.getStringArrayListExtra("list");

Problems populating a fragment list

I have a SherlockFragmentActivity class that collects values from a server and loads it in to my database. This SherlockFragmentActivity as 3 Fragment called the Book, Video and Audios. Each of them are meant to show values that were downloaded into the db. By challenge now is when I open my UI i dont get to see the values on the fragments not until I start clicking each fragment before the values get populated into the list in the fragment. And I even notice a continuous addition of this values. My fragment class is pasted below.
public class BooksFragment extends SherlockListFragment{
TextView textview = null;
String CategoryID = null;
ArrayList<HashMap<String,String>> listBooks = null;
IDatabaseHelper databaseHelper = null;
Activity activity = null;
Context context = null;
ListAdapter adapter = null;
public BooksFragment(){
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.books, container, false);
// do your view initialization heres
textview = (TextView)view.findViewById(R.id.textView1);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
listBooks = new ArrayList<HashMap<String,String>>();
}
#Override
public void onStart() {
super.onStart();
Bundle bundle =this.getArguments();
if(bundle != null){
CategoryID = bundle.getString("CategoryID");
}
this.initializeComponents();
this.populateListView();
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
activity = getActivity();
context = activity.getBaseContext();
databaseHelper= new DatabaseHelper(context);
}
//Now we are going to initialize components of the fragment
private void initializeComponents(){
ListView listview = getListView();
listview.setOnItemClickListener(listener);
}
//list item click listener
private OnItemClickListener listener = new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
}
};
//This method would be used to collect content from the database and populate the listview item
private void populateListView(){
MedicalBookModel[] booksmodel = this.databaseHelper.ReturnBooks(CategoryID);
if(booksmodel != null){
for(MedicalBookModel book : booksmodel){
HashMap<String,String> bookMap = new HashMap<String,String>();
bookMap.put(MedicalBookModel.MedicalBookModel_ID, book.getID());
bookMap.put(MedicalBookModel.MedicalBookModel_Name,book.getName());
Log.i("values",book.getName());
listBooks.add(bookMap);
}
}
adapter = new SimpleAdapter(context, listBooks,R.layout.list_book,new String[]{ "ID","Name"}, new int[]{ R.id.bookId, R.id.bookName});
setListAdapter(adapter);
}
}
For that you have several solutions :
1- Using the Application instance singleton which is global
2- Creating your own global class to manage your data
3- Use a service bound to the activity (or not) and call backs (maybe intent and broadcast receivers)
4- Pass your object as parceable in argument when adding the fragment
Note that sometimes you will need to invalidate views to force datas to refresh
EXEMPLE OF PARCEABLE OBJECT
public class ImageObject implements Parcelable {
/**
* ATTRIBUTES
*/
protected String _idPicture;
protected String _idAlbum;
protected String _name;
protected String _fileName;
protected String _imageUrl;
protected String _hierarchy;
public ImageObject(String _idPicture, String _idAlbum, String _name, String _fileName, String _imageUrl, String _hierarchy) {
super();
this._idPicture = _idPicture;
this._idAlbum = _idAlbum;
this._name = _name;
this._fileName = _fileName;
this._imageUrl = _imageUrl;
this._hierarchy = _hierarchy;
}
public ImageObject(Parcel in) {
String[] data = new String[6];
in.readStringArray(data);
this._idPicture = data[0];
this._idAlbum = data[1];
this._name = data[2];
this._fileName = data[3];
this._imageUrl = data[4];
this._hierarchy = data[5];
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ImageObject createFromParcel(Parcel in) {
return new ImageObject(in);
}
public ImageObject[] newArray(int size) {
return new ImageObject[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] { this._idPicture, this._idAlbum, this._name, this._fileName, this._imageUrl, this._hierarchy });
}
}

Categories

Resources