블로그 이사했습니다!
👇 블로그 이전 공지 👇
👇 새 블로그에서 글 보기 👇
[Android] SharedPreferences 데이터 저장하기 — Win Record (tistory.com)
코드는 리사이클러뷰 CRUD에서 이어집니다.
SharedPreferences
SharedPreferences를 사용하면 key-value 형태로 앱 내 데이터를 xml형태로 저장할 수 있다.
이때 저장할 수 있는 데이터 타입은 int, long, float, boolean, String, StringSet 이다.
SharedPreferences methods
// SharedPreferences 객체 생성
SharedPreferences sharedPreferences = getSharedPreferences("파일명", Context.MODE_PRIVATE);
// Editor 생성
SharedPreferences.Editor editor = sharedPreferences.edit();
// 데이터 추가 또는 수정
editor.putBoolean("데이터 키값", 데이터 내용);
editor.putFloat("데이터 키값", 데이터 내용);
editor.putInt("데이터 키값", 데이터 내용);
editor.putLong("데이터 키값", 데이터 내용);
editor.putString("데이터 키값", "데이터 내용");
editor.putStringSet("데이터 키값", 데이터 내용);
// 데이터 삭제
editor.remove("데이터 키값");
// 데이터 반영
editor.apply(); // apply() 해야만 변경 사항이 반영된다.
객체 저장하기
리사이클러뷰로 객체 리스트를 보여주기 위해서는 객체 자체를 저장해야 하는데,
저장할 수 있는 데이터 타입이 한정적이기 때문에 클래스로 만든 객체는 저장이 불가능하다.
따라서 객체의 정보를 String 타입으로 변환하고 이를 SharedPreferences를 이용해 저장한다.
- ApplicationClass.java
앱에서 사용하는 변수, 메소드 등
public class ApplicationClass extends Application {
static SharedPreferences sharedPreferences = null;
static SharedPreferences.Editor editor = null;
static final String MEMBER_DATA = "Member";
static final String MEMBER = "member";
static final String SEP = "@#!~";
@Override
public void onCreate() {
super.onCreate();
if (sharedPreferences == null) {
sharedPreferences = getApplicationContext().getSharedPreferences(MEMBER_DATA, Context.MODE_PRIVATE); // MEMBER_DATA : 데이터 저장할 xml 파일명
editor = sharedPreferences.edit();
}
}
}
- BaseActivity.java
모든 액티비티의 부모 액티비티
리사이클러뷰의 아이템인 멤버 객체를 검색, 추가, 수정, 삭제하는 등의 메소드를 가짐
public class BaseActivity extends AppCompatActivity {
void addMember(String name, int age, String job) {
int newIndex = getMemberSize() + 1;
if (newIndex > 0) {
String key = String.format(Locale.KOREA, "%s%03d", MEMBER, newIndex); // key = MEMBER001;
String value = name + SEP + age + SEP + job;
editor.putString(key, value); // 새로운 멤버 정보
editor.apply();
}
}
void editMember(String key, String name, int age, String job) {
String value = name + SEP + age + SEP + job;
editor.putString(key, value).apply();
}
void deleteMember(Member member) {
// 선택한 member 객체의 키부터 마지막 키까지 하나씩 데이터를 당기는 작업. 마지막 키는 삭제.
int index = Integer.parseInt(member.getKey().replace(MEMBER, "")); // if member.key == MEMBER001 -> index == 1
while (true) {
String key = String.format(Locale.KOREA, "%s%03d", MEMBER, index); // 현재 키
String nextKey = String.format(Locale.KOREA, "%s%03d", MEMBER, index + 1); // 다음 키
String value = sharedPreferences.getString(nextKey, null); // 다음 키의 데이터
if (value == null) { // 마지막 키인 경우 삭제하기
editor.remove(key);
break;
} else // 다음 키가 있을 경우 현재 키에 다음 키의 값을 넣어주기
editor.putString(key, value);
}
editor.apply();
}
Member getMember(int index) { // 특정 index 의 멤버 정보 가져오기
String key = String.format(Locale.KOREA, "%s%03d", MEMBER, index + 1); // arraylist나 for문을 돌려 가지고 올 때의 index는 0부터 n-1까지이므로 key를 설정할 때에는 index+1해줌
String value = sharedPreferences.getString(key, null); // 해당 키의 데이터 가져오기
if (value == null) return null; // 키에 대한 데이터가 null 이면 null 리턴
String[] saveData = value.split(SEP);
String name = saveData[0];
int age = Integer.parseInt(saveData[1]);
String job = saveData[2];
return new Member(key, name, age, job);
}
void getMemberList(ArrayList<Member> members) { // 저장된 모든 멤버 추가하기
for (int i = 0; i < getMemberSize(); i++) {
members.add(getMember(i));
}
}
int getMemberSize() { // 저장된 멤버 아이템의 개수
int i = 0;
while (true) {
if (getMember(i) == null) return i;
i++;
}
}
}
- MainActivity.java
onCreate()에서 저장된 멤버 아이템 불러와 세팅하기
onStart()에서 추가·수정 작업이 있을 경우 멤버 아이템 다시 세팅하기
public class MainActivity extends BaseActivity {
RecyclerView recyclerView;
ArrayList<Member> members = new ArrayList<>();
CustomAdapter adapter = new CustomAdapter(members, this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContent();
getMemberList(members); // sharedPreferences 에서 멤버 정보 가져오기
}
void setContent() {
recyclerView = findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelperCallback(adapter));
helper.attachToRecyclerView(recyclerView);
findViewById(R.id.btn_create).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(), AddActivity.class));
}
});
if (getMemberSize() == 0) { // 테스트를 위해 멤버 아이템이 없을 경우 초기값 넣어주기
addMember("Kim", 12, "student");
addMember("Jake", 20, "programmer");
addMember("Tom", 41, "baker");
addMember("Conan", 32, "teacher");
addMember("Chris", 26, "COO");
addMember("John", 43, "PD");
addMember("Kate", 56, "professor");
addMember("Shara", 30, "student");
addMember("Megan", 14, "soccer player");
addMember("Josh", 17, "student");
}
}
@Override
protected void onNewIntent(Intent intent) { // launchMode = "singleTask"
super.onNewIntent(intent);
setIntent(intent);
}
@Override
protected void onStart() {
super.onStart();
if (getIntent().getBooleanExtra("refresh", false)) {
// 추가 또는 수정 작업이 있을 경우 멤버 아이템 다시 세팅하기
members.clear();
getMemberList(members);
adapter.notifyDataSetChanged();
}
}
}
- AddActivity.java
메인 액티비티에서 추가 버튼을 누를 경우 추가 액티비티로 넘어와, 멤버 정보 입력해 멤버 추가하기
public class AddActivity extends BaseActivity {
EditText edtName, edtAge, edtJob;
Button btnSubmit;
String name, job;
int age;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item);
edtName = findViewById(R.id.edt_name);
edtAge = findViewById(R.id.edt_age);
edtJob = findViewById(R.id.edt_job);
btnSubmit = findViewById(R.id.btn_submit);
btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
name = edtName.getText().toString();
job = edtJob.getText().toString();
age = Integer.parseInt(edtAge.getText().toString());
if (name.length() > 0 && job.length() > 0 && age > 0) {
addMember(name, age, job);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("refresh", true);
startActivity(intent);
finish();
}
}
});
}
}
- EditActivity.java
아이템 클릭할 경우 수정 액티비티로 넘어와, 멤버 정보 수정하기
public class EditActivity extends BaseActivity {
EditText edtName, edtAge, edtJob;
Button btnSubmit;
String name, job;
int age;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item);
edtName = findViewById(R.id.edt_name);
edtAge = findViewById(R.id.edt_age);
edtJob = findViewById(R.id.edt_job);
Member member = (Member) getIntent().getSerializableExtra("member");
name = member.getName();
job = member.getJob();
age = member.getAge();
edtName.setText(name);
edtAge.setText(String.valueOf(age));
edtJob.setText(job);
btnSubmit = findViewById(R.id.btn_submit);
btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
name = edtName.getText().toString();
job = edtJob.getText().toString();
age = Integer.parseInt(edtAge.getText().toString());
if (name.length() > 0 && job.length() > 0 && age > 0) {
editMember(member.getKey(), name, age, job);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("refresh", true);
startActivity(intent);
finish();
}
}
});
}
}
- Member.java
public class Member implements Serializable {
String key;
String name;
int age;
String job;
public Member(String name, int age, String job) {
this.key = "";
this.name = name;
this.age = age;
this.job = job;
}
public Member(String key, String name, int age, String job) {
this.key = key;
this.name = name;
this.age = age;
this.job = job;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
- CustomAdapter.java
클릭 시 수정 액티비티로 넘어가기
왼쪽으로 스와이프 후 삭제 버튼 클릭 시 아이템 삭제 및 해당 정보 삭제하기
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> implements ItemTouchHelperListener {
ArrayList<Member> members;
Context mContext;
@Override
public boolean onItemMove(int from_position, int to_position) {
return false;
}
@Override
public void onItemSwipe(int position) {
}
@Override
public void onLeftClick(int position, RecyclerView.ViewHolder viewHolder) {
}
@Override
public void onRightClick(int position, RecyclerView.ViewHolder viewHolder) {
BaseActivity activity = new BaseActivity();
activity.deleteMember(members.get(position));
members.remove(position);
notifyDataSetChanged();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
// adapter의 viewHolder에 대한 inner class (setContent()와 비슷한 역할)
// itemView를 저장하는 custom viewHolder 생성
// findViewById & 각종 event 작업
TextView tvName, tvAge, tvJob;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
// item 에 대한 클릭 이벤트 설정
tvName = itemView.findViewById(R.id.item_name);
tvAge = itemView.findViewById(R.id.item_age);
tvJob = itemView.findViewById(R.id.item_job);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
Intent intent = new Intent(mContext, EditActivity.class);
intent.putExtra("member", members.get(position)); // 클릭한 member 객체 전달
mContext.startActivity(intent);
}
}
});
}
}
public CustomAdapter(ArrayList<Member> members) {
// adapter constructor
this.members = members;
}
public CustomAdapter(ArrayList<Member> members, Context mContext) {
// adapter constructor for needing context part
this.members = members;
this.mContext = mContext;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// onCreateViewHolder: make xml as an object using LayoutInflater & create viewHolder with the object
// layoutInflater로 xml객체화. viewHolder 생성.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_member, parent, false);
return new CustomViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
// onBindViewHolder: put data of item list into xml widgets
// xml의 위젯과 데이터를 묶는(연결하는, setting하는) 작업.
// position에 해당하는 data, viewHolder의 itemView에 표시함
holder.tvName.setText(members.get(position).getName());
holder.tvAge.setText(String.valueOf(members.get(position).getAge()));
holder.tvJob.setText(members.get(position).getJob());
}
@Override
public int getItemCount() {
// getItemCount: return the size of the item list
// item list의 전체 데이터 개수 return
return (members != null ? members.size() : 0);
}
}
결과 화면
1. 리사이클러뷰에 아이템 추가 및 수정하기
2. 저장된 정보 확인하기
Shift*2>Device File Explorer>data>data>패키지명>shared_prefs>파일명.xml
전체 코드
다음 글
참고자료
SharedPreferences.Editor | Android 개발자 | Android Developers
[Android] 안드로이드 SharedPreferences 사용법 및 예제 :: R_Son (tistory.com)
안드로이드 - shared preferences 키값을 배열로 - 안드로이드 Q&A (masterqna.com)
(안드로이드) 내부저장소 접근하기 (tistory.com)
공부하며 정리한 글입니다. 내용에 대한 피드백은 언제나 환영입니다.
'android' 카테고리의 다른 글
SharedPreferences ArrayList 저장하기 (0) | 2021.01.21 |
---|---|
SharedPreferences 객체 저장하기 (0) | 2021.01.16 |
Firbase 사진 업로드하기 (0) | 2021.01.14 |
이미지 받아 다른 액티비티에 전달하기 (0) | 2021.01.14 |
가져온 이미지 회전 막기 (0) | 2021.01.14 |
댓글