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.
I'll use:
In it is mainly based on this post:
https://codinginflow.com/tutorials/android/save-arraylist-to-sharedpreferences-with-gson
But because some API has changed (for this have a look here: https://developer.android.com/jetpack/androidx/migrate/class-mappings) since then 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 time, I create this tutorial for you. Also I added some additional information that was not mentioned in my 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 "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.0.+' 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 alter 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"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" />
</RelativeLayout>
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 insdie of that file with the following code inside of it:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
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>
</androidx.cardview.widget.CardView>
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());
}
}
You'll probably see lots of erros. 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 MainActiviy.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<ExampleAdapter.ExampleViewHolder> {
private ArrayList<ExampleItem> 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();
}
}
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;
}
}
We should now be set. Press on run and you should see a working sample app that saves custom data.
If you like it, then please share it with others.
You can download the app here from my gitHub and tweak it as you like:
https://github.com/pandaquests/AndroidSaveData
Use it as a base for your own projects. If you want, then tell me what projects you intend or have done with. I'm really curious to know. So long
I'll use:
- Android studio
- android 28
- gson
- gradle
In it is mainly based on this post:
https://codinginflow.com/tutorials/android/save-arraylist-to-sharedpreferences-with-gson
But because some API has changed (for this have a look here: https://developer.android.com/jetpack/androidx/migrate/class-mappings) since then 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 time, I create this tutorial for you. Also I added some additional information that was not mentioned in my 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 "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.0.+' 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 alter 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"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" />
</RelativeLayout>
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 insdie of that file with the following code inside of it:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
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>
</androidx.cardview.widget.CardView>
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());
}
}
You'll probably see lots of erros. 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 MainActiviy.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<ExampleAdapter.ExampleViewHolder> {
private ArrayList<ExampleItem> 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();
}
}
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;
}
}
We should now be set. Press on run and you should see a working sample app that saves custom data.
If you like it, then please share it with others.
You can download the app here from my gitHub and tweak it as you like:
https://github.com/pandaquests/AndroidSaveData
Use it as a base for your own projects. If you want, then tell me what projects you intend or have done with. I'm really curious to know. So long