ParcelableArraylist may produce nullpointerexception in fragment - java

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

Related

how do i save my arraylist onto on onSaveInstanceState

i have a growing arraylist with a custom object, for it to grow i need to save it so it doesn't get cleared, but even after implementing parcelable still doesn't work. did i implement parcelble wrong? all code works apart from being able to save my arraylist, if some one could help it will be a great help
//class
public class team implements Parcelable {
// Defining Activity class to use
private Activity activity;
// Defining text box
LinearLayout lay;
View Tbox;
// Members Defining
String teamname;
String teacher;
ArrayList<Players> members = new ArrayList<Players>();
public team(Activity activity, String teamname, String teacher) {
// To be able to use activity
this.activity = activity;
// Normal things to define
this.teamname = teamname;
this.teacher = teacher;
// initialize the lay and Tbox variables
lay = activity.findViewById(R.id.Scontainer);
Tbox = activity.getLayoutInflater().inflate(R.layout.text_box_output, null);
}
public void addtext() {
// add text to the layout and view
TextView title = Tbox.findViewById(R.id.daTeam);
title.setText(teamname);
lay.addView(Tbox);
}
//bs
protected team(Parcel in) {
teamname = in.readString();
teacher = in.readString();
}
public static final Creator<team> CREATOR = new Creator<team>() {
#Override
public team createFromParcel(Parcel in) {
return new team(in);
}
#Override
public team[] newArray(int size) {
return new team[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(#NonNull Parcel parcel, int i) {
parcel.writeString(teamname);
parcel.writeString(teacher);
}
}
//mainactivity
public class MainActivity extends AppCompatActivity {
ArrayList<team> listofteams ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null ) {
listofteams = savedInstanceState.getParcelableArrayList("key");
}
else{
listofteams = new ArrayList<team>();
}
setContentView(R.layout.sports_screen);
//sending out variable
Intent intent = new Intent (this, Creating_Class_main.class);
Activity ma = this;
//names
Intent MB = getIntent();
String Classinp = MB.getStringExtra("strC");
String tchinp = MB.getStringExtra("strT");
//adding team
team sportsteam;
System.out.println(listofteams);
boolean flag = MB.getBooleanExtra("flag", false);
if (flag){
sportsteam = new team(ma, Classinp,tchinp);
listofteams.add(sportsteam);
System.out.println(listofteams);
}
}
//saveing layout
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("key", listofteams);
super.onSaveInstanceState(outState);
}
}

Parcelable object changes completely when sent as an Extra of an Intent

I'm trying to put a Parcelable object as an extra in an intent and pass it to the next Activity, and it doesn't crash but the object changes dramatically. I'm sending when clicking on an item from a RecyclerView in a Fragment and opening an Activity from it.
This is how I send it:
AdminProfile adminProfile = list.get(position).admin;
Intent intent = new Intent(view.getContext(),ClosedChatActivity.class);
intent.putExtra("chat",adminProfile);
view.getContext().startActivity(intent);
This how I get it:
adminProfile = (AdminProfile) getIntent().getExtras().getParcelable("chat");
And here the class:
public class AdminProfile implements Parcelable {
public static final Creator<AdminProfile> CREATOR = new Creator<AdminProfile>() {
#Override
public AdminProfile createFromParcel(Parcel in) {
return new AdminProfile(in);
}
#Override
public AdminProfile[] newArray(int size) {
return new AdminProfile[size];
}
};
public Long idUser;
public String name;
public String professio;
public String description;
public List<WebLink> webLinks;
public Long idOficina;
protected AdminProfile(Parcel in) {
if (in.readByte() == 0) {
idUser = null;
} else {
idUser = in.readLong();
}
name = in.readString();
professio = in.readString();
description = in.readString();
webLinks = in.createTypedArrayList(WebLink.CREATOR);
if (in.readByte() == 0) {
idOficina = null;
} else {
idOficina = in.readLong();
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(idUser);
parcel.writeString(name);
parcel.writeString(professio);
parcel.writeString(description);
parcel.writeLong(idOficina);
parcel.writeList(webLinks);
}
}
I can't understand why, but when I send the object I have UserId=3, but when I get it it's userId=55834574848. Any ideas?
The Parcelable functions were filled automatically by Android Studio, and reading the first byte messed it up.
Changing
if (in.readByte() == 0) {
idUser = null;
} else {
idUser = in.readLong();
}
for
idUser = in.readLong();
fixed it.

How to pass ParcelableArrayList from Fragment to Fragment?

I have been trying to find the way to pass a ParcelableArrayList from one Fragment to Another and for some reason when I receive the ParcelableArrayList it's empty. I have checked many posts about this problem but I don't make it work.
This is my Activity that holds the Fragments in a FrameLayout:
package com.blumonpay.restaurant.customer.presentation.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.WindowManager;
import com.blumonpay.android.mifel.restaurante.R;
import com.blumonpay.restaurant.customer.presentation.fragments.ShowPayMethodsFragment;
public class PayMethodsActivity extends AppCompatActivity {
private Fragment showFragment;
private Fragment addFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
setContentView(R.layout.activity_pay_methods);
showFragment = ShowPayMethodsFragment.getInstance(this);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, showFragment)
.commit();
}
public void switchFragment(Fragment fragment) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frameLayout, fragment)
.commit();
}
}
This is how I'm trying to pass the ArrayList in my first Fragment:
Bundle dataBundle = new Bundle();
dataBundle.putParcelableArrayList("cardsList", (ArrayList<? extends Parcelable>) list);
dataBundle.putInt("position",position);
ShowDetailedPayMethodFragment showDetailPayMethod = ShowDetailedPayMethodFragment.getInstance(context);
showDetailPayMethod.setArguments(dataBundle);
((PayMethodsActivity)context).switchFragment(showDetailPayMethod);
As you can see I'm also passing an int value which I can receive with no problem at all.
Then, this is the second Fragment where I'm receiving the data (ParcelableArrayList and the int value):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_view_detailed_pay_method, container, false);
if (this.getArguments()!=null) {
cardsList = this.getArguments().getParcelableArrayList("cardsList");
positionList = this.getArguments().getInt("position");
}
cardsBannerAdapter = new CustomCardsBannerAdapter(context, cardsList);
cardsViewPager.setAdapter(cardsBannerAdapter);
initSlider();
return v;
}
For some reason the List is empty when I get to this point, the only value I'm getting is this.getArguments().getInt("position"); (int value)
And finally this is my POJO class Cards:
package com.blumonpay.restaurant.customer.domain.model;
import android.os.Parcel;
import android.os.Parcelable;
public class Cards implements Parcelable {
private String cardNumber;
private String cardType;
private String cardBrand;
private String cardExpirationDate;
private String cardHolderName;
public Cards(String cardNumber, String cardType, String cardBrand, String cardExpirationDate, String cardHolderName) {
this.cardNumber = cardNumber;
this.cardType = cardType;
this.cardBrand = cardBrand;
this.cardExpirationDate = cardExpirationDate;
this.cardHolderName = cardHolderName;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public String getCardType() {
return cardType;
}
public void setCardType(String cardType) {
this.cardType = cardType;
}
public String getCardBrand() {
return cardBrand;
}
public void setCardBrand(String cardBrand) {
this.cardBrand = cardBrand;
}
public String getCardExpirationDate() {
return cardExpirationDate;
}
public void setCardExpirationDate(String cardExpirationDate) {
this.cardExpirationDate = cardExpirationDate;
}
public String getCardHolderName() {
return cardHolderName;
}
public void setCardHolderName(String cardHolderName) {
this.cardHolderName = cardHolderName;
}
protected Cards(Parcel in) {
cardNumber = in.readString();
cardType = in.readString();
cardBrand = in.readString();
cardExpirationDate = in.readString();
cardHolderName = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(cardNumber);
dest.writeString(cardType);
dest.writeString(cardBrand);
dest.writeString(cardExpirationDate);
dest.writeString(cardHolderName);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Cards> CREATOR = new Parcelable.Creator<Cards>() {
#Override
public Cards createFromParcel(Parcel in) {
return new Cards(in);
}
#Override
public Cards[] newArray(int size) {
return new Cards[size];
}
};
}
Any clue of what am I missing?
Tried the same in kotlin, with the Cards.java intact. The list gets passed. Here is the snippet.
Could you try and compare?
In first fragment as an example:
val item = Cards("gfhfhfhfh", "", "", "", "")
val list = ArrayList<Cards>()
list.add(item
Passing it as: (no explicit cast)
bundle.putParcelableArrayList("list",list)
In the next fragment:
val l = arguments?.getParcelableArrayList<Cards>("list")
According to this post, How to marshall and unmarshall Parcelable, Parcelable object is not stable which might well be the reason that you cannot pass it from one activity to another. I faced similar problem recently and used the same post to solve my problem. Basically in steps:
1. You need to marshall the Parcelable object in the first Activity as :
byte[] bytes = marshall(parcelableObj);
intentOpenSecondActivity.putExtra(SOME_KEY, bytes);
2. You need to unmarshall it in the second Activity as :
byte[] bytes = getIntent().getExtras().getByteArray(SOME_KEY);
parcelableObj = unmarshall(bytes, ParcelableObject.CREATOR);

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;
}
}

How to pass object with List of other object between activities using Parcelable?

I have an object called Order which I want to pass between activities. Currently I am using Parcelable to do so.
public class Order implements Parcelable {
private String email;
private Long timestamp;
private List<OrderItem> items;
public Order() { }
private Order(Parcel in) {
email = in.readString();
timestamp = in.readLong();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<Order> CREATOR = new Creator<Order>() {
#Override
public Order createFromParcel(Parcel in) {
return new Order(in);
}
#Override
public Order[] newArray(int size) {
return new Order[size];
}
};
// Getters
...
}
The items field is a List of OrderItem objects which implement the Parcelable interface.
public class OrderItem implements Parcelable {
private String orderedClothingId;
private int quantity;
public OrderItem() { }
public OrderItem(String orderedClothingId, int quantity) {
this.orderedClothingId = orderedClothingId;
this.quantity = quantity;
}
private OrderItem(Parcel in) {
orderedClothingId = in.readString();
quantity = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(orderedClothingId);
dest.writeInt(quantity);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<OrderItem> CREATOR = new Creator<OrderItem>() {
#Override
public OrderItem createFromParcel(Parcel in) {
return new OrderItem(in);
}
#Override
public OrderItem[] newArray(int size) {
return new OrderItem[size];
}
};
}
Now to pass an Order object called order from one activity to another I do the following:
Intent intent = new Intent(mContext, ActivityTwo.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(ORDER_DETAIL_INTENT_EXTRA_KEY, order);
mContext.startActivity(intent);
In ActivityTwo I collect the Order object like so:
Bundle data = getIntent().getExtras();
assert data != null;
mOrder = data.getParcelable(ORDER_DETAIL_INTENT_EXTRA_KEY);
However, when I log the items field contained in the Order object in ActivityTwo it is null. How do I pass the original non-null Order object between activities without the items list being null?
First you miss to read the array back with dest = in.readTypedList(emptyList, CREATOR);
But second and more important, you need to write/read the same ammount of arguments, since you have a if in your writeToParcel you need the same when reading:
private Order(Parcel in) {
email = in.readString();
if(in.readByte() == 1)
timestamp = in.readLong(); //here to skip just like the writeToParcel
in.readTypedList(items = new ArrayList<OrderItem>(), OrderItem.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
From first glance it looks like you are passing different different keys within your parcelable
ORDER_DETAIL_INTENT_EXTRA_KEY in the first and CLOTHING_ADMIN_DETAIL_INTENT_EXTRA_KEY in the 2nd. They should both be the same, so pick which one.
Also you can use getIntent().getParcelableExtra() instead of having to use a Bundle

Categories