Some performance improvements

This commit is contained in:
Christian Basler 2017-09-12 21:28:56 +02:00
parent 9dd1b457e3
commit 1e8b71e43b
7 changed files with 107 additions and 27 deletions

View File

@ -166,18 +166,17 @@ class MessageDetailFragment : Fragment() {
return true
}
R.id.delete -> {
Singleton.labeler.delete(item)
if (isInTrash(item)) {
messageRepo.remove(item)
} else {
item.labels.clear()
item.addLabels(messageRepo.getLabels(Label.Type.TRASH))
messageRepo.save(item)
}
activity.onBackPressed()
return true
}
R.id.mark_unread -> {
item.addLabels(messageRepo.getLabels(Label.Type.UNREAD))
Singleton.labeler.markAsUnread(item)
messageRepo.save(item)
if (activity is MainActivity) {
(activity as MainActivity).updateUnread()
@ -188,7 +187,7 @@ class MessageDetailFragment : Fragment() {
if (item.isUnread() && activity is MainActivity) {
(activity as MainActivity).updateUnread()
}
item.labels.clear()
Singleton.labeler.archive(item)
messageRepo.save(item)
return true
}

View File

@ -17,11 +17,14 @@
package ch.dissem.apps.abit
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.OnScrollListener
import android.view.*
import android.widget.Toast
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
@ -29,6 +32,7 @@ import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
import ch.dissem.apps.abit.listener.ListSelectionListener
import ch.dissem.apps.abit.repository.AndroidMessageRepository
import ch.dissem.apps.abit.repository.AndroidMessageRepository.Companion.LABEL_ARCHIVE
import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.util.FabUtils
import ch.dissem.bitmessage.entity.Plaintext
@ -41,9 +45,12 @@ import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import kotlinx.android.synthetic.main.fragment_message_list.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.support.v4.onUiThread
import org.jetbrains.anko.uiThread
import java.util.*
private const val PAGE_SIZE = 15
/**
* A list fragment representing a list of Messages. This fragment
* also supports tablet devices by allowing list items to be given an
@ -56,12 +63,33 @@ import java.util.*
*/
class MessageListFragment : Fragment(), ListHolder<Label> {
private var layoutManager: RecyclerView.LayoutManager? = null
private var isLoading = false
private var isLastPage = false
private var layoutManager: LinearLayoutManager? = null
private var swipeableMessageAdapter: SwipeableMessageAdapter? = null
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
private val recyclerViewOnScrollListener = object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
layoutManager?.let { layoutManager ->
val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if (!isLoading && !isLastPage) {
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - 5
&& firstVisibleItemPosition >= 0
&& totalItemCount >= PAGE_SIZE) {
loadMoreItems()
}
}
}
}
}
override var currentLabel: Label? = null
private var emptyTrashMenuItem: MenuItem? = null
@ -70,6 +98,20 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
private val backStack = Stack<Label>()
fun loadMoreItems() {
isLoading = true
swipeableMessageAdapter?.let { messageAdapter ->
doAsync {
val messages = messageRepo.findMessages(currentLabel, messageAdapter.itemCount, PAGE_SIZE)
onUiThread {
messageAdapter.addAll(messages)
isLoading = false
isLastPage = messages.size < PAGE_SIZE
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -82,10 +124,8 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
initFab(activity)
messageRepo = Singleton.getMessageRepository(activity)
if (backStack.isEmpty()) {
if (backStack.isEmpty() && currentLabel == null) {
doUpdateList(activity.selectedLabel)
} else {
doUpdateList(backStack.peek())
}
}
@ -119,13 +159,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
}
}
doAsync {
messageRepo.findMessageIds(label)
.map { messageRepo.getMessage(it) }
.forEach { message ->
uiThread { swipeableMessageAdapter?.add(message) }
}
}
loadMoreItems()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
@ -189,6 +223,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
recycler_view.layoutManager = layoutManager
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableMessageAdapter
recycler_view.itemAnimator = animator
recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
recycler_view.addItemDecoration(SimpleListDividerDecorator(
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true))
@ -204,6 +239,17 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
recyclerViewTouchActionGuardManager = touchActionGuardManager
recyclerViewSwipeManager = swipeManager
this.swipeableMessageAdapter = adapter
Singleton.labeler.listener = { message, added, removed ->
if (added.contains(currentLabel)) {
// TODO: add to current list, at correct position
} else if (removed.contains(currentLabel)) {
swipeableMessageAdapter?.remove(message)
} else if (removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD }) {
// TODO: update if in current list, maybe update unread badges
swipeableMessageAdapter?.update(message)
}
}
}
private fun initFab(context: MainActivity) {
@ -295,4 +341,10 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
true
}
}
fun addMessage(message: Plaintext) {
if (message.labels.contains(currentLabel) || (currentLabel == LABEL_ARCHIVE && message.labels.isEmpty())) {
swipeableMessageAdapter?.addFirst(message)
}
}
}

View File

@ -96,6 +96,35 @@ class SwipeableMessageAdapter : RecyclerView.Adapter<SwipeableMessageAdapter.Vie
notifyDataSetChanged()
}
fun addFirst(item: Plaintext) {
val index = data.size
data.addFirst(item)
notifyItemInserted(index)
}
fun addAll(items: Collection<Plaintext>) {
val index = data.size
data.addAll(items)
notifyItemRangeInserted(index, items.size)
}
fun remove(item: Plaintext) {
val index = data.indexOf(item)
data.removeIf { it.id == item.id }
notifyItemRemoved(index)
}
fun update(item: Plaintext) {
data.replaceAll {
if (it.id == item.id) {
item
} else {
it
}
}
notifyItemChanged(data.indexOf(item))
}
fun clear(newLabel: Label?) {
label = newLabel
data.clear()

View File

@ -17,16 +17,12 @@
package ch.dissem.apps.abit.listener
import android.content.Context
import java.util.Deque
import java.util.LinkedList
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import ch.dissem.apps.abit.MainActivity
import ch.dissem.apps.abit.notification.NewMessageNotification
import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.entity.Plaintext
import java.util.*
import java.util.concurrent.Executors
/**
* Listens for decrypted Bitmessage messages. Does show a notification.

View File

@ -42,10 +42,10 @@ import java.util.*
*/
class AndroidMessageRepository(private val sql: SqlHelper, private val context: Context) : AbstractMessageRepository() {
override fun findMessages(label: Label?) = if (label === LABEL_ARCHIVE) {
super.findMessages(null as Label?)
override fun findMessages(label: Label?, offset: Int, limit: Int) = if (label === LABEL_ARCHIVE) {
super.findMessages(null as Label?, offset, limit)
} else {
super.findMessages(label)
super.findMessages(label, offset, limit)
}
fun findMessageIds(label: Label) = if (label === LABEL_ARCHIVE) {
@ -224,7 +224,7 @@ class AndroidMessageRepository(private val sql: SqlHelper, private val context:
return result
}
override fun find(where: String): List<Plaintext> {
override fun find(where: String, offset: Int, limit: Int): List<Plaintext> {
val result = LinkedList<Plaintext>()
// Define a projection that specifies which columns from the database
@ -235,7 +235,8 @@ class AndroidMessageRepository(private val sql: SqlHelper, private val context:
db.query(
TABLE_NAME, projection,
where, null, null, null,
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC"
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
if (limit == 0) null else "$offset, $limit"
).use { c ->
while (c.moveToNext()) {
val iv = c.getBlob(c.getColumnIndex(COLUMN_IV))

View File

@ -30,6 +30,7 @@ import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.payload.Pubkey
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
import ch.dissem.bitmessage.ports.DefaultLabeler
import ch.dissem.bitmessage.utils.ConversationService
import ch.dissem.bitmessage.utils.TTL
import ch.dissem.bitmessage.utils.UnixTime.DAY
@ -40,6 +41,7 @@ import org.jetbrains.anko.uiThread
* Provides singleton objects across the application.
*/
object Singleton {
val labeler = DefaultLabeler()
var bitmessageContext: BitmessageContext? = null
private set
private var conversationService: ConversationService? = null
@ -69,6 +71,7 @@ object Singleton {
.powRepo(powRepo)
.networkHandler(NioNetworkHandler())
.listener(getMessageListener(ctx))
.labeler(labeler)
.doNotSendPubkeyOnIdentityCreation()
.build()
}

View File

@ -5,7 +5,7 @@ configurations.all {
}
buildscript {
ext.kotlin_version = '1.1.4-2'
ext.kotlin_version = '1.1.4-3'
ext.anko_version = '0.10.1'
repositories {
jcenter()