As of now, the activity does not remember whether a conversation is
switched across configuration changes (such as screen rotations). Fix
this by adding onSaveInstanceState() and onRestoreInstanceState()
callbacks in the activity to pass this information to the new instance.
To make the implementation of this simpler, all code to configure the
MessageListView, which was duplicated in several places in the codebase,
has been moved to the MessageListView's constructor.
While we're at it, make the padding setting independent of screen
density instead of specifying in fixed pixels (equivalent to specifying
the value in dp instead of px), and increase the padding for switched
views. This ensures that message text isn't obscured by the gradient at
the edges of the ConversationGallery, which started happening when we
began caching MessageListViews in the DeckAdapter.
Each IRCConnection starts an input thread and an output thread when
created; if not stopped, these threads continue to hold the IRCService,
resulting in a leak when the service is stopped. Fix this by using
PircBot's dispose() to stop the threads when disposing of the
IRCConnection.
There are at least two significant memory leaks in Yaaic, which cause
the client to force close after a few hours with an
OutOfMemoryException:
(1) The IRCService holds Conversation objects, which contain a
MessageListAdapter, which have references to the ConversationActivity
context. This causes Activity contexts to outlast the Activity, causing
a significant memory leak over time.
Fix this by holding the MessageListAdapter in the ConversationActivity's
DeckAdapter instead of in the Conversation objects. The DeckAdapter's
lifecycle matches that of the Activity, so this prevents the leak.
(2) Every call to DeckAdapter.getView()/renderConversation() creates a
new MessageListView and adds it to the deck. But adding the view to
the deck causes the deck to take a reference to the view, leaking the
MessageListView until the Activity is finished. (This has the effect of
exacerbating the first leak, since the Activity context holds a
reference to the deck.)
Fix this leak by caching MessageListViews in the DeckAdapter, and
returning an existing MessageListView for a Conversation in getView() if
one already exists.
If a private message that should open a new query window contains a
mention of the user's nick, the expected new window fails to open
because the isMentioned() path tries to use
server.getConversation().setStatus(), and server.getConversation() is
null in this case. Fix this by moving the attempt to highlight the
window to a point where a conversation is guaranteed to exist.
This has two advantages:
(1) The activity remembers which conversation was last selected if it's
destroyed (e.g. via the Back button) and then recreated with the connection
still running.
(2) It prevents onCreate() from clearing all the mentioned notifications for
the conversations in that activity.