Skip to content

Commit

Permalink
Use HackerNewsRepository in StoryActivity
Browse files Browse the repository at this point in the history
  • Loading branch information
tomoya0x00 committed Dec 29, 2018
1 parent 0964e82 commit 7406bec
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import android.view.MenuItem
import android.widget.Toast
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.*

abstract class BaseActivity : AppCompatActivity() {
Expand All @@ -25,13 +23,6 @@ abstract class BaseActivity : AppCompatActivity() {
setContentView(getContentView())
}

fun createRetrofit(url: String): Retrofit {
return Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(MoshiConverterFactory.create())
.build()
}

fun showError(throwable: Throwable) {
Log.v("error", throwable.message)
Toast.makeText(baseContext, throwable.message, Toast.LENGTH_SHORT).show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package droidkaigi.github.io.challenge2019
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import droidkaigi.github.io.challenge2019.data.api.response.Item
import droidkaigi.github.io.challenge2019.data.repository.entity.Comment
import droidkaigi.github.io.challenge2019.databinding.ItemCommentBinding


class CommentAdapter(
var comments: List<Item?>
var comments: List<Comment?>
) : RecyclerView.Adapter<CommentAdapter.ViewHolder>() {

class ViewHolder(val binding: ItemCommentBinding) : RecyclerView.ViewHolder(binding.root)
Expand All @@ -21,6 +21,6 @@ class CommentAdapter(
override fun getItemCount(): Int = comments.size

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.item = comments[position]
holder.binding.comment = comments[position]
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package droidkaigi.github.io.challenge2019

import android.annotation.SuppressLint
import android.arch.lifecycle.Observer
import android.os.AsyncTask
import android.os.Bundle
import android.support.v7.widget.DividerItemDecoration
Expand All @@ -13,13 +14,10 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar
import com.squareup.moshi.Types
import droidkaigi.github.io.challenge2019.data.api.HackerNewsApi
import droidkaigi.github.io.challenge2019.data.api.response.Item
import droidkaigi.github.io.challenge2019.data.repository.HackerNewsRepository
import droidkaigi.github.io.challenge2019.data.repository.Resource
import droidkaigi.github.io.challenge2019.data.repository.entity.Comment
import droidkaigi.github.io.challenge2019.data.repository.entity.Story
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CountDownLatch

class StoryActivity : BaseActivity() {
Expand All @@ -35,13 +33,11 @@ class StoryActivity : BaseActivity() {
private lateinit var progressView: ProgressBar

private lateinit var commentAdapter: CommentAdapter
private lateinit var hackerNewsApi: HackerNewsApi

private var getCommentsTask: AsyncTask<Long, Unit, List<Item?>>? = null
private var hideProgressTask: AsyncTask<Unit, Unit, Unit>? = null
private val storyJsonAdapter = moshi.adapter(Story::class.java)
private val itemsJsonAdapter =
moshi.adapter<List<Item?>>(Types.newParameterizedType(List::class.java, Item::class.java))
private val commentsJsonAdapter =
moshi.adapter<List<Comment?>>(Types.newParameterizedType(List::class.java, Comment::class.java))

private var story: Story? = null

Expand All @@ -59,10 +55,6 @@ class StoryActivity : BaseActivity() {
storyJsonAdapter.fromJson(it)
}

val retrofit = createRetrofit("https://hacker-news.firebaseio.com/v0/")

hackerNewsApi = retrofit.create(HackerNewsApi::class.java)

recyclerView.isNestedScrollingEnabled = false
val itemDecoration = DividerItemDecoration(recyclerView.context, DividerItemDecoration.VERTICAL)
recyclerView.addItemDecoration(itemDecoration)
Expand All @@ -73,7 +65,7 @@ class StoryActivity : BaseActivity() {

val savedComments = savedInstanceState?.let { bundle ->
bundle.getString(STATE_COMMENTS)?.let { itemsJson ->
itemsJsonAdapter.fromJson(itemsJson)
commentsJsonAdapter.fromJson(itemsJson)
}
}

Expand All @@ -89,7 +81,7 @@ class StoryActivity : BaseActivity() {
}

private fun loadUrlAndComments() {
if (story == null) return
val story = this.story ?: return

val progressLatch = CountDownLatch(2)

Expand Down Expand Up @@ -120,45 +112,24 @@ class StoryActivity : BaseActivity() {
progressLatch.countDown()
}
}
webView.loadUrl(story!!.url)

getCommentsTask = @SuppressLint("StaticFieldLeak") object : AsyncTask<Long, Unit, List<Item?>>() {
override fun doInBackground(vararg itemIds: Long?): List<Item?> {
val ids = itemIds.mapNotNull { it }
val itemMap = ConcurrentHashMap<Long, Item?>()
val latch = CountDownLatch(ids.size)

ids.forEach { id ->
hackerNewsApi.getItem(id).enqueue(object : Callback<Item> {
override fun onResponse(call: Call<Item>, response: Response<Item>) {
response.body()?.let { item -> itemMap[id] = item }
latch.countDown()
}

override fun onFailure(call: Call<Item>, t: Throwable) {
latch.countDown()
showError(t)
}
})
webView.loadUrl(story.url)

val liveComments = HackerNewsRepository.getComments(story)
liveComments.observe(this, Observer { resource ->
when (resource) {
is Resource.Success -> {
progressLatch.countDown()
commentAdapter.comments = resource.data
commentAdapter.notifyDataSetChanged()
liveComments.removeObservers(this)
}

try {
latch.await()
} catch (e: InterruptedException) {
return emptyList()
is Resource.Error -> {
progressLatch.countDown()
showError(resource.t)
liveComments.removeObservers(this)
}

return ids.map { itemMap[it] }
}

override fun onPostExecute(items: List<Item?>) {
progressLatch.countDown()
commentAdapter.comments = items
commentAdapter.notifyDataSetChanged()
}
}

getCommentsTask?.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, *story!!.commentIds.toTypedArray())
})
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
Expand All @@ -174,17 +145,14 @@ class StoryActivity : BaseActivity() {

override fun onSaveInstanceState(outState: Bundle?) {
outState?.apply {
putString(STATE_COMMENTS, itemsJsonAdapter.toJson(commentAdapter.comments))
putString(STATE_COMMENTS, commentsJsonAdapter.toJson(commentAdapter.comments))
}

super.onSaveInstanceState(outState)
}

override fun onDestroy() {
super.onDestroy()
getCommentsTask?.run {
if (!isCancelled) cancel(true)
}
hideProgressTask?.run {
if (!isCancelled) cancel(true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ object HackerNewsRepository {

GetItemsTask(hackerNewsApi) { items ->
val comments = items.map { it?.toComment(emptyList()) }
liveData.value = if (comments.all { it == null }) {
liveData.value = if (!story.commentIds.isEmpty() && comments.all { it == null }) {
Resource.Error(Exception("failed to get all comments"))
} else {
Resource.Success(comments)
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/res/layout/item_comment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<data>

<variable
name="item"
type="droidkaigi.github.io.challenge2019.data.api.response.Item"
name="comment"
type="droidkaigi.github.io.challenge2019.data.repository.entity.Comment"
/>

<import
Expand All @@ -34,7 +34,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:text="@{item.author}"
android:text="@{comment.author}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
Expand All @@ -46,8 +46,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:text="@{item.text != null ? Html.fromHtml(item.text) : null}"
android:visibility="@{item.text != null ? View.VISIBLE : View.GONE}"
android:text="@{comment.text != null ? Html.fromHtml(comment.text) : null}"
android:visibility="@{comment.text != null ? View.VISIBLE : View.GONE}"
android:autoLink="all"
app:layout_constraintTop_toBottomOf="@id/author"
app:layout_constraintStart_toStartOf="parent"
Expand Down

0 comments on commit 7406bec

Please sign in to comment.