1

I have Looked around here on StackOverflow and the internet and tried a few things but all of them are giving me the same general problem.

I have an ArrayList that I create in one activity and then send it through (another activity or 2 others depending on the users choices) and in each activity (including the one that the arraylist is created in) has the user select a single button from a group. Upon selecting the button I have a listener that creates a simple string and then adds that String to the ArrayList, or at least that's what I want it to do.

  1. I have tried using Serialized classes to pass the same list through all the activities it needs to go through
  2. I have tried making a new ArrayList in each class, copying the one from the previous class that was sent via an intent.putExtra() and then received so it could be copied into a new arraylist to do the same thing until it gets to the final Activity.
  3. I have tried to make sense of Parcleable implementation but It just seems like to much for me (I'm not to good at this right now).

All of these have given me the same NullPointerException whenever I try and use the .add() method of the ArrayList (or the .addAll() in terms of the second attempt to get this done.

Any suggestions along with explanations you would have to give to a beginner would be greatly appreciated! I can put code if needed!!

Gareth Davidson
  • 4,857
  • 2
  • 26
  • 45
KellysOnTop23
  • 1,325
  • 2
  • 15
  • 34
  • maybe this could help http://stackoverflow.com/questions/4780835/pass-arraylist-from-one-activity-to-other – Elliot Landry Jul 28 '14 at 19:30
  • You need to post your code and LogCat so we can see why it's happening. No one here has magic wand to know what's happening without any piece of code. – Shumail Jul 28 '14 at 19:37
  • Check this answer http://stackoverflow.com/a/5374603/3820750 maybe can help you. – merryrppin Jul 28 '14 at 19:39
  • I don't think you need `Parcelable` if you don't have `ArrayList` of custom objects. The reason you are getting `NullPointerException` might be related to your `Activity` life cycle. Make sure you copy/create your instances in right method and don't forget when you switch activity, you previous Activity might be killed and you might have data loss. – Gokhan Arik Jul 28 '14 at 19:46
  • You don't need to understand the Parcelable implementation, you just need to throw it into the http://parcelabler.com and get an automatic implementation just like that – EpicPandaForce Jul 28 '14 at 20:02
  • Personally I'd just hold the `ArrayList` in a Singleton helper class but that's just my personal choice for shared objects. – Squonk Jul 28 '14 at 20:04
  • This by the way is a relevant question so I linked it: http://stackoverflow.com/questions/13601883/how-to-pass-arraylist-of-objects-from-one-to-another-activity-using-intent-in-an – EpicPandaForce Jul 28 '14 at 20:04

4 Answers4

3

First thing, you should use Parcelable, it is more efficient in this case. Have a look at this link for the "why":
https://medium.com/@theblackcat102/passing-object-between-activity-using-gson-7dfa11d74e06

Second, I'd do it like this:

public class ActivityOne extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_one);
        Intent intent = new Intent(this, ActivityTwo.class);
        ArrayList<Person> strings = new ArrayList<Person>(Arrays.asList(new Person("Bob"),new Person("Dude")));
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList(ActivityTwo.PARCELABLE_KEY,strings);
        intent.putExtras(bundle);
        startActivity(intent);
    }
}


public class ActivityTwo extends Activity {
    public static final String PARCELABLE_KEY = "array_key";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);
        if (getIntent() != null) {
            ArrayList<Person> persons = getIntent().getParcelableArrayListExtra(PARCELABLE_KEY);
            Log.d("test", persons.toString());
        }
    }
}

public class Person implements Parcelable {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel source) {
            return new Person(source);
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    private Person(Parcel in) {
        this.name = in.readString();
    }
}

Also, do not be afraid of Parcelables! And as a good developer, you should be lazy, then use a Parcelable generator such as:
http://www.parcelabler.com/

Just copy your POJO class(es) and generate (an Android Studio plugin also exists).

Finally, don't forget that you cannot pass unlimited data between 2 activities. You could also consider putting your data into a database.

Pang
  • 9,564
  • 146
  • 81
  • 122
Rocel
  • 1,029
  • 1
  • 7
  • 22
  • This is your desired implementation if it's only being shared among a few activities. You won't run into any data corruption/sync problems, but yes, it will add a slightly unnoticeable overhead and some boilerplate. – Toguard Jul 28 '14 at 20:31
  • Thank you so much for this! I am convinced that Parcelable is the best way to go about this, but even after the generator and your example I am still lost, so for now I will have to go with the second answer which I have worked out to just copy the list to a new list in each activity. However I will revisit parcelables because I want what I making to be as efficient as possible! thanks again! – KellysOnTop23 Jul 31 '14 at 20:31
0

I put together a quick example of passing the array list to other activities and adding items to it.

public class FirstActivity extends Activity {

    public static final String EXTRA_FIRST_ARRAY = "ExtraFirstArray";

    private static final String TAG = FirstActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ArrayList<String> firstArrayList = new ArrayList<String>();

        firstArrayList.add("First Activity Test1");
        firstArrayList.add("First Activity Test2");
        firstArrayList.add("First Activity Test3");

        Log.d(TAG, "First Array List: ");

        for (String value : firstArrayList) {
            Log.d(TAG, "Value: " + value);
        }

        Intent intent = new Intent(this, SecondActivity.class);
        intent.putStringArrayListExtra(EXTRA_FIRST_ARRAY, firstArrayList);
        startActivity(intent);
    }
}

public class SecondActivity extends Activity {

    public static final String EXTRA_SECOND_ARRAY = "ExtraSecondArray";

    private static final String TAG = SecondActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getIntent().getExtras() != null) {

            final ArrayList<String> firstArrayList = getIntent().getStringArrayListExtra(FirstActivity.EXTRA_FIRST_ARRAY);

            ArrayList<String> secondArrayList = new ArrayList<String>();

            secondArrayList.addAll(firstArrayList);

            secondArrayList.add("Second Activity Test1");
            secondArrayList.add("Second Activity Test2");
            secondArrayList.add("Second Activity Test3");

            Log.d(TAG, "Second Array List: ");

            for (String value : secondArrayList) {
                Log.d(TAG, "Value: " + value);
            }

            Intent intent = new Intent(this, ThirdActivity.class);
            intent.putStringArrayListExtra(EXTRA_SECOND_ARRAY, secondArrayList);
            startActivity(intent);
        }
    }
}

public class ThirdActivity extends Activity {

    private static final String TAG = ThirdActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getIntent().getExtras() != null) {

            final ArrayList<String> secondArrayList = getIntent().getStringArrayListExtra(SecondActivity.EXTRA_SECOND_ARRAY);

            ArrayList<String> thirdArrayList = new ArrayList<String>();

            thirdArrayList.addAll(secondArrayList);

            thirdArrayList.add("Third Activity Test1");
            thirdArrayList.add("Third Activity Test2");
            thirdArrayList.add("Third Activity Test3");

            Log.d(TAG, "Third Array List: ");

            for (String value : thirdArrayList) {
                Log.d(TAG, "Value: " + value);
            }
        }
    }
}
Willie Nel
  • 363
  • 2
  • 9
  • Great example. My only suggestion would be to use startActivityForResult() in the calling Activities so that the list can be passed backwards, and then overriding finish() in the receiving ones to pass back the edited ArrayList when they exit so that the beginning Activity can see the changes made to the list (assuming that's necessary...) – Cruceo Jul 28 '14 at 20:13
0

If you have some data that you want to share among activities i would personally suggest that u keep them as a field on the application object so u would need to extend the application class.

public class MyApplication extend Application{

private List<SomeData> data;

@overrite
public void onCreate(){
super.onCreate();
data = new ArrayList<SomeData>();
}

public List<SomeData> getData(){

return data
}
}

In the manifest file you would have to configure ur application class in the application xml-tag

<application
android:name:"package.name.MyApplication">
</application>

Finally in ur activities you can access them by calling:

((MyApplication)getApplication()).getData();

In this way you dont consume resources on serializing/deserializing and you have access globally in the application context. Just pay attention to not overdo this as those data will occupy the memory independently from any activity. but if intend to persist some data which u will frequently access from different this is a optimized solution compare to serializing or passing through Parcelable interface.

eldjon
  • 2,800
  • 2
  • 20
  • 23
  • Many hiccups with this solution. I would advice against it unless: -You need something to be persisted while application context exists. It's mostly true while the app remains in Recents. -You control how the data is being modified. I've seen this get out of control whenever they expose a list that everyone has access to. You might run into data corruption/sync problems. So only do this when absolutely necessary, I would advice a Parcelable if you only need to send it from one activity to the other. – Toguard Jul 28 '14 at 20:28
  • well i find it quite good solution from the performance perspective. if you have thousands of items in a list parcelable becomes an expensive operations specifically when u have to access the data from different activities frequently. if the programmers know what they r doin there is no risk of going out of control. data sync problems might occur no matter what. its up to the programmer again – eldjon Jul 28 '14 at 20:39
  • Yes, It is quite useful for specific cases like the one you mentioned. When you have thousands of elements that need to be persisted across to a given amount activities. The overhead grows as the list grows. And I agree, it's up to the developer, many abuse Application object with really small data that is used by very few activities that may not even be used that often by users. And there's others that use it as a standard just for the sake of being lazy. So it's good to know when to use this approach. – Toguard Jul 28 '14 at 20:46
0

You can use also custom intent :

public class SharedIntent extends Intent {
    private List list;

    public void putArrayList(List list){
        this.list = list;
    }

    public List getList(){
        return list;
    }
}

Send :

public class SenderActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedIntent intent = new SharedIntent();
        intent.putArrayList(new ArrayList<String>());
    }
}

Retrieve :

public class GettingActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getIntent() instanceof SharedIntent) {
            SharedIntent intent = (SharedIntent) getIntent();
            ArrayList<String> list = (ArrayList<String>) intent.getList();
        }
    }
}
Sergey Shustikov
  • 15,377
  • 12
  • 67
  • 119
  • if i remember it correctly u cannot use custom intent. intents themselves are recreated within android so whatever custom u create its gonna be cast to Intent at a certain point. and on the other end the list wont exist – eldjon Jul 28 '14 at 19:57