Search code examples
androidparcelable

How do I make a list of objects parcelable in Android?


So I have an app that searches for an artist on the internet, via an API and displays the list of the results (artist names) after performing this search at hand. I want to retain this list as I change the orientation (portrait - landscape) of my device and not having to perform the search again. Here is some code:

public class MainActivityFragment extends Fragment{

    public static final String ARTIST_ID = "artistId";
    private final String NO_RESULTS = "No artists found. Please check your input!";

    private List<Artist> artists = new ArrayList<>();
    private ArtistArrayAdapter adapter;

    public MainActivityFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        final SearchView searchView = (SearchView) rootView.findViewById(R.id.search_artist);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String artistName) {
                SearchArtist(artistName);
                InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0);
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });

        ListView listView = (ListView) rootView.findViewById(android.R.id.list);
        adapter = new ArtistArrayAdapter(getActivity(), R.layout.artist_list_item, artists);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Artist artist = artists.get(position);
                String artistId = artist.id;
                Intent detailArtist = new Intent(getActivity(), DetailActivity.class);
                detailArtist.putExtra(ARTIST_ID, artistId);
                startActivity(detailArtist);
            }
        });

        return rootView;
    }

So I think I have to make the List of artists parcelable and then pass it to the onSaveInstanceState method. But how do make this list parcelable?

Thanks a lot, I hope this isn't too confusing...


Solution

  • You'll need to implement the Parcelable Interface for your Artist Data Model class. For example

    public class ArtistParcelable implements Parcelable {
        public String id;
        public String artistName;
        public List<String> artistImageUrls = Collections.emptyList();
    
        public ArtistParcelable(Artist artist) {
            // Do the assignments here
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            //write 
            dest.writeString(this.id);
            dest.writeString(this.artistName);
            dest.writeStringList(this.artistImageUrls);
        }
    
        protected ArtistParcelable(Parcel in) {
            //retrieve
            this.id = in.readString();
            this.artistName = in.readString();
            this.artistImageUrls = in.createStringArrayList();
        }
    
        public static final Parcelable.Creator<ArtistParcelable> CREATOR = new Parcelable.Creator<ArtistParcelable>() {
            public ArtistParcelable createFromParcel(Parcel source) {
                return new ArtistParcelable(source);
            }
    
            public ArtistParcelable[] newArray(int size) {
                return new ArtistParcelable[size];
            }
        };
    }
    

    And in your fragment - if you have List mArtists, then you save and retrieve the list like

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList(ARTISTS, (ArrayList<? extends Parcelable>) mArtists);
    }
    

    And in onCreateView

    if (savedInstanceState != null) {
            mArtists = savedInstanceState.getParcelableArrayList(ARTISTS);
    

    Here's a good guide, which you can follow. https://guides.codepath.com/android/Using-Parcelable

    There's an IDE plugin called Android Parcelable Code Generator available also, which generates all the boilerplate code for you.

    And there's also a library called Parceler, which is pretty handy. It removes the boilerplate entirely.