ソースを参照

Refactoring of recycler view holders

Vadik Sirekanyan 7 年 前
コミット
d078f4e86d

+ 49 - 0
app/src/main/java/com/sirekanyan/knigopis/feature/books/BookDataViewHolder.kt

@@ -0,0 +1,49 @@
+package com.sirekanyan.knigopis.feature.books
+
+import android.view.View
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
+import com.sirekanyan.knigopis.common.extensions.*
+import com.sirekanyan.knigopis.common.setProgressSmoothly
+import com.sirekanyan.knigopis.model.BookDataModel
+import com.sirekanyan.knigopis.model.BookModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.book.*
+
+class BookDataViewHolder(
+    override val containerView: View,
+    onClick: (BookDataModel) -> Unit,
+    onLongClick: (BookDataModel) -> Unit
+) : CommonViewHolder<BookModel>(containerView),
+    LayoutContainer {
+
+    private val resources = containerView.resources
+
+    init {
+        containerView.setOnClickListener {
+            model?.let {
+                onClick(it as BookDataModel)
+            }
+        }
+        containerView.setOnLongClickListener {
+            model?.let {
+                onLongClick(it as BookDataModel)
+            }
+            true
+        }
+    }
+
+    override fun onBind(position: Int, model: BookModel) {
+        val book = model as BookDataModel
+        bookImage.setSquareImage(book.image)
+        bookTitle.text = resources.getTitleString(book.title)
+        bookAuthor.text = resources.getAuthorString(book.author)
+        bookProgress.progress = 0
+        if (book.isFinished) {
+            bookProgress.hideNow()
+        } else {
+            bookProgress.showNow()
+            bookProgress.setProgressSmoothly(book.priority)
+        }
+    }
+
+}

+ 31 - 0
app/src/main/java/com/sirekanyan/knigopis/feature/books/BookHeaderViewHolder.kt

@@ -0,0 +1,31 @@
+package com.sirekanyan.knigopis.feature.books
+
+import android.view.View
+import com.sirekanyan.knigopis.R
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
+import com.sirekanyan.knigopis.common.extensions.showNow
+import com.sirekanyan.knigopis.model.BookHeaderModel
+import com.sirekanyan.knigopis.model.BookModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.header.*
+
+class BookHeaderViewHolder(
+    override val containerView: View
+) : CommonViewHolder<BookModel>(containerView),
+    LayoutContainer {
+
+    private val resources = containerView.context.resources
+
+    override fun onBind(position: Int, model: BookModel) {
+        val header = model as BookHeaderModel
+        headerTitle.text = header.title
+        headerDivider.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE
+        headerCount.text = resources.getQuantityString(
+            R.plurals.common_header_books,
+            header.count,
+            header.count
+        )
+        headerCount.showNow(header.count > 0)
+    }
+
+}

+ 25 - 30
app/src/main/java/com/sirekanyan/knigopis/feature/notes/NoteViewHolder.kt

@@ -1,40 +1,35 @@
 package com.sirekanyan.knigopis.feature.notes
 
-import android.support.v7.widget.RecyclerView
-import android.text.format.DateUtils
 import android.view.View
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
 import com.sirekanyan.knigopis.common.extensions.setCircleImage
 import com.sirekanyan.knigopis.common.extensions.setSquareImage
-import kotlinx.android.synthetic.main.note.view.*
-
-class NoteViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
-
-    fun setTitle(title: String) {
-        view.bookTitle.text = title
-    }
-
-    fun setAuthor(author: String) {
-        view.bookAuthor.text = author
-    }
-
-    fun setNotes(notes: String) {
-        view.userNotes.text = notes
-    }
-
-    fun setTimestamp(timestamp: Long) {
-        view.userDate.text = DateUtils.getRelativeTimeSpanString(timestamp)
-    }
-
-    fun setNickname(nickname: String) {
-        view.userNickname.text = nickname
-    }
-
-    fun setAvatarUrl(url: String?) {
-        view.userSmallAvatar.setCircleImage(url)
+import com.sirekanyan.knigopis.model.NoteModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.note.*
+
+class NoteViewHolder(
+    override val containerView: View,
+    private val onClick: (NoteModel) -> Unit
+) : CommonViewHolder<NoteModel>(containerView),
+    LayoutContainer {
+
+    init {
+        containerView.setOnClickListener {
+            model?.let {
+                onClick(it)
+            }
+        }
     }
 
-    fun setBookImageUrl(url: String?) {
-        view.bookImage.setSquareImage(url)
+    override fun onBind(position: Int, model: NoteModel) {
+        bookImage.setSquareImage(model.bookImage)
+        bookTitle.text = model.bookTitle
+        bookAuthor.text = model.bookAuthor
+        userNotes.text = model.noteContent
+        userDate.text = model.noteDate
+        userNickname.text = model.userName
+        userSmallAvatar.setCircleImage(model.userImage)
     }
 
 }

+ 1 - 1
app/src/main/java/com/sirekanyan/knigopis/feature/notes/NotesAdapter.kt

@@ -15,7 +15,7 @@ class NotesAdapter(
         NoteViewHolder(parent.inflate(R.layout.note), onClick)
 
     override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
-        holder.setNote(getItem(position))
+        holder.bind(position, getItem(position))
     }
 
 }

+ 0 - 49
app/src/main/java/com/sirekanyan/knigopis/feature/user/BooksAdapter.kt

@@ -1,49 +0,0 @@
-package com.sirekanyan.knigopis.feature.user
-
-import com.sirekanyan.knigopis.R
-import com.sirekanyan.knigopis.common.adapter.AbstractBooksAdapter
-import com.sirekanyan.knigopis.common.adapter.BookHeaderViewHolder
-import com.sirekanyan.knigopis.common.adapter.BookItemViewHolder
-import com.sirekanyan.knigopis.common.view.dialog.DialogFactory
-import com.sirekanyan.knigopis.common.view.dialog.createDialogItem
-import com.sirekanyan.knigopis.feature.book.createNewBookIntent
-import com.sirekanyan.knigopis.repository.model.Book
-import com.sirekanyan.knigopis.repository.model.BookHeader
-import com.sirekanyan.knigopis.repository.model.FinishedBook
-
-class BooksAdapter(
-    books: List<Book>,
-    private val dialogs: DialogFactory
-) : AbstractBooksAdapter(books, R.layout.header, R.layout.user_book) {
-
-    override fun bindHeaderViewHolder(holder: BookHeaderViewHolder, header: BookHeader, i: Int) {
-        if (header.title.isEmpty()) {
-            holder.setTitle(R.string.books_header_done_other)
-        } else {
-            holder.setTitle(header.title)
-        }
-        holder.showTopDivider(i > 0)
-        holder.setBooksCount(header.count)
-    }
-
-    override fun bindItemViewHolder(holder: BookItemViewHolder, book: FinishedBook) {
-        holder.setTitle(book.title)
-        holder.setAuthor(book.author)
-        holder.setNotes(book.notes)
-        holder.setBookImageUrl(book.bookImageUrl)
-        holder.setOnLongClick { view ->
-            val context = view.context
-            dialogs.showDialog(
-                book.title + " — " + book.author,
-                createDialogItem(R.string.user_button_todo, R.drawable.ic_playlist_add) {
-                    context.startActivity(context.createNewBookIntent(book.title, book.author))
-                },
-                createDialogItem(R.string.user_button_done, R.drawable.ic_playlist_add_check) {
-                    context.startActivity(context.createNewBookIntent(book.title, book.author, 100))
-                }
-            )
-            true
-        }
-    }
-
-}

+ 36 - 0
app/src/main/java/com/sirekanyan/knigopis/feature/user/UserBookDataViewHolder.kt

@@ -0,0 +1,36 @@
+package com.sirekanyan.knigopis.feature.user
+
+import android.view.View
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
+import com.sirekanyan.knigopis.common.extensions.setSquareImage
+import com.sirekanyan.knigopis.common.extensions.showNow
+import com.sirekanyan.knigopis.model.BookDataModel
+import com.sirekanyan.knigopis.model.BookModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.user_book.*
+
+class UserBookDataViewHolder(
+    override val containerView: View,
+    private val onClick: (BookDataModel) -> Unit
+) : CommonViewHolder<BookModel>(containerView),
+    LayoutContainer {
+
+    init {
+        containerView.setOnLongClickListener {
+            model?.let {
+                onClick(it as BookDataModel)
+            }
+            true
+        }
+    }
+
+    override fun onBind(position: Int, model: BookModel) {
+        val book = model as BookDataModel
+        bookTitle.text = book.title
+        bookAuthor.text = book.author
+        bookNotes.showNow(book.notes.isNotEmpty())
+        bookNotes.text = book.notes
+        bookImage.setSquareImage(book.image)
+    }
+
+}

+ 32 - 0
app/src/main/java/com/sirekanyan/knigopis/feature/user/UserBookHeaderViewHolder.kt

@@ -0,0 +1,32 @@
+package com.sirekanyan.knigopis.feature.user
+
+import android.view.View
+import com.sirekanyan.knigopis.R
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
+import com.sirekanyan.knigopis.common.extensions.showNow
+import com.sirekanyan.knigopis.model.BookHeaderModel
+import com.sirekanyan.knigopis.model.BookModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.header.*
+
+class UserBookHeaderViewHolder(
+    override val containerView: View
+) : CommonViewHolder<BookModel>(containerView),
+    LayoutContainer {
+
+    private val context = containerView.context
+    private val defaultTitle = context.getString(R.string.books_header_done_other)
+
+    override fun onBind(position: Int, model: BookModel) {
+        val header = model as BookHeaderModel
+        headerTitle.text = header.title.takeUnless(String::isEmpty) ?: defaultTitle
+        headerCount.text = context.resources.getQuantityString(
+            R.plurals.common_header_books,
+            header.count,
+            header.count
+        )
+        headerCount.showNow()
+        headerDivider.showNow(position > 0)
+    }
+
+}

+ 29 - 24
app/src/main/java/com/sirekanyan/knigopis/feature/users/UserViewHolder.kt

@@ -1,33 +1,38 @@
 package com.sirekanyan.knigopis.feature.users
 
-import android.support.v7.widget.RecyclerView
 import android.view.View
-import com.sirekanyan.knigopis.R
+import com.sirekanyan.knigopis.common.adapter.CommonViewHolder
 import com.sirekanyan.knigopis.common.extensions.setCircleImage
-import com.sirekanyan.knigopis.common.extensions.showNow
-import com.sirekanyan.knigopis.common.getHtmlString
-import kotlinx.android.synthetic.main.user.view.*
-
-class UserViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
-
-    private val context = view.context.applicationContext
-
-    fun setAvatarUrl(url: String?) {
-        view.userAvatar.setCircleImage(url)
-    }
-
-    fun setNickname(nickname: String) {
-        view.userNickname.text = nickname
-    }
-
-    fun setBooksCount(count: Int) {
-        view.totalBooksCount.showNow(count > 0)
-        view.totalBooksCount.text = count.toString()
+import com.sirekanyan.knigopis.model.UserModel
+import kotlinx.android.extensions.LayoutContainer
+import kotlinx.android.synthetic.main.user.*
+
+class UserViewHolder(
+    override val containerView: View,
+    private val onClick: (UserModel) -> Unit,
+    private val onLongClick: (UserModel) -> Unit
+) : CommonViewHolder<UserModel>(containerView),
+    LayoutContainer {
+
+    init {
+        containerView.setOnClickListener {
+            model?.let {
+                onClick(it)
+            }
+        }
+        containerView.setOnLongClickListener {
+            model?.let {
+                onLongClick(it)
+            }
+            true
+        }
     }
 
-    fun setNewBooksCount(count: Int) {
-        view.newBooksCount.showNow(count > 0)
-        view.newBooksCount.text = context.getHtmlString(R.string.user_new_books_count, count)
+    override fun onBind(position: Int, model: UserModel) {
+        userAvatar.setCircleImage(model.image)
+        userNickname.text = model.name
+        totalBooksCount.text = model.booksCount
+        newBooksCount.text = model.newBooksCount
     }
 
 }

+ 9 - 40
app/src/main/java/com/sirekanyan/knigopis/feature/users/UsersAdapter.kt

@@ -1,53 +1,22 @@
 package com.sirekanyan.knigopis.feature.users
 
-import android.support.v7.widget.RecyclerView
+import android.support.v7.recyclerview.extensions.ListAdapter
 import android.view.ViewGroup
 import com.sirekanyan.knigopis.R
-import com.sirekanyan.knigopis.Router
-import com.sirekanyan.knigopis.common.ResourceProvider
+import com.sirekanyan.knigopis.common.adapter.SimpleItemCallback
 import com.sirekanyan.knigopis.common.extensions.inflate
-import com.sirekanyan.knigopis.common.view.dialog.DialogFactory
-import com.sirekanyan.knigopis.common.view.dialog.createDialogItem
-import com.sirekanyan.knigopis.repository.model.subscription.Subscription
+import com.sirekanyan.knigopis.model.UserModel
 
 class UsersAdapter(
-    private val users: List<Subscription>,
-    private val router: Router,
-    private val dialogs: DialogFactory,
-    private val resources: ResourceProvider
-) : RecyclerView.Adapter<UserViewHolder>() {
+    private val onClick: (UserModel) -> Unit,
+    private val onLongClick: (UserModel) -> Unit
+) : ListAdapter<UserModel, UserViewHolder>(SimpleItemCallback(UserModel::id)) {
 
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
-        val view = parent.inflate(R.layout.user)
-        return UserViewHolder(view)
-    }
-
-    override fun getItemCount(): Int {
-        return users.size
-    }
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
+        UserViewHolder(parent.inflate(R.layout.user), onClick, onLongClick)
 
     override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
-        val subscription = users[position]
-        val user = subscription.subUser
-        holder.setAvatarUrl(user.avatar)
-        holder.setNickname(user.name)
-        holder.setBooksCount(user.booksCount)
-        holder.setNewBooksCount(subscription.newBooksCount)
-        holder.view.setOnClickListener {
-            router.openUserScreen(user.id, user.name, user.avatar)
-        }
-        val dialogItems = user.profiles
-            .map { UriItem(it, resources) }
-            .distinctBy(UriItem::title)
-            .map { uriItem ->
-                createDialogItem(uriItem.title, uriItem.iconRes) {
-                    router.openWebPage(uriItem.uri)
-                }
-            }
-        holder.view.setOnLongClickListener {
-            dialogs.showDialog(user.name, *dialogItems.toTypedArray())
-            true
-        }
+        holder.bind(position, getItem(position))
     }
 
 }