refactored base fragments and activities

fixed some memory leaks
This commit is contained in:
Mariotaku Lee 2017-01-07 19:34:42 +08:00
parent dd815fef84
commit 92a8609491
13 changed files with 54 additions and 56 deletions

View File

@ -37,7 +37,7 @@ import org.mariotaku.twidere.constant.IntentConstants.EXTRA_LONGITUDE
import org.mariotaku.twidere.fragment.iface.IBaseFragment import org.mariotaku.twidere.fragment.iface.IBaseFragment
import org.mariotaku.twidere.fragment.iface.IMapFragment import org.mariotaku.twidere.fragment.iface.IMapFragment
class GoogleMapFragment : SupportMapFragment(), Constants, IMapFragment, IBaseFragment { class GoogleMapFragment : SupportMapFragment(), Constants, IMapFragment, IBaseFragment<GoogleMapFragment> {
private val actionHelper = IBaseFragment.ActionHelper(this) private val actionHelper = IBaseFragment.ActionHelper(this)
@ -108,7 +108,7 @@ class GoogleMapFragment : SupportMapFragment(), Constants, IMapFragment, IBaseFr
} }
} }
override fun executeAfterFragmentResumed(useHandler: Boolean, action: (IBaseFragment) -> Unit) { override fun executeAfterFragmentResumed(useHandler: Boolean, action: (GoogleMapFragment) -> Unit) {
actionHelper.executeAfterFragmentResumed(useHandler, action) actionHelper.executeAfterFragmentResumed(useHandler, action)
} }

View File

@ -68,7 +68,7 @@ import java.util.*
import javax.inject.Inject import javax.inject.Inject
@SuppressLint("Registered") @SuppressLint("Registered")
open class BaseActivity : ChameleonActivity(), IExtendedActivity, IThemedActivity, open class BaseActivity : ChameleonActivity(), IExtendedActivity<BaseActivity>, IThemedActivity,
IControlBarActivity, OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity, OnFitSystemWindowsListener, SystemWindowsInsetsCallback,
KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback { KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback {
@ -273,7 +273,7 @@ open class BaseActivity : ChameleonActivity(), IExtendedActivity, IThemedActivit
actionHelper.dispatchOnResumeFragments() actionHelper.dispatchOnResumeFragments()
} }
override fun executeAfterFragmentResumed(action: (IExtendedActivity) -> Unit) { override fun executeAfterFragmentResumed(action: (BaseActivity) -> Unit) {
actionHelper.executeAfterFragmentResumed(action) actionHelper.executeAfterFragmentResumed(action)
} }

View File

@ -765,8 +765,11 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
} }
private fun showAutoRefreshConfirm() { private fun showAutoRefreshConfirm() {
val df = AutoRefreshConfirmDialogFragment() if (isFinishing) return
df.show(supportFragmentManager, "auto_refresh_confirm") executeAfterFragmentResumed { activity ->
val df = AutoRefreshConfirmDialogFragment()
df.show(activity.supportFragmentManager, "auto_refresh_confirm")
}
} }
private fun setTabPosition(initialTab: Int) { private fun setTabPosition(initialTab: Int) {

View File

@ -85,7 +85,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
override fun onFitSystemWindows(insets: Rect) { override fun onFitSystemWindows(insets: Rect) {
super.onFitSystemWindows(insets) super.onFitSystemWindows(insets)
val fragment = currentVisibleFragment val fragment = currentVisibleFragment
if (fragment is IBaseFragment) { if (fragment is IBaseFragment<*>) {
fragment.requestFitSystemWindows() fragment.requestFitSystemWindows()
} }
} }

View File

@ -25,7 +25,6 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.support.v4.app.DialogFragment import android.support.v4.app.DialogFragment
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.app.hasRunningLoadersSafe import android.support.v4.app.hasRunningLoadersSafe
import android.support.v4.content.ContextCompat import android.support.v4.content.ContextCompat
import android.support.v4.view.ViewPager import android.support.v4.view.ViewPager
@ -57,7 +56,7 @@ import java.io.File
import javax.inject.Inject import javax.inject.Inject
import android.Manifest.permission as AndroidPermissions import android.Manifest.permission as AndroidPermissions
class MediaViewerActivity : BaseActivity(), IExtendedActivity, IMediaViewerActivity { class MediaViewerActivity : BaseActivity(), IMediaViewerActivity {
@Inject @Inject
lateinit var mFileCache: FileCache lateinit var mFileCache: FileCache
@ -342,20 +341,20 @@ class MediaViewerActivity : BaseActivity(), IExtendedActivity, IMediaViewerActiv
private val PROGRESS_FRAGMENT_TAG = "progress" private val PROGRESS_FRAGMENT_TAG = "progress"
override fun dismissProgress() { override fun dismissProgress() {
val activity = context as IExtendedActivity val activity = context as IExtendedActivity<*>
activity.executeAfterFragmentResumed { activity -> activity.executeAfterFragmentResumed { activity ->
val fm = (activity as FragmentActivity).supportFragmentManager val fm = activity.supportFragmentManager
val fragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG) as? DialogFragment val fragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG) as? DialogFragment
fragment?.dismiss() fragment?.dismiss()
} }
} }
override fun showProgress() { override fun showProgress() {
val activity = context as IExtendedActivity val activity = context as IExtendedActivity<*>
activity.executeAfterFragmentResumed { activity -> activity.executeAfterFragmentResumed { activity ->
val fragment = ProgressDialogFragment() val fragment = ProgressDialogFragment()
fragment.isCancelable = false fragment.isCancelable = false
fragment.show((activity as FragmentActivity).supportFragmentManager, PROGRESS_FRAGMENT_TAG) fragment.show(activity.supportFragmentManager, PROGRESS_FRAGMENT_TAG)
} }
} }

View File

@ -19,19 +19,20 @@
package org.mariotaku.twidere.activity.iface package org.mariotaku.twidere.activity.iface
import android.support.v4.app.FragmentActivity
import java.util.* import java.util.*
/** /**
* Created by mariotaku on 15/12/28. * Created by mariotaku on 15/12/28.
*/ */
interface IExtendedActivity { interface IExtendedActivity<out A : FragmentActivity> {
fun executeAfterFragmentResumed(action: (IExtendedActivity) -> Unit) fun executeAfterFragmentResumed(action: (A) -> Unit)
class ActionHelper(private val activity: IExtendedActivity) { class ActionHelper<out A: FragmentActivity>(private val activity: A) {
private var fragmentResumed: Boolean = false private var fragmentResumed: Boolean = false
private val actionQueue = LinkedList<(IExtendedActivity) -> Unit>() private val actionQueue = LinkedList<(A) -> Unit>()
fun dispatchOnPause() { fun dispatchOnPause() {
fragmentResumed = false fragmentResumed = false
@ -45,14 +46,14 @@ interface IExtendedActivity {
private fun executePending() { private fun executePending() {
if (!fragmentResumed) return if (!fragmentResumed) return
var action: ((IExtendedActivity) -> Unit)? var action: ((A) -> Unit)?
do { do {
action = actionQueue.poll() action = actionQueue.poll()
action?.invoke(activity) action?.invoke(activity)
} while (action != null) } while (action != null)
} }
fun executeAfterFragmentResumed(action: (IExtendedActivity) -> Unit) { fun executeAfterFragmentResumed(action: (A) -> Unit) {
actionQueue.add(action) actionQueue.add(action)
executePending() executePending()
} }

View File

@ -61,7 +61,7 @@ abstract class AbsToolbarTabPagesFragment : BaseSupportFragment(), RefreshScroll
for (i in 0 until count) { for (i in 0 until count) {
if (i > currentItem - pageLimit - 1 || i < currentItem + pageLimit) { if (i > currentItem - pageLimit - 1 || i < currentItem + pageLimit) {
val obj = pagerAdapter!!.instantiateItem(viewPager, i) val obj = pagerAdapter!!.instantiateItem(viewPager, i)
if (obj is IBaseFragment) { if (obj is IBaseFragment<*>) {
obj.requestFitSystemWindows() obj.requestFitSystemWindows()
} }
} }

View File

@ -39,7 +39,7 @@ import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.sync.SyncController import org.mariotaku.twidere.util.sync.SyncController
import javax.inject.Inject import javax.inject.Inject
abstract class BasePreferenceFragment : PreferenceFragmentCompat(), IBaseFragment { abstract class BasePreferenceFragment : PreferenceFragmentCompat(), IBaseFragment<BasePreferenceFragment> {
private var ringtonePreferenceKey: String? = null private var ringtonePreferenceKey: String? = null
@Inject @Inject
@ -122,7 +122,7 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(), IBaseFragmen
return super.onPreferenceTreeClick(preference) return super.onPreferenceTreeClick(preference)
} }
override fun executeAfterFragmentResumed(useHandler: Boolean, action: (IBaseFragment) -> Unit) { override fun executeAfterFragmentResumed(useHandler: Boolean, action: (BasePreferenceFragment) -> Unit) {
actionHelper.executeAfterFragmentResumed(useHandler, action) actionHelper.executeAfterFragmentResumed(useHandler, action)
} }

View File

@ -29,7 +29,7 @@ import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import javax.inject.Inject import javax.inject.Inject
open class BaseSupportFragment : Fragment(), IBaseFragment { open class BaseSupportFragment : Fragment(), IBaseFragment<BaseSupportFragment> {
// Utility classes // Utility classes
@Inject @Inject
@ -69,7 +69,7 @@ open class BaseSupportFragment : Fragment(), IBaseFragment {
GeneralComponentHelper.build(context!!).inject(this) GeneralComponentHelper.build(context!!).inject(this)
} }
override fun executeAfterFragmentResumed(useHandler: Boolean, action: (IBaseFragment) -> Unit) { override fun executeAfterFragmentResumed(useHandler: Boolean, action: (BaseSupportFragment) -> Unit) {
actionHelper.executeAfterFragmentResumed(useHandler, action) actionHelper.executeAfterFragmentResumed(useHandler, action)
} }

View File

@ -300,8 +300,7 @@ class DraftsFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, OnItemCl
override fun onPreExecute() { override fun onPreExecute() {
super.onPreExecute() super.onPreExecute()
(activity as IExtendedActivity).executeAfterFragmentResumed { (activity as IExtendedActivity<*>).executeAfterFragmentResumed { activity ->
val activity = it as FragmentActivity
val f = ProgressDialogFragment.show(activity.supportFragmentManager, FRAGMENT_TAG_DELETING_DRAFTS) val f = ProgressDialogFragment.show(activity.supportFragmentManager, FRAGMENT_TAG_DELETING_DRAFTS)
f.isCancelable = false f.isCancelable = false
} }
@ -309,8 +308,7 @@ class DraftsFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, OnItemCl
override fun onPostExecute(result: Unit) { override fun onPostExecute(result: Unit) {
super.onPostExecute(result) super.onPostExecute(result)
(activity as IExtendedActivity).executeAfterFragmentResumed { (activity as IExtendedActivity<*>).executeAfterFragmentResumed { activity ->
val activity = it as FragmentActivity
val fm = activity.supportFragmentManager val fm = activity.supportFragmentManager
val f = fm.findFragmentByTag(FRAGMENT_TAG_DELETING_DRAFTS) val f = fm.findFragmentByTag(FRAGMENT_TAG_DELETING_DRAFTS)
if (f is DialogFragment) { if (f is DialogFragment) {

View File

@ -130,6 +130,7 @@ import org.mariotaku.twidere.util.support.WindowSupport
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback
import org.mariotaku.twidere.view.TabPagerIndicator import org.mariotaku.twidere.view.TabPagerIndicator
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener
import java.lang.ref.WeakReference
import java.util.* import java.util.*
class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener, class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener,
@ -931,14 +932,14 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
df?.dismiss() df?.dismiss()
} }
}.successUi { result -> }.successUi { result ->
executeAfterFragmentResumed { executeAfterFragmentResumed { fragment ->
val df = AddRemoveUserListDialogFragment() val df = AddRemoveUserListDialogFragment()
df.arguments = Bundle { df.arguments = Bundle {
this[EXTRA_ACCOUNT_KEY] = user.account_key this[EXTRA_ACCOUNT_KEY] = user.account_key
this[EXTRA_USER_KEY] = user.key this[EXTRA_USER_KEY] = user.key
this[EXTRA_USER_LISTS] = result this[EXTRA_USER_LISTS] = result
} }
df.show(fragmentManager, "add_remove_list") df.show(fragment.fragmentManager, "add_remove_list")
} }
}.failUi { }.failUi {
Utils.showErrorMessage(context, R.string.action_getting_user_lists, it, false) Utils.showErrorMessage(context, R.string.action_getting_user_lists, it, false)
@ -1594,14 +1595,15 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
dialog.setOnShowListener { dialog.setOnShowListener {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener { dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
val checkedPositions = dialog.listView.checkedItemPositions val checkedPositions = dialog.listView.checkedItemPositions
val weakActivity = WeakReference(activity)
promiseOnUi { promiseOnUi {
val activity = activity as IExtendedActivity val activity = weakActivity.get() as? IExtendedActivity<*> ?: return@promiseOnUi
activity.executeAfterFragmentResumed { activity.executeAfterFragmentResumed { activity ->
ProgressDialogFragment.show(fragmentManager, "update_lists_progress") ProgressDialogFragment.show(activity.supportFragmentManager, "update_lists_progress")
} }
}.then { }.then {
val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) val activity = weakActivity.get() ?: throw IllegalStateException()
val twitter = MicroBlogAPIFactory.getInstance(activity, accountKey)
val successfulStates = SparseBooleanArray() val successfulStates = SparseBooleanArray()
try { try {
for (i in 0 until checkedPositions.size()) { for (i in 0 until checkedPositions.size()) {
@ -1620,9 +1622,10 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
throw UpdateListsException(successfulStates) throw UpdateListsException(successfulStates)
} }
}.alwaysUi { }.alwaysUi {
val activity = activity as IExtendedActivity val activity = weakActivity.get() as? IExtendedActivity<*> ?: return@alwaysUi
activity.executeAfterFragmentResumed { activity.executeAfterFragmentResumed { activity ->
val df = fragmentManager.findFragmentByTag("update_lists_progress") as? DialogFragment val manager = activity.supportFragmentManager
val df = manager.findFragmentByTag("update_lists_progress") as? DialogFragment
df?.dismiss() df?.dismiss()
} }
}.successUi { }.successUi {

View File

@ -27,7 +27,7 @@ import android.support.v4.app.Fragment
import org.mariotaku.twidere.constant.IntentConstants import org.mariotaku.twidere.constant.IntentConstants
import java.util.* import java.util.*
interface IBaseFragment { interface IBaseFragment<out F : Fragment> {
val extraConfiguration: Bundle? val extraConfiguration: Bundle?
get() = null get() = null
@ -64,18 +64,14 @@ interface IBaseFragment {
fun getSystemWindowsInsets(insets: Rect): Boolean fun getSystemWindowsInsets(insets: Rect): Boolean
} }
fun executeAfterFragmentResumed(useHandler: Boolean = false, action: (IBaseFragment) -> Unit) fun executeAfterFragmentResumed(useHandler: Boolean = false, action: (F) -> Unit)
class ActionHelper(private val fragment: IBaseFragment) { class ActionHelper<out F : Fragment>(private val fragment: F) {
private val handler: Handler private val handler: Handler = Handler(Looper.getMainLooper())
init {
handler = Handler(Looper.getMainLooper())
}
private var fragmentResumed: Boolean = false private var fragmentResumed: Boolean = false
private val actionQueue = LinkedList<ExecuteInfo>() private val actionQueue = LinkedList<ExecuteInfo<F>>()
fun dispatchOnPause() { fun dispatchOnPause() {
fragmentResumed = false fragmentResumed = false
@ -86,10 +82,9 @@ interface IBaseFragment {
executePending() executePending()
} }
private fun executePending() { private fun executePending() {
if (!fragmentResumed) return if (!fragmentResumed) return
var info: ExecuteInfo var info: ExecuteInfo<F>
while (true) { while (true) {
info = actionQueue.poll() ?: break info = actionQueue.poll() ?: break
if (info.useHandler) { if (info.useHandler) {
@ -100,11 +95,11 @@ interface IBaseFragment {
} }
} }
fun executeAfterFragmentResumed(useHandler: Boolean = false, action: (IBaseFragment) -> Unit) { fun executeAfterFragmentResumed(useHandler: Boolean = false, action: (F) -> Unit) {
actionQueue.add(ExecuteInfo(action, useHandler)) actionQueue.add(ExecuteInfo(action, useHandler))
executePending() executePending()
} }
private data class ExecuteInfo(val action: (IBaseFragment) -> Unit, val useHandler: Boolean) private data class ExecuteInfo<in F : Fragment>(val action: (F) -> Unit, val useHandler: Boolean)
} }
} }

View File

@ -22,7 +22,6 @@ package org.mariotaku.twidere.task
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.support.v4.app.DialogFragment import android.support.v4.app.DialogFragment
import android.support.v4.app.FragmentActivity
import org.mariotaku.twidere.activity.iface.IExtendedActivity import org.mariotaku.twidere.activity.iface.IExtendedActivity
import org.mariotaku.twidere.fragment.ProgressDialogFragment import org.mariotaku.twidere.fragment.ProgressDialogFragment
import java.io.File import java.io.File
@ -38,16 +37,16 @@ abstract class ProgressSaveFileTask(
) : SaveFileTask(context, source, destination, getMimeType) { ) : SaveFileTask(context, source, destination, getMimeType) {
override fun showProgress() { override fun showProgress() {
(context as IExtendedActivity).executeAfterFragmentResumed { activity -> (context as IExtendedActivity<*>).executeAfterFragmentResumed { activity ->
val fragment = ProgressDialogFragment() val fragment = ProgressDialogFragment()
fragment.isCancelable = false fragment.isCancelable = false
fragment.show((activity as FragmentActivity).supportFragmentManager, PROGRESS_FRAGMENT_TAG) fragment.show(activity.supportFragmentManager, PROGRESS_FRAGMENT_TAG)
} }
} }
override fun dismissProgress() { override fun dismissProgress() {
(context as IExtendedActivity).executeAfterFragmentResumed { activity -> (context as IExtendedActivity<*>).executeAfterFragmentResumed { activity ->
val fm = (activity as FragmentActivity).supportFragmentManager val fm = activity.supportFragmentManager
val fragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG) as? DialogFragment val fragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG) as? DialogFragment
fragment?.dismiss() fragment?.dismiss()
} }