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);
}
}
Related
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);
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.
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
I want to store the data in a ArrayList and access it in another class,but when when I access the arraylist,the arraylist.size() is 0.Means I didn't access the same arraylist. Somebody please tell me what I doing wrong.
Here is my POJO class
public class item {
private String name;
private String body;
private String profileImage;
public Item(){
}
public Item(String body,String name,String profileImage){
this.body = body;
this.name = name;
this.profileImage = profileImage;
}
//Getter and setter
Here is how I store the data in Class A,which I checked,is successfully insert it to the arraylist.
Class A
List<Item> items = new ArrayList<>();
Item item = new Item();
item.setBody(body);
item.setName(name);
item.setProfileImage(profileImage);
items.add(item);
The problem is in Class B when I access the item.size() it return value 0,means that I didnt access to the same arraylist.
Here is what I done in Class B
List<Item>items = new ArrayList<>();
Log.d("ListSize",String.valueOf(items.size()));
I tried this which I done in RecycleView before,but this doesnt work,cause my Class B is a Fragment activity
public Class B(Context mContext, List<Item> items) {
this.mContext = mContext;
this.items = items;
}
So what is the correct way for me initialize the arraylist which I save data to in Class A in Class B?
change class like this:
public class Item implements Parcelable{
private String name;
private String body;
private String profileImage;
public Item(){
}
public Item(Parcel in) {
name = in.readString();
body = in.readString();
profileImage = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(body);
dest.writeString(profileImage);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Item> CREATOR = new Parcelable.Creator<Item>() {
#Override
public Item createFromParcel(Parcel in) {
return new Item(in);
}
#Override
public Item[] newArray(int size) {
return new Item[size];
}
};
public Item(String body,String name,String profileImage){
this.body = body;
this.name = name;
this.profileImage = profileImage;
}
Now in Class A:
ArrayList<Item> mDATA = new ArrayList<>();
/****** add values in array list ****/
Intent i = new Intent(CLASS_A.this, CLASS_B.class);
i.putParcelableArrayListExtra("ARRAY_DATA", mDATA);
startActivity(i);
Now in Class B, get list:
Intent intent = getIntent();
ArrayList<Item> mDATAFROMA = new ArrayList<>();
try {
mDATAFROMA = intent.getParcelableArrayListExtra("ARRAY_DATA");
Log.d("ListSize",String.valueOf(mDATAFROMA.size()));
} catch (Exception e) {
e.printStackTrace();
}
For fragement pass like:
Bundle args = new Bundle();
args.putParcelableArrayList("GET_LIST", (ArrayList<? extends Parcelable>) mDATA);
fragmentDemo.setArguments(args);
And in fragment fetch:
ArrayList<Item> mDATAFROMA = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle pb=getArguments();
mDATAFROMA = pb.getParcelableArrayList("GET_LIST");
}
I have an ArrayList of a custom object. This ArrayList I pass to my RecyclerView Adapter. When an event occurs I need to retrieve the object from the ArrayList that contains a variable with a unique value, make changes to that object and then reload the ViewHolder corresponding to that object. How do I achieve this?
The problem is that I don't have the position of the object within the ArrayList because the positions keep changing dynamically. I just have this unique value corresponding to a object on the basis of which I want to make changes.
I tried doing list.clear() then reassigning objects to the ArrayList with the updated values and then calling adapter.notifyDataSetChanged() but it didn't work.
EDIT:
I have provided the code below of the Activity which contains the recyclerview. The actual code is much larger so I decided to edit it to only show the necessary details regarding this question. Please let me know if I need to add more code.
So, basically what happens here is that IMActivity is bound to a service and passes its context to the service while binding. When an event occurs in the service a database value is changed and updateActivity() is called in the service.
What I want updateActivity() to do is to check the chatMsgList for a ChatMsg object that contains a variable that has a unique value and reload the viewholder corresponding to that ChatMsg object.
Please let me know if I need to clarify further.
public class IMActivity extends AppCompatActivity implements Sertivity {
private RecyclerView recyclerView;
private ImAdapter imAdapter;
private List<ChatMsg> chatMsgList = new ArrayList<>();
EditText etIM;
ImageButton ibSend;
TalkSeeService.TalkSeeBinder talkSeeBinder;
String usernames[]= new String[10];
String otherUserName;
List<Msg> msgList;
DBAct db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService(new Intent(com.abdralabs.talksee.IMActivity.this, TalkSeeService.class), new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
talkSeeBinder = (TalkSeeService.TalkSeeBinder)service;
talkSeeBinder.setSertivity(com.abdralabs.talksee.IMActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name) {
talkSeeBinder.setSertivity(null);
talkSeeBinder = null;
}
},BIND_AUTO_CREATE);
setContentView(R.layout.activity_im);
recyclerView = (RecyclerView)findViewById(R.id.rv_im);
imAdapter = new ImAdapter(chatMsgList);
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
layoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(imAdapter);
ibSend = (ImageButton)findViewById(R.id.ib_send);
etIM = (EditText)findViewById(R.id.et_im);
ibSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//THE TEXT FROM THE EDITTEXT IS TAKEN AND THEN ADDED TO THE DATABASE
updateChatData();
}
});
db = new DBAct(com.abdralabs.talksee.IMActivity.this,otherUserName);
msgList = db.getAllMessages();
db.close();
prepareChatData();
}
private void prepareChatData() {
for (int i=0; i<msgList.size(); i++) {
ChatMsg chatMsg = new ChatMsg(msgList.get(i).getMessage(),
convertToDayDateTime(Long.valueOf(msgList.get(i).getTime())),
msgList.get(i).getOther(),
getReceiptFromDelivered(i));
chatMsgList.add(chatMsg);
}
imAdapter.notifyDataSetChanged();
}
private void updateChatData(){
msgList = db.getAllMessages();
db.close();
int i = msgList.size() - 1;
ChatMsg chatMsg = new ChatMsg(msgList.get(i).getMessage(),
convertToDayDateTime(Long.valueOf(msgList.get(i).getTime())),
msgList.get(i).getOther(),
getReceiptFromDelivered(i));
chatMsgList.add(chatMsg);
imAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(imAdapter.getItemCount());
}
#Override
public void updateActivity() {
chatMsgList.clear();
prepareChatData();
recyclerView.smoothScrollToPosition(imAdapter.getItemCount());
}
#Override
public void callActivityMethod() {
updateChatData();
}
private String convertToDayDateTime(long timestamp){
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();
SimpleDateFormat sdf = new SimpleDateFormat("EEE dd/MM/yyyy HH:mm");
sdf.setTimeZone(tz);
String localTime = sdf.format(new Date(timestamp));
return localTime;
}
private String getReceiptFromDelivered(int position){
String receipt;
if (msgList.get(position).getDelivered().equals("0")){
receipt = "...";
}else {
receipt = "S";
}
return receipt;
}
}
IMAdapter.java
public class ImAdapter extends RecyclerView.Adapter <RecyclerView.ViewHolder> {
private List<ChatMsg> chatMsgList = new ArrayList<ChatMsg>();
final int VIEW_TYPE_USER = 1;
final int VIEW_TYPE_OTHER = 0;
public ImAdapter(List<ChatMsg> chatMsgList){
this.chatMsgList = chatMsgList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType==VIEW_TYPE_USER){
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_msg_user,parent,false);
return new ImUserViewHolder(itemView);
}
else {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_msg_other,parent,false);
return new ImOtherViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType()==VIEW_TYPE_USER){
ChatMsg chatMsg = chatMsgList.get(position);
ImUserViewHolder imUserViewHolder = (ImUserViewHolder)holder;
imUserViewHolder.msg.setText(chatMsg.getMsg());
imUserViewHolder.timeStamp.setText(chatMsg.getTime());
}
else {
ChatMsg chatMsg = chatMsgList.get(position);
ImOtherViewHolder imOtherViewHolder = (ImOtherViewHolder) holder;
imOtherViewHolder.msg.setText(chatMsg.getMsg());
imOtherViewHolder.timeStamp.setText(chatMsg.getTime());
}
}
#Override
public int getItemViewType(int position) {
ChatMsg chatMsg = chatMsgList.get(position);
if (chatMsg.getOther().equals("true")){
return VIEW_TYPE_OTHER;
}
else {
return VIEW_TYPE_USER;
}
}
#Override
public int getItemCount() {
return chatMsgList.size();
}
public class ImOtherViewHolder extends RecyclerView.ViewHolder{
public TextView msg;
public TextView timeStamp;
public ImOtherViewHolder(View itemView) {
super(itemView);
msg = (TextView)itemView.findViewById(R.id.tv_chat_msg_other);
timeStamp = (TextView)itemView.findViewById(R.id.tv_time_chat_msg_other);
}
}
public class ImUserViewHolder extends RecyclerView.ViewHolder{
public TextView msg;
public TextView timeStamp;
public ImUserViewHolder(View itemView) {
super(itemView);
msg = (TextView)itemView.findViewById(R.id.tv_chat_msg_user);
timeStamp = (TextView)itemView.findViewById(R.id.tv_time_chat_msg_user);
}
}
}
To you IMAdapter add method
public void setChatMsgList(List<ChatMsg> chatMsgList ) {
this.chatMsgList = chatMsgList;
}
and in your IMActivity in method prepareChatData call this new setChatMsgList method
{
...
chatMsgList.add(chatMsg);
}
imAdapter.setChatMsgList(chatMsgList);
imAdapter.notifyDataSetChanged();