DEV Community

Panda Quests
Panda Quests

Posted on

How to persistently saving custom objects in Android

This post was first published on my blog

In almost any app you need to persistently save custom information in your app and later load it and display it to the user. Unfortunately Android doesn’t provide you this functionality out of the box. Therefore in this tutorial, I’ll show you how to create an app that persistently saves custom objects with gson.

The technologies I’ll use are as follows:

Android studio
android 28
gson
gradle
This article is mainly based on this post. But because some API have changed, you won’t be able to create an app if you follow the above mentioned tutorial. It took me a while to get it going. In order to save you time, I create this tutorial for you. Also I added some additional information that was not mentioned in my above mentioned reference post and that may be helpful for beginners.

First create a new app via android studio select the empty app template and call it e.g. MyApplication. Then add the following dependencies into your build.gradle file:

dependencies {
implementation 'com.android.support:design:28.0.+'
implementation 'com.google.code.gson:gson:2.8.5'
}

We need for our UI some designs that is not provided by the standard android SDK. Therefore we have to add the design dependency:
implementation com.android.support:design:28.0+

Google provides you with gson methods you can use to serialize and deserialize java objects: https://github.com/google/gson

Mind you, the number 28 in i.e. com.android.support:design:28.9.+ refers to your target SDK version. make sure that these are always the same number. In my example it’s 28. Your’s may differ. In order to know which target version you are using, you can also check in your gradle-file:

android {
compileSdkVersion 28
defaultConfig {
...
targetSdkVersion 28
...
}
}

Once you have added the above dependencies, click on the “sync” (at the top right corner) so gradle can download the needed dependencies.

The next step is to design our main layout. We want two input fields where we type in some data (that we will later save) and two buttons: Insert and save. The Insert button inserts our newly created object into the list displayed in the main view. The save button saves it persistently on our app. In the layout folder write inside the activity_main.xml file this:

`<?xml version="1.0" encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="de.pandaquests.myapplication.MainActivity">

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="100dp"
    android:background="@android:color/darker_gray" />

<EditText
    android:id="@+id/edittext_line_1"
    android:layout_width="180dp"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_alignParentBottom="true"
    android:layout_marginBottom="52dp"
    android:hint="Line 1" />

<EditText
    android:id="@+id/edittext_line_2"
    android:layout_width="180dp"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_alignParentBottom="true"
    android:hint="Line 2" />

<Button
    android:id="@+id/button_insert"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignTop="@id/edittext_line_1"
    android:layout_marginStart="13dp"
    android:layout_marginTop="23dp"
    android:layout_toEndOf="@id/edittext_line_1"
    android:text="insert" />

<Button
    android:id="@+id/button_save"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@id/button_insert"
    android:layout_toEndOf="@+id/button_insert"
    android:text="save" />
Enter fullscreen mode Exit fullscreen mode

`

Next is we create the UI for our custom element. The custom element represents the data we insert into the list. Create in the layout folder a file named example_item.xml by right clicking and choose new -> Layout resource file. Write example_item.xml as the name and ignore the rest, because we will overwrite everything inside of that file with the following code inside of it:

`<?xml version="1.0" encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="4dp">

    <TextView
        android:id="@+id/textview_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Line 1"
        android:textColor="@android:color/black"
        android:textSize="20sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textview_line_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textview_line1"
        android:layout_marginStart="8dp"
        android:text="Line 2"
        android:textSize="15sp" />

</RelativeLayout>
Enter fullscreen mode Exit fullscreen mode

`

Once we are done with that, we will create the needed functionality for our main activity. Inside the MainActivity.java file write the following:

`package de.pandaquests.myapplication;

import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

ArrayList<ExampleItem> mExampleList;
private RecyclerView mRecyclerView;
private ExampleAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    loadData();
    buildRecyclerView();
    setInsertButton();

    Button buttonSave = findViewById(R.id.button_save);
    buttonSave.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            saveData();
        }
    });
}

private void saveData() {
    SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    Gson gson = new Gson();
    String json = gson.toJson(mExampleList);
    editor.putString("task list", json);
    editor.apply();
}

private void loadData() {
    SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString("task list", null);
    Type type = new TypeToken<ArrayList<ExampleItem>>() {}.getType();
    mExampleList = gson.fromJson(json, type);

    if (mExampleList == null) {
        mExampleList = new ArrayList<>();
    }
}

private void buildRecyclerView() {
    mRecyclerView = findViewById(R.id.recyclerview);
    mRecyclerView.setHasFixedSize(true);
    mLayoutManager = new LinearLayoutManager(this);
    mAdapter = new ExampleAdapter(mExampleList);

    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.setAdapter(mAdapter);
}

private void setInsertButton() {
    Button buttonInsert = findViewById(R.id.button_insert);
    buttonInsert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EditText line1 = findViewById(R.id.edittext_line_1);
            EditText line2 = findViewById(R.id.edittext_line_2);
            insertItem(line1.getText().toString(), line2.getText().toString());
        }
    });
}

private void insertItem(String line1, String line2) {
    mExampleList.add(new ExampleItem(line1, line2));
    mAdapter.notifyItemInserted(mExampleList.size());
}
Enter fullscreen mode Exit fullscreen mode

}`

You’ll probably see lots of errors. But don’t worry it’s because there are still files missing. Next we create the ExampleAdapter.java. Create in your project folder (the folder where also your MainActivity.java file is) a file named ExampleAdapter.java

`package de.pandaquests.myapplication;

import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;

public class ExampleAdapter extends RecyclerView.Adapter {
private ArrayList mExampleList;

public static class ExampleViewHolder extends RecyclerView.ViewHolder {
    public TextView mTextViewLine1;
    public TextView mTextViewLine2;

    public ExampleViewHolder(View itemView) {
        super(itemView);
        mTextViewLine1 = itemView.findViewById(R.id.textview_line1);
        mTextViewLine2 = itemView.findViewById(R.id.textview_line_2);
    }
}

public ExampleAdapter(ArrayList<ExampleItem> exampleList) {
    mExampleList = exampleList;
}

@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
    ExampleViewHolder evh = new ExampleViewHolder(v);
    return evh;
}

@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
    ExampleItem currentItem = mExampleList.get(position);

    holder.mTextViewLine1.setText(currentItem.getLine1());
    holder.mTextViewLine2.setText(currentItem.getLine2());
}

@Override
public int getItemCount() {
    return mExampleList.size();
}
Enter fullscreen mode Exit fullscreen mode

}`

Now we only need our custom Object. Let’s create ExampleItem.java file in your project folder and paste in the following code:

`package de.pandaquests.myapplication;
public class ExampleItem {
private String mLine1;
private String mLine2;

public ExampleItem(String line1, String line2) {
    mLine1 = line1;
    mLine2 = line2;
}

public String getLine1() {
    return mLine1;
}

public String getLine2() {
    return mLine2;
}
Enter fullscreen mode Exit fullscreen mode

}`

We should now be set. Press on run and you should see a working sample app that saves custom data.

You can download the whole app here from my gitHub and tweak it as you like. Use it as a base for your own projects.

If you used the code I provided, then tell my what projects you intend to implement or already implemented. I’m really curious to know. So long.

More details can be found in the original article. If you want to know more, drop a line or follow me here or on my tech blog.

Top comments (0)