Losing data when sending between two classes - java

My app doesn't display anything when passing data from one class to another. I located through with the debugger that my ArrayList doesn't get the right value from the class.
I'm sending data with the following function:
public class Adaugare extends AppCompatActivity {
private ListView myListView;
private NumeAdapter numeAdapter;
String inume;
int ivarsta;
Intent intent = new Intent();
private ArrayList persoanaArrayList = new ArrayList<>();
public ArrayList getPersoanaArrayList() {
return persoanaArrayList;
}
public int getPersoanaArrayListsize() {
return persoanaArrayList.size();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_adaugare);
myListView = (ListView) findViewById(R.id.persoana_list);
Button btn_fin = (Button) findViewById(R.id.btn_fin);
btn_fin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText nume_edit_text = (EditText) findViewById(R.id.ins_nume);
EditText varsta_edit_text = (EditText) findViewById(R.id.ins_var);
ivarsta = Integer.parseInt(varsta_edit_text.getText().toString());
inume = nume_edit_text.getText().toString();
persoanaArrayList.add(new Persoana(inume, ivarsta));
}
});
}
}
And recieving it with:
public class Afisare extends AppCompatActivity {
ListView myListView;
NumeAdapter numeAdapter;
Adaugare ad = new Adaugare();
int cate;
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_afisare);
myListView = (ListView) findViewById(R.id.persoana_list);
ArrayList<Persoana> persoanaArrayList = new ArrayList<Persoana>(ad.getPersoanaArrayList());
numeAdapter = new NumeAdapter(this, persoanaArrayList);
myListView.setAdapter(numeAdapter);
}
The class Persoana is:
public class Persoana {
private String nume;
private int varsta;
Persoana(String inume, int ivar) {
this.nume = inume;
this.varsta = ivar;
}
public String getNume() {
return nume;
}
public int getVarsta() {
return varsta;
}
public void setNume(String nume) {
this.nume = nume;
}
public void setVarsta(int varsta) {
this.varsta = varsta;
}
}
Persoana is the main class, everything is saved in it. ad is an object of Adaugare, Adaugare being the class from which I've taken the code for getPersoanaArrayList. At debugging some values appeared at ad, namely Adaugare #4556, and persoanaArrayList remains null.
I need the persoanaArrayList so that i can initialize my Adapter and listView. Everything else in the code seems fine from step by step testing with debugger.

Your problem is with the following line in the Afisare class:
Adaugare ad = new Adaugare();
You can't simply new one activity from another activity and expect to access a shared list between them. To share instance data between java objects you need a reference to the other object. Creating a new instance will create a new empty list. That's why you are "losing" data. A quick fix would be to make the list static so it can be accessed from any instance.
But since you're dealing with Android, the right way to share data between activities is by using intent extras. The first activity starts the second activity via an intent. The first activity places the desired data in the intent as extras. The second activity uses getIntent() and the various methods on Intent to access the extras.
One last tip, in Android, you never use the new operator with Activities. Activities are created by the system to service an intent. If you find yourself using the new operator, that's a sign that you're doing something wrong.

Related

how to store list of fragments using SharedPreferences

I'm using SharedPreferences to store a list of fragments of my android, however it gave me thousands lines of error which make non-sense:
2021-12-07 17:09:13.228 14833-14833/? E/AndroidRuntime: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1058)
at .......
(just small parts of error messages)
I tried to store a list of strings it works fine, but if I switch to an object with list of fragments it fails.
Here is my object.java:
public class CardList {
ArrayList<Card> list; //Card is my fragments
public CardList(ArrayList<Card> list) {
this.list = list;
}
public void updateList(Card c) {
list.add(c);
}
public int getListSize() {
return list.size();
}
}
here is my MainActivity.java, the new intent here was just to test if I can get my data back when I'm back to MainActivity
public class MainActivity extends AppCompatActivity {
public static final String WEATHER_PREFS = "weatherPrefs";
public CardList cardList;
public ArrayList<Card> cards;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cards = new ArrayList<>();
cardList = new CardList(cards);
SharedPreferences setting = getSharedPreferences(WEATHER_PREFS,MODE_PRIVATE);
Gson gson = new Gson();
String savedList = setting.getString("cardList","");
if (!savedList.equals("")) {
cardList = gson.fromJson(savedList,CardList.class);
}
Button btn= findViewById(R.id.switchActtivity);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
Gson gson = new Gson();
String savedInstanceString = gson.toJson(cardList);
SharedPreferences setting = getSharedPreferences(WEATHER_PREFS,MODE_PRIVATE);
SharedPreferences.Editor editor = setting.edit();
editor.putString("cardList",savedInstanceString);
editor.apply();
startActivity(intent);
}
});
Button increase = findViewById(R.id.increase);
increase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cardList.updateList(Card.newInstance("hello","world"));
Log.i("Array List Size After Click",String.valueOf(cardList.getListSize()));
}
});
}
}
Can someone teach me how to store custom object with an arraylist attribute in Android? Thanks in advance!
Fragments aren't serializable, meaning they can't be broken down into pure data ie JSON, much less deserializable.
Looking at your code there is no good way to just make it work either.
You need to follow separation of concerns, Fragments are glorified views. They shouldn't be holding information to any great extent, so they shouldn't be passed around as if they did.
What you could do is have a CardModel that contains all information needed for a Card Fragment.
The CardModel can contain simple data that you would find in JSON like Integer,String, etc...
A List<CardModel> can be deserialized from JSON. And then when you're in the MainActivity you could create as many Card Fragments as needed to represent the List<CardModel> with a simple list.size()

How to pass entire Arraylist to another activity

I am making a mp3 player app , in my main activity I am showing the list of all songs in recycler view and when user click on the song I am trying to send entire array list of songs to my player activity , where I can work for with next and previous songs play , but my app crashes when click the song
Process: com.choudhary.musicplayer, PID: 8686
java.lang.RuntimeException: Parcel: unable to marshal value com.choudhary.musicplayer.AudioModel#a0de380
at android.os.Parcel.writeValue(Parcel.java:1667)
at android.os.Parcel.writeList(Parcel.java:966)
at android.os.Parcel.writeValue(Parcel.java:1614)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:878)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1588)
at android.os.Bundle.writeToParcel(Bundle.java:1233)
at android.os.Parcel.writeBundle(Parcel.java:918)
at android.content.Intent.writeToParcel(Intent.java:9987)
at android.app.IActivityManager$Stub$Proxy.startActivity(IActivityManager.java:3636)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1675)
at android.app.Activity.startActivityForResult(Activity.java:4651)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:597)
at android.app.Activity.startActivityForResult(Activity.java:4609)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:583)
at android.app.Activity.startActivity(Activity.java:4970)
at android.app.Activity.startActivity(Activity.java:4938)
at com.choudhary.musicplayer.MusicAdapter$1.onClick(MusicAdapter.java:54)
at android.view.View.performClick(View.java:6608)
at android.view.View.performClickInternal(View.java:6585)
at android.view.View.access$3100(View.java:785)
at android.view.View$PerformClick.run(View.java:25921)
My Adapter's OnBind method :--
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.name.setText(arrayList.get(position).getaName());
holder.album.setText(arrayList.get(position).getaAlbum());
holder.imageView.setImageBitmap(BitmapFactory.decodeFile(arrayList.get(position).getAlbumart()));
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent in = new Intent(context,PlayerActivity.class);
in.putExtra("SONG",arrayList.get(position).getaName());
in.putExtra("PATH",arrayList.get(position).getaPath());
in.putExtra("ALBUM",arrayList.get(position).getaAlbum());
in.putExtra("LIST",arrayList);
in.putExtra("POSITION", arrayList.get(position).toString());
context.startActivity(in);
}
});
}
my Player Activity :---
public class PlayerActivity extends AppCompatActivity {
TextView songanme, songAlbum,duration,movetime;
ImageView playbutton,nextbtn,previousbtn;
SeekBar seekBar;
MediaPlayer mediaPlayer ;
ArrayList<AudioModel> list;
int CURRENT_POSITION ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
songanme = findViewById(R.id.music_name_pl);
movetime = findViewById(R.id.move_time);
seekBar = findViewById(R.id.seekBar);
songAlbum = findViewById(R.id.music_album_pl);
duration = findViewById(R.id.duration);
playbutton = findViewById(R.id.play_btn_pl);
nextbtn = findViewById(R.id.next_btn_pl);
previousbtn = findViewById(R.id.previous_pl);
list = new ArrayList<>();
songanme.setSelected(true);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
list = (ArrayList) bundle.getParcelableArrayList("LIST");
}
Let's assume that you want to pass an ArrayList of the Song class from Activity1 to Activity2.
1- The Song class should implement the Serializable class.
It would be something like that..
import java.io.Serializable;
public class Song implements Serializable {
String name;
String album;
public Song(String name, String album) {
this.name = name;
this.album = album;
}
}
2-In Activity1 pass your array list object as an extra to Ativity2
ArrayList<Song> songs= new ArrayList();
songs.add(new Song("song1","album1"));
songs.add(new Song("song2","album2"));
songs.add(new Song("song3","album3"));
Intent intent=new Intent(this,Activity2.class);
intent.putExtra("songs",songs);
startActivity(intent);
3- Finally receive the array list with getSerializableExtra in Activity2
ArrayList<Song> songs = (ArrayList<Song>) getIntent().getSerializableExtra("songs");
Log.i("HINT", "" + songs.size());
You can create a singleton class for sharing your ArrayList across various components of android. Sample code for the singleton class is described below-
public class SongBank
{
private static SongBank instance;
private ArrayList<Song> songsArrayList;
private SongBank(Context context)
{
// You can do any stuff if you want here
}
// create getter and setter methods for your arrayList
public void setSongsList(ArrayList<Song> songs)
{
if(songs!=null)
{
this.songsArrayList=songs;
}
}
public ArrayList<Song> getSongsList()
{
return this.songsArrayList;
}
public static SongBank getInstance(Context context)
{
if(instance==null)
{
instance=new SongBank(context);
}
return instance;
}
}
The instance of this singleton class can be called across various activities or fragments and you can also change the Arraylist value across different activities if you want. You can also call this class and get the list in your music service without worrying about serialization.

Android: Passing int value from one activity to another

I'm struggling to figure out why I can't pass an int value from one activity to another. The app will ask you to press a button to generate a random number from 1-100 which will be displayed below the button. There is also another button which will open a new activity simply showing the random number that was rolled... but I just get 0.
I've looked into similar questions asked but to no avail.
Here's my code from MainActivity
public class MainActivity extends ActionBarActivity {
int n;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void ButtonRoll(View view) {
TextView textRoll = (TextView) findViewById(R.id.textview_roll);
Random rand = new Random();
n = rand.nextInt(100) + 1;
String roll = String.valueOf(n);
textRoll.setText("Random number is " + roll);
}
public void OpenStats(View view) {
Intent getStats = new Intent(this, Stats.class);
startActivity(getStats);
}
public int GetNumber (){ return n; }
}
Heres my 2nd class.
public class Stats extends Activity {
MainActivity statistics = new MainActivity();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stats);
int n = statistics.GetNumber();
TextView tvStats = (TextView) findViewById(R.id.passedNumber_textview);
String number = String.valueOf(n);
tvStats.setText(number);
}
}
Is using getters the wrong way to get data from another class when using activities? Thanks for your time.
You should pass your data as an extra attached to your intent. To do this you need to first determine a global key to be used. You could do something like this in your MainActivity
public static final String SOME_KEY = "some_key";
then modify your OpenStats method to
public void OpenStats(View view) {
Intent getStats = new Intent(this, Stats.class);
getStats.putExtra(SOME_KEY, n);
startActivity(getStats);
}
and then in Stats.class onCreate method
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.stats);
int n = getIntent().getIntExtra(MainActivity.SOME_KEY, -1);
TextView tvStats = (TextView) findViewById(R.id.passedNumber_textview);
String number = String.valueOf(n);
tvStats.setText(number);
}
You obviously should make sure that you are calling ButtonRoll at least once or that you set n so that you aren't passing a null int.
Also, as note, convention states that methods should use lower camel case formatting. That is, the first word is completely lower case and the first letter of subsequent words is upper case. That would change your methods
OpenStats() -> openStats()
ButtonRoll() -> buttonRoll()
Classes/objects are upper camel case, just to help avoid confusion.

Passing string from class to main activity

I'm trying to pass something from one class to my MainActivity, but it doesn't seem to work, I don't understand why.
I have my GPS Tracker on another class (not the MainActivity) in order to reuse it.
When the location changes, I want my other class to call a method from within the MainActivity to update my UI.
I summarized my code like that :
My MAIN ACTIVITY :
public class MainActivity extends Activity implements OnClickListener {
TextView tv;
EditText et;
Button btun;
int arg0;
int stuff;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
et = (EditText) findViewById(R.id.et);
btun = (Button) findViewById(R.id.btun);
btun.setOnClickListener(this);
}
private void setter(int stuff) {
tv.setText(stuff);
}
public void setText(int _stuff) {
_stuff = stuff;
setter(_stuff);
}
#Override
public void onClick(View v) {
Getter get = new Getter();
get.getInfo(Integer.parseInt(et.getText().toString()));
}
The other Class :
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I end up having a NullPointerException in my LogCat
at :
- tv.setText(stuff);
- setter(_stuff);
- main.setText(_getString);
- get.getInfo(Integer.parseInt(et.getText().toString()));
and I don't really know why, and above all, how to fix it.
I'll appreciate any help !
(PS : My GPS tracker thingy is working fine, it's just about invoking my setter() method.
Instantiaing an Object of MainActivity doesn't automatically call onCreate method but this method is called when you start an activity using Intent; And using the same intent you can pass extra values. For example:
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("key", value);
context.startActivity(intent);
and then in your main activity onCreate method:
String value = getIntent.getStringExtra("key");
Edit:
In your case why don't you change your void getInfo(int getString) to return a String value i.e.
public class Getter {
...
...
public String getInfo(int getString) {
_getString = getString * 8;
return Integer.toString(_getString);
}
}
and then in onClick event of MainActivity bind this returned text to TextView
It's maybe because the MainActivity's onCreate()-Method hasn't been called. Therefore the tv is still null causing the NullPointerException
One problem is here. main is an Activity, but it should be the MainActivity calling this object.
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I cannot really make out what you are trying to achieve in the Getter class, but either:
1: Pass the Activity instance to the object
public class Getter {
int _getString;
MainActivity _main = null;
public Getter(MainActivity main) {
_main = main;
}
public void getInfo(int getString) {
_getString = getString * 8;
_main.setText(_getString);
}
}
#Override
public void onClick(View v) {
Getter get = new Getter(this);
get.getInfo(Integer.parseInt(et.getText().toString()));
}
or
2: set the text in the Activity and only get the value from the Getter (My choice)
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
return getString * 8;
}
}
#Override
public void onClick(View v) {
Getter get = new Getter();
int info = get.getInfo(Integer.parseInt(et.getText().toString()));
setText(Integer.toString(info));
}
Use Application Class or create a separate Class and declare a static variable in it. Use getter & setter methods to get the value. To update the Textview in mainacivity from other class pass the texview reference variable from main activity and put null check condition in other class if textview is not null then update the value.

get value from checkbox and show in other activity

I need get te value from checkbox and show in other activity and display in textview.
This is the code FormSupervisar.
public class FormSupervisar extends Activity {
CheckBox Si;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.formsupervisar);
Si=(CheckBox)findViewById(R.id.chBoxSi);
}
public void btnEnviar(View view){
if (Si.isChecked()){
Intent i = new Intent(this,FormBotonSi.class);
i.putExtra("Si",Si.getText().toString().trim());
startActivity(i);
}
}
The activity when i call the string and show the String in a TextView
public class FormBotonSi extends Activity {
private String ,Si ;
private TextView tvTipoInspeccion;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.formbotonsi);
Bundle bn1 = getIntent().getExtras();
Si = bn1.getString(Si);
tvTipoInspeccion.setText(Si.toString());
}
}
Try it this way.....
public class FormBotonSi extends Activity {
......
......
String Si = getIntent().getExtras().getString("Si"); // its "Si" instead of Si
}
One more thing... While you code in Java you must follow the Camel case. Field and Methods always starts with small letter whereas Class, Interface, Enums, Constructors starts with Capital letters.
use
Si = bn1.getString("Si");
instead of
Si = bn1.getString(Si);
for getting value in second activity because you are setting "Si" as key in first activity(in FormSupervisar)
OR
You can initialize Si String as:
private String Si="Si";
Si = bn1.getString(Si);

Categories