Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".view.image.ImageActivity"
android:theme="@style/DialogTheme"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class MovieRepository implements MovieDataSource {

private MovieRemoteDataSource remoteDataSource;

private List<Movie> savedMovieList;

private MovieRepository(){
remoteDataSource = MovieRemoteDataSource.getInstance();
}
Expand All @@ -30,4 +32,12 @@ public Single<SearchMovieResponse> searchMovies(Map<String, String> request) {

return remoteDataSource.searchMovies(request);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조를 세분화 시키신 것이 인상 깊었습니다, remoteDataSource를 한 번 더 감싸셨는데 싱글톤 패턴을 두 번 적용하신 이유가 궁금합니다

}

public List<Movie> getSavedMovieList() {
return savedMovieList;
}

public void setSavedMovieList(List<Movie> savedMovieList) {
this.savedMovieList = savedMovieList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

public abstract class BaseActivity<B extends ViewDataBinding, P extends BasePresenter> extends AppCompatActivity {
Expand All @@ -20,7 +21,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 화면 세로 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
try {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} catch (Exception e){
Log.e(TAG, e.getMessage());
}

binding = DataBindingUtil.setContentView(this, getLayoutId());
presenter = getPresenter();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.example.yeseul.movieapp.view.image;

import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.customtabs.CustomTabsIntent;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PagerSnapHelper;
import android.support.v7.widget.SnapHelper;
import android.view.WindowManager;
import android.widget.LinearLayout;

import com.example.yeseul.movieapp.R;
import com.example.yeseul.movieapp.data.source.movie.MovieRepository;
import com.example.yeseul.movieapp.databinding.ActivityImageBinding;
import com.example.yeseul.movieapp.view.BaseActivity;

public class ImageActivity extends BaseActivity<ActivityImageBinding, ImagePresenter> implements ImageContract.View {

public static String EXTRA_IMAGE_POSITION = "EXTRA_IMAGE_POSITION";

private ImageAdapter adapter;

private int position;

@Override
protected int getLayoutId() {
return R.layout.activity_image;
}

@Override
protected ImagePresenter getPresenter() {
return new ImagePresenter(this, MovieRepository.getInstance());
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

position = getIntent().getIntExtra(EXTRA_IMAGE_POSITION, 0);

// 팝업창 레이아웃 크기 변경
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = LinearLayout.LayoutParams.MATCH_PARENT;
params.height = LinearLayout.LayoutParams.MATCH_PARENT;
getWindow().setAttributes(params);

// 어댑터 생성
adapter = new ImageAdapter(this, null);

presenter.setAdapterView(adapter);
presenter.setAdapterModel(adapter);

initView();

presenter.onViewCreated();
}

private void initView() {

// 리사이클러뷰 생성
binding.recyclerImage.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
binding.recyclerImage.setAdapter(adapter);

SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(binding.recyclerImage);

// 터치 발생한 곳 position 으로 넘기기
binding.recyclerImage.scrollToPosition(position);

// 닫기 버튼 리스너 등록
binding.btnClose.setOnClickListener(v -> finish());
}

/**
* 영화 상세 정보 URL 로 연결 */
@Override
public void startMovieDetailPage(String linkUrl) {

CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
.setToolbarColor(getResources().getColor(R.color.colorPrimary))
.build();

customTabsIntent.launchUrl(this, Uri.parse(linkUrl));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.yeseul.movieapp.view.image;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.yeseul.movieapp.R;
import com.example.yeseul.movieapp.databinding.HolderMovieImageBinding;
import com.example.yeseul.movieapp.pojo.Movie;
import com.example.yeseul.movieapp.view.adapter.BaseRecyclerAdapter;

import java.util.List;

public class ImageAdapter extends BaseRecyclerAdapter<Movie, ImageAdapter.ViewHolder> {

public ImageAdapter(Context context, List<Movie> itemList) {
super(context, itemList);
}

@Override
protected void onBindView(ViewHolder holder, int position) {
holder.binding.setItem(itemList.get(position));
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.holder_movie_image, parent, false);
return new ViewHolder(view);
}

public class ViewHolder extends RecyclerView.ViewHolder{

HolderMovieImageBinding binding;

public ViewHolder(@NonNull View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.yeseul.movieapp.view.image;

import com.example.yeseul.movieapp.pojo.Movie;
import com.example.yeseul.movieapp.view.BasePresenter;
import com.example.yeseul.movieapp.view.BaseView;
import com.example.yeseul.movieapp.view.adapter.AdapterContract;

public interface ImageContract {

interface View extends BaseView {

void startMovieDetailPage(String linkUrl);
}

interface Presenter extends BasePresenter {

void setAdapterView(AdapterContract.View adapterView);

void setAdapterModel(AdapterContract.Model<Movie> adapterModel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.example.yeseul.movieapp.view.image;

import com.example.yeseul.movieapp.data.source.movie.MovieRepository;
import com.example.yeseul.movieapp.pojo.Movie;
import com.example.yeseul.movieapp.view.adapter.AdapterContract;

public class ImagePresenter implements ImageContract.Presenter {

private ImageContract.View view;
private MovieRepository repository;
private AdapterContract.View adapterView;
private AdapterContract.Model<Movie> adapterModel;

public ImagePresenter(ImageContract.View view, MovieRepository repository) {
this.view = view;
this.repository = repository;
}

@Override
public void setAdapterView(AdapterContract.View adapterView) {
this.adapterView = adapterView;
this.adapterView.setOnItemClickListener(position -> {
this.view.startMovieDetailPage(this.adapterModel.getItem(position).getLinkUrl());
});
}

@Override
public void setAdapterModel(AdapterContract.Model<Movie> adapterModel) {
this.adapterModel = adapterModel;
}

@Override
public void onViewCreated() {

loadItems(true);
}

@Override
public void loadItems(boolean isRefresh) {

adapterModel.addItems(repository.getSavedMovieList());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.yeseul.movieapp.view.main;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
Expand All @@ -16,6 +17,7 @@
import com.example.yeseul.movieapp.databinding.ActivityMovieBinding;
import com.example.yeseul.movieapp.utils.KeyboardUtil;
import com.example.yeseul.movieapp.view.BaseActivity;
import com.example.yeseul.movieapp.view.image.ImageActivity;

public class MainActivity extends BaseActivity<ActivityMovieBinding, MainPresenter> implements MainContract.View {

Expand Down Expand Up @@ -55,6 +57,9 @@ private void initView() {
binding.recyclerMovie.setNestedScrollingEnabled(false);
binding.recyclerMovie.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

// 리사이클러 뷰 내의 이미지 클릭 이벤트 리스너 등록
adapter.setOnImageClickListener(this::startImageActivity);

// 최하단 스크롤 감지
binding.recyclerMovie.setOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
Expand Down Expand Up @@ -118,4 +123,13 @@ public void startMovieDetailPage(String linkUrl) {

customTabsIntent.launchUrl(this, Uri.parse(linkUrl));
}

/**
* 이미지 상세 보기 화면 띄우기 */
private void startImageActivity(int position) {
presenter.saveMovieList();
Intent intent = new Intent(getApplicationContext(), ImageActivity.class);
intent.putExtra(ImageActivity.EXTRA_IMAGE_POSITION, position);
startActivity(intent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ interface Presenter extends BasePresenter {
void setAdapterView(AdapterContract.View adapterView);

void setAdapterModel(AdapterContract.Model<Movie> adapterModel);

void saveMovieList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.annotation.SuppressLint;
import android.databinding.ObservableBoolean;
import android.databinding.ObservableField;
import android.databinding.ObservableInt;

import com.example.yeseul.movieapp.data.source.movie.MovieRepository;
import com.example.yeseul.movieapp.mapper.MovieMapper;
Expand All @@ -16,6 +17,7 @@
public class MainPresenter implements MainContract.Presenter {

public final ObservableBoolean isLoading = new ObservableBoolean(false); // 로딩 중 flag 바인딩
public final ObservableInt totalCount = new ObservableInt(0); // 검색결과 count 바인딩

private MainContract.View view;
private MovieRepository repository;
Expand Down Expand Up @@ -71,6 +73,11 @@ public void setAdapterModel(AdapterContract.Model<Movie> adapterModel) {
this.adapterModel = adapterModel;
}

@Override
public void saveMovieList() {
repository.setSavedMovieList(adapterModel.getItemList());
}

@SuppressLint("CheckResult")
private void getMovieList(){

Expand All @@ -83,6 +90,7 @@ private void getMovieList(){
// 로딩 flag OFF
isLoading.set(false);

totalCount.set(response.getTotal());
List<Movie> movieList = response.getMovieList();

if(movieList.size() == 0){ // 검색 결과가 없는 경우
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,23 @@

public class MovieListAdapter extends BaseRecyclerAdapter<Movie, MovieListAdapter.ViewHolder> {

private ImageClickListener imageClickListener = null;

public MovieListAdapter(Context context) {
super(context);
}

public void setOnImageClickListener(ImageClickListener imageClickListener){
this.imageClickListener = imageClickListener;
}

@Override
protected void onBindView(ViewHolder holder, int position) {
holder.binding.setItem(itemList.get(position));

if(imageClickListener != null){
holder.binding.ivThumbnail.setOnClickListener(v -> imageClickListener.onImageClick(position));
}
}

@NonNull
Expand All @@ -40,4 +50,9 @@ public ViewHolder(@NonNull View itemView) {
binding = DataBindingUtil.bind(itemView);
}
}

public interface ImageClickListener{

void onImageClick(int position);
}
}
14 changes: 14 additions & 0 deletions app/src/main/res/drawable-v24/line_bottom_trans.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="@null"/>
</shape>
</item>
<item android:right="-2dp" android:left="-2dp" android:top="-2dp">
<shape>
<solid android:color="@null"/>
<stroke android:color="@color/colorDivider" android:width="1dp"/>
</shape>
</item>
</layer-list>
4 changes: 4 additions & 0 deletions app/src/main/res/drawable/btn_close.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<vector android:height="40dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="40dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>
Loading