Android — 예상 시간: 25분
이 튜토리얼에서 Thorben Primke는 RecyclerView의 서브클래스인 RealmRecyclerView를 사용해서 렘에 저장된 데이터로부터 Grid Layout을 만드는 법을 알려줍니다.
앱에 grid layout을 넣는 방법을 찾고 있나요? 렘에 저장된 데이터로 이런 인터페이스를 정말 빨리 만들 수 있습니다. 더 좋은 점은 데이터를 자동 애니메이션의 트리거로 만들 수도 있다는 겁니다.
최종 결과물 코드는 GitHub에서 볼 수 있습니다.
완성 화면은 아래와 같습니다.
튜토리얼
주의: NY Times의 API에서 데이터를 가져오려면 API Key가 필요합니다. NY Times Developer site에서 API Key를 무료로 받을 수 있습니다.
“Empty Activity” 템플릿으로 새 안드로이드 스튜디오 프로젝트를 만드세요.
jitpack.io에서 gradle dependency로 RealmSearchView를 프로젝트에 추가할 수 있습니다.
프로젝트의 build.gradle
파일에 아래 내용을 추가하세요.
maven { url "https://jitpack.io" }
결과는 다음과 같습니다.
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
다음으로 app module의 build.gradle
파일에 아래 내용을 추가하세요.
compile 'com.github.thorbenprimke:realm-recycler-view:0.9.4'
이 튜토리얼에서는 샘플 데이터 세트와 이미지 로딩 라이브러리를 사용할 겁니다. 앱에 추가하려면 아래 내용을 app module의 build.gradle
파일에 추가하세요.
compile 'com.github.thorbenprimke:realm-nytimes-data:0.9.2'
compile 'com.github.bumptech.glide:glide:3.6.1'
dependency를 다시 동기화하면 준비 완료입니다.
인테그레이션
프로젝트의 기본 뼈대를 완성했으니 RealmRecyclerView
를 통합하고 RealmBasedRecyclerViewAdapter
의 서브클래스인 RealmRecyclerView
를 구현해서 보여줄 차례입니다.
MainActivity
의 레이아웃 파일을 열고 아래 내용으로 교체하세요.
<FrameLayout
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="match_parent">
<co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView
android:id="@+id/realm_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rrvIsRefreshable="false"
app:rrvLayoutType="Grid"
app:rrvGridLayoutSpanCount="2"
/>
</FrameLayout>
뷰에는 세 가지 커스텀 속성이 지정돼 있습니다.
- rrvIsRefreshable - RecyclerView의 당겨서 새로 고침 기능을 끕니다.
-
rrvLayoutType -
RealmRecyclerView
는 여러 레이아웃 타입을 지원하는데 이 튜토리얼에서는 2개 칼럼을 가진 Grid를 사용할 겁니다. -
rrvGridLayoutSpanCount -
rrvLayoutType
를 Grid로 설정한 경우 이 속성을 0보다 크게 설정해야 합니다.
샘플 데이터에서 NYTimesStory
(출처) 클래스를 사용합니다. adapter에서 하나의 스토리를 표현하기 위한 형식으로 이 클래스를 사용할 예정입니다.
NYTimesStory
는 뷰의 집합으로 표현되는데 결과는 다음과 같습니다.
_------------------_
Image
Date
Title
Abstract
_------------------_
RealmBasedRecyclerViewAdapter
내의 ViewHolder에서 사용될 뷰는 grid_item_view.xml
으로 명명했습니다. 레이아웃 폴더에 아래 내용으로 레이아웃을 생성하세요.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="5dp"
android:layout_gravity="center_horizontal"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:singleLine="true"
android:ellipsize="end"
android:textStyle="bold"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_gravity="center_horizontal"
android:singleLine="true"
android:ellipsize="end"/>
<TextView
android:id="@+id/story_abstract"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center_horizontal"
android:maxLines="5"
android:ellipsize="end"/>
</LinearLayout>
NYTimesStory
를 화면에 렌더링 하기 위해 데이터 모델은 위 레이아웃을 매핑합니다.
이제 RealmBasedRecyclerViewAdapter
클래스를 상속받아 서브 클래스를 만들어야 합니다.
public class NYTimesStoryRecyclerViewAdapter extends RealmBasedRecyclerViewAdapter<NYTimesStory,
NYTimesStoryRecyclerViewAdapter.ViewHolder> {
public NYTimesStoryRecyclerViewAdapter(
Context context,
RealmResults<NYTimesStory> realmResults,
boolean automaticUpdate,
boolean animateIdType) {
super(context, realmResults, automaticUpdate, animateIdType);
}
public class ViewHolder extends RealmViewHolder {
public TextView title;
public TextView publishedDate;
public ImageView image;
public TextView storyAbstract;
public ViewHolder(LinearLayout container) {
super(container);
this.title = (TextView) container.findViewById(R.id.title);
this.publishedDate = (TextView) container.findViewById(R.id.date);
this.image = (ImageView) container.findViewById(R.id.image);
this.storyAbstract = (TextView) container.findViewById(R.id.story_abstract);
}
}
@Override
public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) {
View v = inflater.inflate(R.layout.grid_item_view, viewGroup, false);
ViewHolder vh = new ViewHolder((LinearLayout) v);
return vh;
}
@Override
public void onBindRealmViewHolder(ViewHolder viewHolder, int position) {
final NYTimesStory nyTimesStory = realmResults.get(position);
viewHolder.title.setText(nyTimesStory.getTitle());
viewHolder.publishedDate.setText(nyTimesStory.getPublishedDate());
final RealmList<NYTimesMultimedium> multimedia = nyTimesStory.getMultimedia();
if (multimedia != null && !multimedia.isEmpty()) {
Glide.with(GridExampleActivity.this).load(
multimedia.get(0).getUrl()).into(viewHolder.image);
} else {
viewHolder.image.setImageResource(R.drawable.nytimes_logo);
}
viewHolder.storyAbstract.setText(nyTimesStory.getStoryAbstract());
}
}
onCreateRealmViewHolder
메서드는 grid_item_view
를 inflate 해서 ViewHolder
에 넘겨줍니다.
onBindRealmViewHolder
메서드에서 NYTimesStory
가 view에 바인딩 됩니다.
원격지의 스토리 이미지를 불러오기 위해서 이미지 로딩 라이브러리인 Glide를 사용합니다.
요소 연결
필요 요소들을 다 만들었으니 이제 RealmRecyclerView
와 NYTimesStoryRecyclerViewAdapter
를 연결해야겠죠.
액티비티에 아래 코드를 구현하세요.
private RealmRecyclerView realmRecyclerView;
private NYTimesStoryRecyclerViewAdapter nyTimesStoryAdapter;
private Realm realm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_grid_layout);
realmRecyclerView = (RealmRecyclerView) findViewById(R.id.realm_recycler_view);
setTitle(getResources().getString(
R.string.activity_layout_name,
getIntent().getStringExtra("Type")));
resetRealm();
Realm.setDefaultConfiguration(getRealmConfig());
realm = Realm.getDefaultInstance();
RealmResults<NYTimesStory> nyTimesStories =
realm.where(NYTimesStory.class).findAllSorted("sortTimeStamp", false);
nyTimesStoryAdapter = new NYTimesStoryRecyclerViewAdapter(this, nyTimesStories, true, true);
realmRecyclerView.setAdapter(nyTimesStoryAdapter);
final NYTimesDataLoader nyTimesDataLoader = new NYTimesDataLoader();
nyTimesDataLoader.loadAllData(realm, "YOUR_NY_TIMES_API_KEY");
}
@Override
protected void onDestroy() {
super.onDestroy();
realm.close();
realm = null;
}
private RealmConfiguration getRealmConfig() {
return new RealmConfiguration
.Builder(this)
.setModules(Realm.getDefaultModule(), new NYTimesModule())
.build();
}
private void resetRealm() {
Realm.deleteRealm(getRealmConfig());
}
액티비티의 onCreate
메서드 내에서는 렘 쿼리에 대한 응답으로 반환된 RealmResults
가 NYTimesStoryRecyclerViewAdapter
로 전달됩니다. NYTimesStoryRecyclerViewAdapter
의 생성자에는 2개의 boolean 매개 변수가 있습니다. 이를 통해 adapter가 자동적으로 새로운 Realm result를 보여주고 grid 아이템을 움직이도록 할 수 있습니다.
Realm
의 스키마가 com.github.thorbenprimke:realm-nytimes-data
라는 외부 라이브로리로부터 NYTimes의 모델을 포함하게 하려면 getRealmConfig()
메서드로 Realm
의 기본 설정을 해야 합니다.
이 시점에서 애플리케이션을 실행할 수는 있지만 Realm
이 비어 있으므로 아무것도 보이지 않을 겁니다.
기본적인 구조를 연결했으니 데이터를 준비해보죠. New York Times는 멋진 API를 제공하고 있는데 이 중에 “Top Stories” API를 사용해서 최신 뉴스 스토리를 불러와 grid에 보여줄 예정입니다.
초기 설정에서 realm-nytimes-data
를 gradle dependency에 추가했었죠. 이 라이브러리는 NYTimesStory
(출처) 와 NYTimesMultimedium
(출처) 두 가지의 렘 모델을 포함하고 있는데, 이를 통해 New York Times Top Stories API로부터 받은 데이터를 표현할 수 있습니다.
튜토리얼을 단순화하기 위해 API로부터 데이터를 요청하는 방법이나 받은 JSON 데이터를 디시리얼라이즈해서 Realm 객체*로 만드는 법을 다루진 않을 겁니다. 그 대신 API Key를 New York Times Developer site에 등록하기만 하면 됩니다.
그다음 아래처럼 액티비티 안의 YOUR_NY_TIMES_API_KEY
를 본인의 API key로 바꾸세요.
nyTimesDataLoader.loadAllData(realm, "YOUR_NY_TIMES_API_KEY");
loadAllData
메서드는 API 응답을 불러오고 처리해서 렘에 스토리를 추가합니다.
데이터가 들어왔으니 애플리케이션을 실행해서 NYTimes의 뉴스 스토리 헤드라인을 아래처럼 grid에서 볼 수 있습니다.
- 데이터 요청과 JSON 파싱에 대해 궁금하다면 샘플 데이터 프로젝트의
NYTimesDataLoader
(출처) 메서드 구현부를 보세요. 이 메서드는 제공된 섹션을 위한 async API 요청을 담당하고 JSON 응답을 파싱 해서 렘 모델로 삽입합니다.
컨텐츠에 대하여
이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.