-
Notifications
You must be signed in to change notification settings - Fork 3
Chapter2 #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: junieberry-chapter1
Are you sure you want to change the base?
Chapter2 #6
Changes from all commits
73a058d
0c30ca1
602ac8d
544e315
1221d7e
6aeab68
9de7801
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.example.mvvm2 | ||
|
|
||
| import android.app.Application | ||
| import android.content.SharedPreferences | ||
| import com.example.mvvm2.data.repository.local.SharedPreference | ||
|
|
||
| class App: Application() { | ||
| override fun onCreate() { | ||
| super.onCreate() | ||
| instance = this | ||
| } | ||
|
|
||
| companion object { | ||
| lateinit var instance: App | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package com.example.mvvm2.data.repository | ||
|
|
||
| import com.example.mvvm2.data.model.MovieResponse | ||
| import com.example.mvvm2.data.repository.local.LocalDataSource | ||
| import com.example.mvvm2.data.repository.local.LocalDataSourceImpl | ||
| import com.example.mvvm2.data.repository.remote.RemoteDataSourceImpl | ||
| import retrofit2.Call | ||
|
|
||
| interface Repository { | ||
| val remoteDataSource: RemoteDataSourceImpl | ||
| val localDataSource: LocalDataSourceImpl | ||
|
|
||
| fun getMovieList(query: String): Call<MovieResponse> | ||
| fun getHistory(): ArrayList<String>? | ||
| fun setHistory(title:String) | ||
| } | ||
|
|
||
| class RepositoryImpl() : Repository { | ||
| override val remoteDataSource: RemoteDataSourceImpl | ||
| get() = RemoteDataSourceImpl() | ||
| override val localDataSource: LocalDataSourceImpl | ||
| get() = LocalDataSourceImpl() | ||
|
|
||
| override fun getMovieList(query: String): Call<MovieResponse> { | ||
| return remoteDataSource.getMovieList(query) | ||
| } | ||
|
|
||
| override fun getHistory(): ArrayList<String>? { | ||
| return localDataSource.getHistory() | ||
| } | ||
|
|
||
| override fun setHistory(title: String) { | ||
| return localDataSource.setHistory(title) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.example.mvvm2.data.repository.local | ||
|
|
||
| import com.example.mvvm2.App | ||
|
|
||
| interface LocalDataSource { | ||
| val pref: SharedPreference | ||
| get() = SharedPreference(App.instance.applicationContext) | ||
|
|
||
| fun getHistory(): ArrayList<String>? | ||
| fun setHistory(title:String) | ||
| } | ||
|
|
||
| class LocalDataSourceImpl():LocalDataSource{ | ||
| override fun getHistory(): ArrayList<String>? { | ||
| return pref.getHistory() | ||
| } | ||
|
|
||
| override fun setHistory(title: String) { | ||
| pref.setHistory(title) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.example.mvvm2.data.repository.local | ||
|
|
||
| import android.content.Context | ||
| import android.content.SharedPreferences | ||
| import android.util.Log | ||
| import com.example.mvvm2.App | ||
| import com.google.gson.Gson | ||
| import com.google.gson.reflect.TypeToken | ||
|
|
||
| class SharedPreference(context: Context) { | ||
| private val PREF_NAME = "PREF" | ||
| private val PREF_MODE = Context.MODE_PRIVATE | ||
| private var pref: SharedPreferences = context.getSharedPreferences(PREF_NAME, PREF_MODE) | ||
|
|
||
|
|
||
| private val HISTORY = "HISTORY" | ||
| fun getHistory(): ArrayList<String>? { | ||
| val history = pref.getString(HISTORY, null) | ||
| return Gson().fromJson(history, object : TypeToken<ArrayList<String>>() {}.type) | ||
| } | ||
|
|
||
| fun setHistory(h: String) { | ||
| var history: ArrayList<String>? = if (getHistory().isNullOrEmpty()) arrayListOf() else getHistory() | ||
| history!!.add(h) | ||
| history = history.distinct() as ArrayList<String> | ||
|
|
||
| if (history.size == 6) { | ||
| history.removeAt(0) | ||
| } | ||
| pref.edit().putString(HISTORY, Gson().toJson(history)).apply() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.example.mvvm2.data.repository.remote | ||
|
|
||
| import com.example.mvvm2.data.model.MovieResponse | ||
| import retrofit2.Call | ||
|
|
||
| interface RemoteDataSource { | ||
| fun getMovieList(query: String):Call<MovieResponse> | ||
| } | ||
|
|
||
| class RemoteDataSourceImpl() : RemoteDataSource { | ||
|
|
||
| override fun getMovieList(query: String): Call<MovieResponse> { | ||
| return BaseRetrofit.retrofit.create(MovieRetrofit::class.java).getMovieList(query) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.example.mvvm2.ui.history | ||
|
|
||
| import android.content.Intent | ||
| import androidx.appcompat.app.AppCompatActivity | ||
| import android.os.Bundle | ||
| import androidx.databinding.DataBindingUtil | ||
| import androidx.lifecycle.ViewModelProvider | ||
| import com.example.mvvm2.R | ||
| import com.example.mvvm2.databinding.ActivityHistoryBinding | ||
| import com.example.mvvm2.databinding.ActivityMainBinding | ||
| import com.example.mvvm2.ui.main.MainActivity | ||
| import com.example.mvvm2.ui.main.MainRecyclerAdapter | ||
| import com.example.mvvm2.ui.main.MainViewModel | ||
| import com.example.mvvm2.ui.moive.MovieActivity | ||
|
|
||
| class HistoryActivity : AppCompatActivity() { | ||
| private lateinit var vm:HistoryViewModel | ||
| private lateinit var binding: ActivityHistoryBinding | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
|
|
||
| //viewmodel | ||
| vm = ViewModelProvider( | ||
| this, | ||
| ViewModelProvider.NewInstanceFactory() | ||
| )[HistoryViewModel::class.java] | ||
| vm.getHistory() | ||
|
|
||
| //binding | ||
| binding = DataBindingUtil.setContentView(this, R.layout.activity_history) | ||
| binding.vm = vm | ||
| binding.lifecycleOwner = this | ||
| binding.historyRecycler.adapter = HistoryRecyclerAdapter(){ | ||
| val mainIntent = Intent(this, MainActivity::class.java).apply { | ||
| putExtra("title", it) | ||
| } | ||
| startActivity(mainIntent) | ||
| } | ||
|
|
||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package com.example.mvvm2.ui.history | ||
|
|
||
| import android.annotation.SuppressLint | ||
| import android.view.LayoutInflater | ||
| import android.view.View | ||
| import android.view.ViewGroup | ||
| import androidx.recyclerview.widget.RecyclerView | ||
| import com.example.mvvm2.databinding.ItemHistoryBinding | ||
|
|
||
| class HistoryRecyclerAdapter(val historyClickListener: (String) -> Unit) : | ||
| RecyclerView.Adapter<HistoryRecyclerAdapter.ViewHolder>() { | ||
|
|
||
| private val histories:ArrayList<String> = arrayListOf() | ||
|
|
||
| override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryRecyclerAdapter.ViewHolder { | ||
| val binding = ItemHistoryBinding.inflate(LayoutInflater.from(parent.context), parent, false) | ||
| return ViewHolder(binding) | ||
| } | ||
|
|
||
| override fun onBindViewHolder(holder: HistoryRecyclerAdapter.ViewHolder, position: Int) { | ||
| holder.bind(histories[position]) | ||
| holder.itemView.setOnClickListener { historyClickListener(histories[position])} | ||
| } | ||
|
|
||
| override fun getItemCount(): Int = histories.size | ||
|
|
||
| @SuppressLint("NotifyDataSetChanged") | ||
| fun setItem(histories: ArrayList<String>) { | ||
| this.histories.clear() | ||
| this.histories.addAll(histories) | ||
| notifyDataSetChanged() | ||
| } | ||
|
|
||
| class ViewHolder(private val binding:ItemHistoryBinding):RecyclerView.ViewHolder(binding.root){ | ||
| fun bind(history:String) { | ||
| binding.history = history | ||
| } | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.example.mvvm2.ui.history | ||
|
|
||
| import androidx.lifecycle.MutableLiveData | ||
| import androidx.lifecycle.ViewModel | ||
| import com.example.mvvm2.data.repository.RepositoryImpl | ||
|
|
||
| class HistoryViewModel:ViewModel() { | ||
| val repository:RepositoryImpl = RepositoryImpl() | ||
|
|
||
| val historyList: MutableLiveData<ArrayList<String>?> = MutableLiveData() | ||
|
|
||
| fun getHistory () { | ||
| historyList.value = repository.getHistory() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import androidx.databinding.DataBindingUtil | |
| import androidx.lifecycle.ViewModelProvider | ||
| import com.example.mvvm2.R | ||
| import com.example.mvvm2.databinding.ActivityMainBinding | ||
| import com.example.mvvm2.ui.history.HistoryActivity | ||
| import com.example.mvvm2.ui.moive.MovieActivity | ||
| import javax.security.auth.callback.Callback | ||
| import kotlin.math.log | ||
|
|
@@ -26,6 +27,12 @@ class MainActivity : AppCompatActivity() { | |
| ViewModelProvider.NewInstanceFactory() | ||
| )[MainViewModel::class.java] | ||
|
|
||
|
|
||
| if (intent.getStringExtra("title") != null) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 스코프 함수를 써서 해보세요! |
||
| vm.query = intent.getStringExtra("title").toString() | ||
| vm.getMoveList() | ||
| } | ||
|
|
||
| // binding | ||
| binding = DataBindingUtil.setContentView(this, R.layout.activity_main) | ||
| binding.vm = vm | ||
|
|
@@ -36,5 +43,11 @@ class MainActivity : AppCompatActivity() { | |
| } | ||
| startActivity(movieIntent) | ||
| } | ||
|
|
||
| //History button clickListener | ||
| binding.mainHistoryBtn.setOnClickListener{ | ||
| val historyIntent = Intent(this, HistoryActivity::class.java) | ||
| startActivity(historyIntent) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,27 @@ | ||
| package com.example.mvvm2.ui.main | ||
|
|
||
| import android.util.Log | ||
| import android.view.View | ||
| import android.widget.ImageView | ||
| import android.widget.TextView | ||
| import androidx.databinding.BindingAdapter | ||
| import androidx.recyclerview.widget.LinearLayoutManager | ||
| import androidx.recyclerview.widget.RecyclerView | ||
| import com.bumptech.glide.Glide | ||
| import com.example.mvvm2.R | ||
| import com.example.mvvm2.data.model.Movie | ||
| import com.example.mvvm2.ui.history.HistoryRecyclerAdapter | ||
| import org.w3c.dom.Text | ||
|
|
||
| @BindingAdapter("bind_visible_if") | ||
| fun setVisibility(textView:TextView, empty:Boolean) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. view 다음에 들어오는 데이터는 nullable하게 받아줘야 합니다! |
||
| if (empty) { | ||
| textView.visibility = View.VISIBLE | ||
| } | ||
| else { | ||
| textView.visibility = View.GONE | ||
| } | ||
|
Comment on lines
+18
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 삼항 연산을 쓰는게 더 깔끔할거같아요 |
||
| } | ||
|
|
||
| @BindingAdapter("bind_movie_list") | ||
| fun setMovie(recyclerView: RecyclerView, movies:ArrayList<Movie>?){ | ||
|
|
@@ -23,4 +37,11 @@ fun setImage(imageView: ImageView, url:String) { | |
| .load(url) | ||
| .error(R.drawable.ic_launcher_foreground) | ||
| .into(imageView) | ||
| } | ||
|
|
||
| @BindingAdapter("bind_history_list") | ||
| fun setHistory(recyclerView: RecyclerView, histories: ArrayList<String>?) { | ||
| if (histories != null) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 스코프함수! |
||
| (recyclerView.adapter as HistoryRecyclerAdapter).setItem(histories) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,10 @@ import com.example.mvvm2.data.model.Movie | |
| import com.example.mvvm2.databinding.ItemMainBinding | ||
| import com.example.mvvm2.ui.moive.MovieActivity | ||
|
|
||
| class MainRecyclerAdapter ( val movieClickListener: (Movie)->Unit) : RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() { | ||
| var movies:ArrayList<Movie> = arrayListOf() | ||
| class MainRecyclerAdapter(val movieClickListener: (Movie) -> Unit) : | ||
| RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() { | ||
|
|
||
| var movies: ArrayList<Movie> = arrayListOf() | ||
|
|
||
| override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { | ||
| val binding = ItemMainBinding.inflate(LayoutInflater.from(parent.context), parent, false) | ||
|
|
@@ -18,24 +20,23 @@ class MainRecyclerAdapter ( val movieClickListener: (Movie)->Unit) : RecyclerVie | |
|
|
||
| override fun onBindViewHolder(holder: ViewHolder, position: Int) { | ||
| holder.bind(movies[position]) | ||
| holder.itemView.setOnClickListener{movieClickListener(movies[position])} | ||
| holder.itemView.setOnClickListener { movieClickListener(movies[position]) } | ||
|
Comment on lines
22
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. binding 내부로 click listener를 넣어서 사용하는게 더 깔끔해보여요! |
||
| } | ||
|
|
||
| override fun getItemCount(): Int { | ||
| return movies.size | ||
| } | ||
|
|
||
| fun setItem(movies : ArrayList<Movie>) { | ||
| fun setItem(movies: ArrayList<Movie>) { | ||
| this.movies.clear() | ||
| this.movies.addAll(movies) | ||
| notifyDataSetChanged() | ||
| } | ||
|
|
||
| class ViewHolder(private val binding: ItemMainBinding) :RecyclerView.ViewHolder(binding.root) { | ||
| fun bind (movie:Movie) { | ||
| class ViewHolder(private val binding: ItemMainBinding) : RecyclerView.ViewHolder(binding.root) { | ||
| fun bind(movie: Movie) { | ||
| binding.movie = movie | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 접근 방식은 좋지 못해요 전역에서 사용하는건데 safe하지 않습니다!
잘 생각해보면 DI로 ViewModel init할때 넣으면 좋을 것 같네요