본문 바로가기
android

SharedPreferences 사용해 데이터 저장하기

by 윈 Win 2021. 1. 15.
728x90

블로그 이사했습니다!

 

👇 블로그 이전 공지 👇

블로그 이전 안내 (tistory.com)

 

 

👇 새 블로그에서 글 보기 👇

[Android] SharedPreferences 데이터 저장하기 — Win Record (tistory.com)

 

[Android] SharedPreferences 데이터 저장하기

⚠️ 2021.01.15에 작성된 글입니다 ⚠️ SharedPreferences SharedPreferences를 사용하면 key-value 형태로 앱 내 데이터를 xml형태로 저장할 수 있다. 이때 저장할 수 있는 데이터 타입은 int, long, float, bo..

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

 

Shift 키 두 번 눌러 Device File Explorer 검색하기

 

data>data>패키지명>shared_prefs>파일명.xml

 

저장된 정보

 

 

 


전체 코드

StoreObjectBySplitString

 

 


다음 글

SharedPreferences 객체 저장하기

 


참고자료

SharedPreferences.Editor  |  Android 개발자  |  Android Developers

[Android] 안드로이드 SharedPreferences 사용법 및 예제 :: R_Son (tistory.com)

안드로이드 - shared preferences 키값을 배열로 - 안드로이드 Q&A (masterqna.com)

(안드로이드) 내부저장소 접근하기 (tistory.com)

 

 

 

공부하며 정리한 글입니다. 내용에 대한 피드백은 언제나 환영입니다.

댓글