개발자 승학

안드로이드 스튜디오 메모장 만들기(Realm 사용) 본문

it/안드로이드(android studio)

안드로이드 스튜디오 메모장 만들기(Realm 사용)

유승학 2018. 5. 29. 13:08

안녕하세요.


이번에는 안드로이드 스튜디오로 간단한 메모장 앱을 만들어볼려고 합니다.


먼저 데이터베이스로는 Realm을 사용합니다.


Realm이란 무엇인가?


Realm 데이터베이스는 오픈 소스로 모바일 사용에 최적화된 내장 데이터베이스 라이브러리입니다.

로컬 기반 데이터베이스라고 합니다. 간단히 말해서 핸드폰 자체가 데이터베이스죠.


Realm의 장점

  • Realm은 네이티브 객체 를 저장합니다: Realm 데이터베이스에는 Swift, Java, Objective-C, C#, React Native를 사용하는 JavaScript 등 모바일 앱 개발에 주로 사용되는 대부분의 언어 바인딩이 있습니다. Realm에 저장하는 객체를 그대로 나머지 코드에서 사용할 수 있습니다.

  • Realm은 zero-copy 입니다: 데이터에 접근하기 위해 데이터를 데이터베이스 안팎으로 복사할 필요가 없습니다. 해당 객체 그대로 직접 작업할 수 있습니다.

  • Realm은 라이브 오브젝트 패턴 을 구현합니다: Realm에 저장된 객체의 인스턴스가 있고 애플리케이션의 다른 곳에서 이 객체를 업데이트하면 기존 인스턴스에 변화가 반영됩니다.

  • Realm은 크로스 플랫폼 입니다: Realm에 특정 플랫폼에 국한된 객체를 저장하지 않는 이상 데이터는 OS를 가리지 않고 동기화될 수 있습니다. (사실 실제 Realm 데이터 파일을 다른 플랫폼 간에 복사해서 사용할 수도 있습니다.)

  • Realm은 오프라인-우선 입니다: 애플리케이션은 Realm이 Realm 오브젝트 서버와 동기화되는지 여부와 관계없이 같은 방법으로 동작됩니다. 연결이 가능해지면 변경 사항이 매끄럽게 동기화됩니다.

  • 마지막으로 Realm은 ACID를 준수합니다.


시작하기


[1단계]

Relam은 Gradle플러그인으로 설치합니다.


프로젝트 수준의 build.gradle에 classpath를 추가합니다.



프로젝트 수준의 build.gradle은 왼쪽 Gradle Scripts의 빨간색 박스 부분입니다.


dependencies에 밑 플러그인을 추가합니다.

classpath "io.realm:realm-gradle-plugin:3.1.4"

[2단계]


realm-android 플러그인을 애플리케이션 수준 build.gradle 파일에서 적용시킵니다.



좌측 빨간색 부분이 애플리케이션 수준 build.gradle입니다.


오른쪽 두 개의 빨간색 박스처럼 추가한 후 싱크해줍니다.


이제 코드를 작성해볼게요.


1.레이아웃 구성

[activity_add.xml]

<?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=".AddActivity">


<EditText
android:id="@+id/title_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="제목"/>

<Button
android:id="@+id/addFinish"
android:text="메모작성"
android:layout_width="150dp"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:layout_height="50dp" />

</RelativeLayout>

[activity_main.xml]

<?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=".MainActivity">


<android.support.v7.widget.RecyclerView
android:id="@+id/rcvMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item">

</android.support.v7.widget.RecyclerView>


<android.support.design.widget.FloatingActionButton
android:id="@+id/floating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="160dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
app:backgroundTint="@color/colorAccent"
android:src="@drawable/ic_content_new"
/>

</RelativeLayout>

[item.xml]


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

android:background="@drawable/border"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp">

<TextView
android:id="@+id/mContextTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:paddingLeft="20dp"
android:text="Data" />


</RelativeLayout>


2.Realm 모델 클래스 생성


[Memo.java]

package com.example.ysh.memong;

import io.realm.RealmObject;
import io.realm.annotations.Required;

public class Memo extends RealmObject{

@Override
public String toString() {
return "Memo{" +
"text='" + text + '\'' +
'}';
}

@Required
private String text;

public Memo() {
this.text = "아무값도 없습니다.";
}
public Memo(String text) {
this.text = text;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}
}

Realm 모델 클래스는 RealmObject 기반 클래스를 상속 받아서 사용합니다.

Realm 모델 클래스는 커스텀 메서드에 의한 public, protected, private 필드를 지원합니다.


3. [MainActivity.java]


public class MainActivity extends AppCompatActivity {

private TextView textView;
private Realm realm;
private RecyclerView rcv;
private RcvAdapter rcvAdapter;
private Memo memo_Main;
public List<Memo> list = new ArrayList<>();

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

textView = findViewById(R.id.mContextTextView);
rcv = findViewById(R.id.rcvMain);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rcv.addItemDecoration(new DividerItemDecoration(this, linearLayoutManager.getOrientation()));
rcv.setLayoutManager(linearLayoutManager);

Realm.init(this);
realm = Realm.getDefaultInstance();

RealmResults<Memo> realmResults = realm.where(Memo.class)
.findAllAsync();

for(Memo memo : realmResults) {
list.add(new Memo(memo.getText()));
rcvAdapter = new RcvAdapter(MainActivity.this,list);
rcv.setAdapter(rcvAdapter);
}

FloatingActionButton button = findViewById(R.id.floating);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,AddActivity.class);
startActivityForResult(intent,1);
}
});
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);

if(resultCode == RESULT_OK) {

String title = data.getStringExtra("title");
String time = data.getStringExtra("time");
Toast.makeText(this,title + "," + time,Toast.LENGTH_SHORT).show();

realm.beginTransaction();
memo_Main = realm.createObject(Memo.class);
memo_Main.setText(title);

realm.commitTransaction();

RealmResults<Memo> realmResults = realm.where(Memo.class)
.equalTo("text",title)
.findAllAsync();

list.add(new Memo(title));
rcvAdapter = new RcvAdapter(MainActivity.this,list);
rcv.setAdapter(rcvAdapter);

}
}
}



4. 메모추가하기

[AddActivity.java]


public class AddActivity extends AppCompatActivity{

private EditText editText;
private String title;
private String formattedDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);

editText = findViewById(R.id.title_text);
Button btn = findViewById(R.id.addFinish);

btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Date c = Calendar.getInstance().getTime();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
formattedDate = df.format(c);
title = editText.getText().toString();
Intent add = new Intent();
add.putExtra("title",title);
add.putExtra("time",formattedDate);
setResult(RESULT_OK,add);
finish();
}
});

}
}


5. 메모등록 및 삭제

[RcvAdapter.java]


public class RcvAdapter extends RecyclerView.Adapter<RcvAdapter.ViewHolder> {

private Activity activity;
private List<Memo> dataList;
private Realm realm;

public RcvAdapter(Activity activity, List<Memo> dataList) {
this.activity = activity;
this.dataList = dataList;
}

@Override
public int getItemCount() {
return dataList.size();
}

class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName;

public ViewHolder(View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.mContextTextView);

itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
removeMemo(dataList.get(getAdapterPosition()).getText());
removeItemView(getAdapterPosition());
return false;
}
});
}
}

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Memo data = dataList.get(position);
holder.tvName.setText(data.getText());
}

private void removeItemView(int position) {
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
}

// 데이터 삭제
private void removeMemo(String text) {
realm = Realm.getDefaultInstance();
final RealmResults<Memo> results = realm.where(Memo.class).equalTo("text",text).findAll();

realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
results.deleteFromRealm(0);
}
});
}
}




메모를 추가하면 MainActivity에 value와 value2로 메모와 현재 시간을 넘겨줍니다.

그리고 activity를 끝냅니다.


github

https://github.com/aiex1234/Memong


RecyclerView에 대한 내용은 안드로이드 관련 카테고리에 있습니다.

궁금하신점은 댓글달아주세요.

Comments