How to pass ParcelableArrayList from Fragment to Fragment? - java

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

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

Android ViewModel do not propagate data

Suddenly I decided that need to gain android dev experience. I want to create a simple us which will get data from lib and push it to segment with the table view. I'm following the guide https://developer.android.com/guide/fragments/communicate
The problem is that I don't have exceptions but the data in the table(R.id.sdkhash) is not updated. There should be some stupid mistake on my side, but I can't find it.
MainActivity.java
I'm getting (InfoViewModel extends ViewModel) here and push the data via selectItem method.
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
infoViewModel = new ViewModelProvider(this).get(InfoViewModel.class);
RuntimeInfo runtimeInfo = new RuntimeInfo("A", "B", "C", "D");
infoViewModel.selectItem(runtimeInfo);
InfoViewModel.java
class RuntimeInfo {
public String sdkHash;
public String deviceUid;
public String URL;
public String userAgent;
public RuntimeInfo(String hash, String deviceid, String url, String agent) {
sdkHash = hash;
deviceUid = deviceid;
URL = url;
userAgent = agent;
}
}
InfoViewModel.java I'm defining my ViewModel here.
class RuntimeInfo {
// Dummy class to hold the data.
public String sdkHash;
public String deviceUid;
public String URL;
public String userAgent;
public RuntimeInfo(String hash, String deviceid, String url, String agent) {
sdkHash = hash;
deviceUid = deviceid;
URL = url;
userAgent = agent;
}
}
public class InfoViewModel extends ViewModel {
private final MutableLiveData<RuntimeInfo> selectedItem = new MutableLiveData<RuntimeInfo>();
public void selectItem(RuntimeInfo item) {
selectedItem.setValue(item);
}
public MutableLiveData<RuntimeInfo> getSelectedItem() {
return selectedItem;
}
}
InfoFragment.java - Fragment which is responsible for the UI part. I want to be able to update its UI based on the data from MainActivity.
public class InfoFragment extends Fragment {
...
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
hashRowview = (TextView) view.findViewById(R.id.sdkhash);
infoViewModel = new ViewModelProvider(this).get(InfoViewModel.class);
infoViewModel.getSelectedItem().observe(getViewLifecycleOwner(), item -> {
hashRowview.setText((CharSequence) item.sdkHash);
});
infoViewModel.getSelectedItem();
RuntimeInfo runtimeInfo = infoViewModel.getSelectedItem().getValue();
System.out.println("*************************************** runtimeInfo:" + runtimeInfo);
if (runtimeInfo != null) {
hashRowview.setText((CharSequence) runtimeInfo.sdkHash);
System.out.println("*************************************** runtimeInfo Not NULL");
}

NotSerializableException when FragmentActivity goes to background in Android

I have 5 fragments inside my activity where one fragment stays active at one time. Clicking on a recyclerview item opens another fragment and puts current fragment in the backstack.
The same code was working fine some days ago, but now the app is throwing NotSerializableException whenever I click the home button to put the app in background. I have tried putting the initializing the variables inside onStart and then giving the null value in onStop but that didn't work.
Fragment Code:
public class PaperListFragment extends Fragment implements Serializable {
private static final String TAG = "PaperListFragment";
private static final String QUESTIONS_FRAGMENT_TAG = "questions_fragment";
private static final String ADD_PAPER_FRAGMENT_TAG = "add_paper_fragment";
private OnFragmentActiveListener mOnFragmentActiveListener;
private TextView mHeadingText;
private Bundle mOutState;
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseReference;
private ProgressBar mProgressBar;
private OnItemClickListener mOnItemClickListener;
private FloatingActionButton mFab;
private RecyclerView mRecyclerViewPaper;
private ArrayList<Paper> mPaperList = new ArrayList<>();
private Subject mSubject = new Subject();
private Exam mExam = new Exam();
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recycler_list, container, false);
mProgressBar = (ProgressBar) rootView.findViewById(R.id.progressbar_news);
mFab = (FloatingActionButton) rootView.findViewById(R.id.floatingActionButton);
mProgressBar.setVisibility(View.VISIBLE);
Log.d(TAG, "onCreateView: Fragment created");
mAuth = FirebaseAuth.getInstance();
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
if (mAuth.getCurrentUser() == null) {
startActivity(new Intent(getActivity(), LoginActivity.class));
getActivity().finish();
return null;
}
if (getArguments() != null) {
mOnFragmentActiveListener = (OnFragmentActiveListener) getArguments().getSerializable(Keys.FRAGMENT_ACTIVE_LISTENER);
mSubject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
mExam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
}
mRecyclerViewPaper = (RecyclerView) rootView.findViewById(R.id.recycler_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()) {
#Override
public boolean canScrollVertically() {
return false;
}
};
mRecyclerViewPaper.setLayoutManager(layoutManager);
Log.d(TAG, "onCreateView: Layout Manager Set.");
mFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startAddPaperFragment();
}
});
mOnItemClickListener = new OnItemClickListener() {
#Override
public void onItemClicked(RecyclerView.ViewHolder holder, int position) {
Log.d(TAG, "onItemClicked: Clicked item position is: "+ position);
QuestionListFragment questionFragment = new QuestionListFragment();
questionFragment.setRetainInstance(true);
startFragment(position, questionFragment, QUESTIONS_FRAGMENT_TAG);
}
#Override
public void OnItemLongClicked(RecyclerView.ViewHolder holder, int position) {
}
};
mHeadingText = (TextView) rootView.findViewById(R.id.heading_textview);
mHeadingText.setText(mExam.getExam_name()+" > "+ mSubject.getSubject_name());
if (mOutState != null) {
mPaperList = (ArrayList<Paper>) mOutState.getSerializable(Keys.PAPER_LIST_KEY);
updateUI();
} else {
updateUIFromDatabase();
}
return rootView;
}
private void startFragment(int position, Fragment fragment, String fragmentTag) {
Paper paper = new Paper();
if (mPaperList.size() > 0) {
paper = mPaperList.get(position);
}
Bundle args = new Bundle();
args.putSerializable(Keys.EXAMS_KEY, mExam);
args.putSerializable(Keys.SUBJECT_KEY, mSubject);
args.putSerializable(Keys.PAPER, paper);
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
fragmentTransaction.replace(R.id.questions_fragment_container, fragment, fragmentTag);
fragmentTransaction.addToBackStack(fragmentTag);
fragmentTransaction.commit();
}
private void startAddPaperFragment() {
AddPaperFragment addPaperFragment = new AddPaperFragment();
addPaperFragment.setRetainInstance(true);
startFragment(0, addPaperFragment, ADD_PAPER_FRAGMENT_TAG);
}
private void updateUIFromDatabase() {
if (getArguments() != null){
Exam exam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
Subject subject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
DatabaseReference paperReference =
mDatabaseReference
.child(Keys.APP_DATA_KEY)
.child(Keys.EXAM_PAPERS)
.child(exam.getExam_name())
.child(subject.getSubject_name());
Query query = paperReference.orderByChild(Keys.TIME_ADDED);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPaperList.clear();
for (DataSnapshot paperChild : dataSnapshot.getChildren()) {
mPaperList.add(paperChild.getValue(Paper.class));
}
updateUI();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
private void updateUI() {
PaperRecyclerAdapter adapter = new PaperRecyclerAdapter(
getActivity(),
mRecyclerViewPaper,
mPaperList,
mOnItemClickListener
);
mRecyclerViewPaper.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onResume() {
super.onResume();
if (getArguments()!=null){
mOnFragmentActiveListener.onFragmentActive(
this,
"Topics"
);
}
}
#Override
public void onPause() {
super.onPause();
mOutState = new Bundle();
mOutState.putSerializable(Keys.PAPER_LIST_KEY, mPaperList);
}
}
Exception:
2018-12-26 17:49:38.344 14834-14834/in.crazybytes.bankmaniaadmin E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.crazybytes.bankmaniaadmin, PID: 14834
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = in.crazybytes.bankmaniaadmin.activities.QuestionsActivity)
at android.os.Parcel.writeSerializable(Parcel.java:1526)
at android.os.Parcel.writeValue(Parcel.java:1474)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
at android.os.Parcel.writeTypedArray(Parcel.java:1306)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
at android.os.Parcel.writeParcelable(Parcel.java:1495)
at android.os.Parcel.writeValue(Parcel.java:1401)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.io.NotSerializableException: com.google.firebase.auth.internal.zzj
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at android.os.Parcel.writeSerializable(Parcel.java:1521)
at android.os.Parcel.writeValue(Parcel.java:1474) 
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723) 
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 
at android.os.Bundle.writeToParcel(Bundle.java:1133) 
at android.os.Parcel.writeBundle(Parcel.java:763) 
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124) 
at android.os.Parcel.writeTypedArray(Parcel.java:1306) 
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639) 
at android.os.Parcel.writeParcelable(Parcel.java:1495) 
at android.os.Parcel.writeValue(Parcel.java:1401) 
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723) 
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 
at android.os.Bundle.writeToParcel(Bundle.java:1133) 
at android.os.Parcel.writeBundle(Parcel.java:763) 
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697) 
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768) 
at android.os.Handler.handleCallback(Handler.java:751) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6123) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Note: The weird thing is that one of fragment has the exact same code and is hosted inside the same activity, but when that fragment is active and app goes to background, interestingly the app is not crashing. 
**Exam Model Class:
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Exam implements Serializable {
private String mExam_name;
private String mExam_key;
private Long mTime_added;
private int mNum_subjects;
private int mNum_questions;
public Exam(String exam_name, String exam_key, Long time_added, int num_subjects, int num_questions) {
mExam_name = exam_name;
mExam_key = exam_key;
mTime_added = time_added;
mNum_subjects = num_subjects;
mNum_questions = num_questions;
}
public Exam() {
}
public String getExam_name() {
return mExam_name;
}
public void setExam_name(String exam_name) {
mExam_name = exam_name;
}
public String getExam_key() {
return mExam_key;
}
public void setExam_key(String exam_key) {
mExam_key = exam_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_subjects() {
return mNum_subjects;
}
public void setNum_subjects(int num_subjects) {
mNum_subjects = num_subjects;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
}
Paper Model Class
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Paper implements Serializable {
private String mPaper_name;
private String mPaper_key;
private Long mTime_added;
private int mNum_questions;
public Paper(String paper_name, String paper_key, Long time_added, int num_questions) {
mPaper_name = paper_name;
mPaper_key = paper_key;
mTime_added = time_added;
mNum_questions = num_questions;
}
public Paper() {
}
public String getPaper_key() {
return mPaper_key;
}
public void setPaper_key(String paper_key) {
mPaper_key = paper_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
public String getPaper_name() {
return mPaper_name;
}
public void setPaper_name(String paper_name) {
mPaper_name = paper_name;
}
}
Subject Model Class:
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Subject implements Serializable {
private String mSubject_name;
private String mSubject_key;
private Long mTime_added;
private int mNum_papers;
private int mNum_questions;
public Subject(String subject_name, String subject_key, Long time_added, int num_papers, int num_questions) {
mSubject_name = subject_name;
mSubject_key = subject_key;
mTime_added = time_added;
mNum_papers = num_papers;
mNum_questions = num_questions;
}
public Subject() {
}
public String getSubject_name() {
return mSubject_name;
}
public void setSubject_name(String subject_name) {
mSubject_name = subject_name;
}
public String getSubject_key() {
return mSubject_key;
}
public void setSubject_key(String subject_key) {
mSubject_key = subject_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_papers() {
return mNum_papers;
}
public void setNum_papers(int num_papers) {
mNum_papers = num_papers;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
}
Somehow QuestionsActivity is getting into the fragment save state, even if you don't intend for that to happen. While QuestionsActivity is being serialized, another object that is not serializable is being encountered. That's why you see TextViews and other things attempting to get serialized because all the instance variables of QuestionsActivity get serialized by default.
My best guess for why this is happening is due to this line:
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
But it's difficult to know for sure without seeing where OnFragmentActiveListener is defined. I'm assuming either QuestionsActivity implements OnFragmentActiveListener, or QuestionsActivity defines OnFragmentActiveListener as an inner class. Either way, if you put an OnFragmentActiveListener into fragment arguments, you will encounter an exception because you indirectly are storing the entire QuestionsActivity as a fragment arg too. When a fragment stops, all fragment args become part of the fragment save state. And that's the cause of the error.
I would suggest not passing the OnFragmentActiveListener around as a fragment arg. If the OnFragmentActiveListener comes from the activity, just use getActivity() to get a reference to the activity and then get a reference to the listener.
I also noticed PaperListFragment implements Serializable and I'm assuming you did the same thing for QuestionsActivity. You probably did this to get around compile errors. But this has led to runtime errors because the instance variables on both of these classes are not all serializable. So to avoid more runtime issues, I would suggest never having activities or fragments implement serializable because these classes are inherently not serializable due to their members.

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

Parcelable list inside Parcelable class not reading back with Parcel.readTypedList

I have two Activities, A and B. I am trying to send object from Activity A, to Activity B. When in Activity A, I can see that my List contains two items, but when I retrieve it in Activity B, the List contains 7000000+ records.
Here is my Assessment class, that implements Parcelable, and contains an ArrayList<Photo> which should be parcelable as well.
Assessment POJO:
public class Assessment extends BaseObservable implements Parcelable {
public Assessment(){
}
#SerializedName("Vehicle")
private String vehicle;
#SerializedName("Photos")
private List<Photo> photos;
#Bindable
public String getVehicle() {
return vehicle;
}
public void setVehicle(String vehicle) {
this.vehicle = vehicle;
notifyPropertyChanged(BR.vehicle);
}
public List<Photo> getPhotos() {
return photos;
}
public void setPhotos(List<Photo> photos) {
this.photos = photos;
}
protected Assessment(Parcel in) {
vehicle = in.readString();
photos = new ArrayList<Photo>();
in.readTypedList(photos, Photo.CREATOR);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(vehicle);
dest.writeTypedList(photos);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Assessment> CREATOR = new Parcelable.Creator<Assessment>() {
#Override
public Assessment createFromParcel(Parcel in) {
return new Assessment(in);
}
#Override
public Assessment[] newArray(int size) {
return new Assessment[size];
}
};
}
Photo POJO:
public class Photo implements Parcelable {
public Photo(){
}
#SerializedName("PhotoPath")
private String photoPath;
public String getPhotoPath() {
return photoPath;
}
public void setPhotoPath(String photoPath) {
this.photoPath = photoPath;
}
#SerializedName("Base64PhotoString")
private String photoBase64String;
public String getPhotoBase64String() {
return photoBase64String;
}
public void setPhotoBase64String(String photoBase64String) {
this.photoBase64String = photoBase64String;
}
protected Photo(Parcel in) {
photoPath = in.readString();
photoBase64String = in.readString();
}
//region parelable
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(photoPath);
dest.writeString(photoBase64String);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Photo> CREATOR = new Parcelable.Creator<Photo>() {
#Override
public Photo createFromParcel(Parcel in) {
return new Photo(in);
}
#Override
public Photo[] newArray(int size) {
return new Photo[size];
}
};
//endregion
}
Here is how I send the object via Intent from Activity A, to Activity B:
public void OnAdapterItemClicked(View view){
Intent activityIntent = new Intent(this, com.example.andrewkp.gaassessing.DisplayAssessment.class);
Assessment extraAssessment = getAssessmentFromCollection(view); //extraAssessment.getPhotos().size() == 2
activityIntent.putExtra("assessment", extraAssessment);
startActivity(activityIntent);
}
And here is how I read the Parcelable object in Activity B:
assessment = getIntent().getExtras().getParcelable("assessment");
I have looked at the following article, and I follow exactly what they do, but my photos list does not persist through to Activity B:
When I debug the readTypedList method in Parcel class, I can see that it adds 7000000+ records to my ArrayList, but never removes them. Why is this behavior happening?
You are able to put up to 1MB of data in a Bundle encapsulated inside Intent.
You will get bunch of errors when sending PhotoBase64String in Bundle.
However, in order to overcome this issue, I would suggest path/URI of your photo to your second activity. Then in your second activity, read photo from that path, and perform your desired operation.

Categories