Browse Source

Documentation, cleanup of TabsManager

master
Anthony Restaino 9 years ago
parent
commit
425392456c
  1. 154
      app/src/main/java/acr/browser/lightning/activity/TabsManager.java

154
app/src/main/java/acr/browser/lightning/activity/TabsManager.java

@ -6,6 +6,7 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
@ -26,14 +27,15 @@ import acr.browser.lightning.utils.FileUtils;
import acr.browser.lightning.view.LightningView; import acr.browser.lightning.view.LightningView;
/** /**
* @author Stefano Pacifici * A manager singleton that holds all the {@link LightningView}
* @date 2015/09/14 * and tracks the current tab. It handles creation, deletion,
* restoration, state saving, and switching of tabs.
*/ */
@Singleton @Singleton
public class TabsManager { public class TabsManager {
private static final String TAG = TabsManager.class.getSimpleName(); private static final String TAG = TabsManager.class.getSimpleName();
private final List<LightningView> mWebViewList = new ArrayList<>(); private final List<LightningView> mTabList = new ArrayList<>(1);
private LightningView mCurrentTab; private LightningView mCurrentTab;
private static final String BUNDLE_KEY = "WEBVIEW_"; private static final String BUNDLE_KEY = "WEBVIEW_";
private static final String BUNDLE_STORAGE = "SAVED_TABS.parcel"; private static final String BUNDLE_STORAGE = "SAVED_TABS.parcel";
@ -53,12 +55,12 @@ public class TabsManager {
* @param intent the intent that started the browser activity. * @param intent the intent that started the browser activity.
* @param incognito whether or not we are in incognito mode. * @param incognito whether or not we are in incognito mode.
*/ */
public synchronized void restoreTabsAndHandleIntent(final Activity activity, public synchronized void restoreTabsAndHandleIntent(@NonNull final Activity activity,
final Intent intent, @Nullable final Intent intent,
final boolean incognito) { final boolean incognito) {
// If incognito, only create one tab, do not handle intent // If incognito, only create one tab, do not handle intent
// in order to protect user privacy // in order to protect user privacy
if (incognito && mWebViewList.isEmpty()) { if (incognito && mTabList.isEmpty()) {
newTab(activity, null, true); newTab(activity, null, true);
return; return;
} }
@ -67,7 +69,7 @@ public class TabsManager {
if (intent != null) { if (intent != null) {
url = intent.getDataString(); url = intent.getDataString();
} }
mWebViewList.clear(); mTabList.clear();
mCurrentTab = null; mCurrentTab = null;
if (mPreferenceManager.getRestoreLostTabsEnabled()) { if (mPreferenceManager.getRestoreLostTabsEnabled()) {
restoreState(activity); restoreState(activity);
@ -91,65 +93,76 @@ public class TabsManager {
newTab(activity, url, false); newTab(activity, url, false);
} }
} }
if (mWebViewList.size() == 0) { if (mTabList.size() == 0) {
newTab(activity, null, false); newTab(activity, null, false);
} }
} }
/** /**
* Return the tab at the given position in tabs list, or null if position is not in tabs list * Return the tab at the given position in tabs list, or
* range. * null if position is not in tabs list range.
* *
* @param position the index in tabs list * @param position the index in tabs list
* @return the corespondent {@link LightningView}, or null if the index is invalid * @return the corespondent {@link LightningView},
* or null if the index is invalid
*/ */
@Nullable @Nullable
public synchronized LightningView getTabAtPosition(final int position) { public synchronized LightningView getTabAtPosition(final int position) {
if (position < 0 || position >= mWebViewList.size()) { if (position < 0 || position >= mTabList.size()) {
return null; return null;
} }
return mWebViewList.get(position); return mTabList.get(position);
} }
/** /**
* Try to low memory pressure * Frees memory for each tab in the
* manager. Note: this will only work
* on API < KITKAT as on KITKAT onward
* the WebViews manage their own
* memory correctly.
*/ */
public synchronized void freeMemory() { public synchronized void freeMemory() {
for (LightningView tab : mWebViewList) { for (LightningView tab : mTabList) {
tab.freeMemory(); tab.freeMemory();
} }
} }
/** /**
* Shutdown the manager * Shutdown the manager. This destroys
* all tabs and clears the references
* to those tabs. Current tab is also
* released for garbage collection.
*/ */
public synchronized void shutdown() { public synchronized void shutdown() {
for (LightningView tab : mWebViewList) { for (LightningView tab : mTabList) {
tab.onDestroy(); tab.onDestroy();
} }
mWebViewList.clear(); mTabList.clear();
mCurrentTab = null; mCurrentTab = null;
} }
/** /**
* Resume the tabs * Reinitializes the preferences for
* all the tabs in the list.
* *
* @param context * @param context the context needed
* to initialize the preferences.
*/ */
public synchronized void resume(final Context context) { public synchronized void resume(@NonNull final Context context) {
for (LightningView tab : mWebViewList) { for (LightningView tab : mTabList) {
tab.initializePreferences(context); tab.initializePreferences(context);
} }
} }
/** /**
* Forward network connection status to the webviews. * Forwards network connection status to the WebViews.
* *
* @param isConnected * @param isConnected whether there is a network
* connection or not.
*/ */
public synchronized void notifyConnectionStatus(final boolean isConnected) { public synchronized void notifyConnectionStatus(final boolean isConnected) {
for (LightningView tab : mWebViewList) { for (LightningView tab : mTabList) {
final WebView webView = tab.getWebView(); final WebView webView = tab.getWebView();
if (webView != null) { if (webView != null) {
webView.setNetworkAvailable(isConnected); webView.setNetworkAvailable(isConnected);
@ -158,38 +171,45 @@ public class TabsManager {
} }
/** /**
* @return The number of currently opened tabs * The current number of tabs in the manager.
*
* @return the number of tabs in the list.
*/ */
public synchronized int size() { public synchronized int size() {
return mWebViewList.size(); return mTabList.size();
} }
/** /**
* Create and return a new tab. The tab is automatically added to the tabs list. * Create and return a new tab. The tab is
* automatically added to the tabs list.
* *
* @param activity * @param activity the activity needed to create the tab.
* @param url * @param url the URL to initialize the tab with.
* @param isIncognito * @param isIncognito whether the tab is an incognito
* @return * tab or not.
* @return a valid initialized tab.
*/ */
public synchronized LightningView newTab(final Activity activity, @NonNull
final String url, public synchronized LightningView newTab(@NonNull final Activity activity,
@Nullable final String url,
final boolean isIncognito) { final boolean isIncognito) {
final LightningView tab = new LightningView(activity, url, isIncognito); final LightningView tab = new LightningView(activity, url, isIncognito);
mWebViewList.add(tab); mTabList.add(tab);
return tab; return tab;
} }
/** /**
* Remove a tab and return its reference or null if the position is not in tabs range * Removes a tab from the list and destroys the tab.
* If the tab removed is the current tab, the reference
* to the current tab will be nullified.
* *
* @param position The position of the tab to remove * @param position The position of the tab to remove.
*/ */
private synchronized void removeTab(final int position) { private synchronized void removeTab(final int position) {
if (position >= mWebViewList.size()) { if (position >= mTabList.size()) {
return; return;
} }
final LightningView tab = mWebViewList.remove(position); final LightningView tab = mTabList.remove(position);
if (mCurrentTab == tab) { if (mCurrentTab == tab) {
mCurrentTab = null; mCurrentTab = null;
} }
@ -197,6 +217,13 @@ public class TabsManager {
Log.d(Constants.TAG, tab.toString()); Log.d(Constants.TAG, tab.toString());
} }
/**
* Deletes a tab from the manager. If the tab
* being deleted is the current tab, this method
* will switch the current tab to a new valid tab.
*
* @param position the position of the tab to delete.
*/
public synchronized void deleteTab(int position) { public synchronized void deleteTab(int position) {
final LightningView currentTab = getCurrentTab(); final LightningView currentTab = getCurrentTab();
int current = positionOf(currentTab); int current = positionOf(currentTab);
@ -219,18 +246,24 @@ public class TabsManager {
/** /**
* Return the position of the given tab. * Return the position of the given tab.
* *
* @param tab the tab to look for * @param tab the tab to look for.
* @return the position of the tab or -1 if the tab is not in the list * @return the position of the tab or -1
* if the tab is not in the list.
*/ */
public synchronized int positionOf(final LightningView tab) { public synchronized int positionOf(final LightningView tab) {
return mWebViewList.indexOf(tab); return mTabList.indexOf(tab);
} }
/**
* Saves the state of the current WebViews,
* to a bundle which is then stored in persistent
* storage and can be unparceled.
*/
public void saveState() { public void saveState() {
Bundle outState = new Bundle(ClassLoader.getSystemClassLoader()); Bundle outState = new Bundle(ClassLoader.getSystemClassLoader());
Log.d(Constants.TAG, "Saving tab state"); Log.d(Constants.TAG, "Saving tab state");
for (int n = 0; n < mWebViewList.size(); n++) { for (int n = 0; n < mTabList.size(); n++) {
LightningView tab = mWebViewList.get(n); LightningView tab = mTabList.get(n);
Bundle state = new Bundle(ClassLoader.getSystemClassLoader()); Bundle state = new Bundle(ClassLoader.getSystemClassLoader());
if (tab.getWebView() != null) { if (tab.getWebView() != null) {
tab.getWebView().saveState(state); tab.getWebView().saveState(state);
@ -240,7 +273,16 @@ public class TabsManager {
FileUtils.writeBundleToStorage(mApp, outState, BUNDLE_STORAGE); FileUtils.writeBundleToStorage(mApp, outState, BUNDLE_STORAGE);
} }
private void restoreState(Activity activity) { /**
* Restores the previously saved tabs from the
* bundle stored in peristent file storage.
* It will create new tabs for each tab saved
* and will delete the saved instance file when
* restoration is complete.
*
* @param activity the Activity needed to create tabs.
*/
private void restoreState(@NonNull Activity activity) {
Bundle savedState = FileUtils.readBundleFromStorage(mApp, BUNDLE_STORAGE); Bundle savedState = FileUtils.readBundleFromStorage(mApp, BUNDLE_STORAGE);
if (savedState != null) { if (savedState != null) {
Log.d(Constants.TAG, "Restoring previous WebView state now"); Log.d(Constants.TAG, "Restoring previous WebView state now");
@ -256,9 +298,10 @@ public class TabsManager {
} }
/** /**
* Return the {@link WebView} associated to the current tab, or null if there is no current tab * Return the {@link WebView} associated to the current tab,
* or null if there is no current tab.
* *
* @return a {@link WebView} or null * @return a {@link WebView} or null if there is no current tab.
*/ */
@Nullable @Nullable
public synchronized WebView getCurrentWebView() { public synchronized WebView getCurrentWebView() {
@ -266,9 +309,11 @@ public class TabsManager {
} }
/** /**
* TODO We should remove also this, but probably not * Return the current {@link LightningView} or null if
* no current tab has been set.
* *
* @return * @return a {@link LightningView} or null if there
* is no current tab.
*/ */
@Nullable @Nullable
public synchronized LightningView getCurrentTab() { public synchronized LightningView getCurrentTab() {
@ -276,19 +321,18 @@ public class TabsManager {
} }
/** /**
* Switch the current tab to the one at the given position. It returns the selected. After this * Switch the current tab to the one at the given position.
* call {@link TabsManager#getCurrentTab()} return the same reference returned by this method if * It returns the selected tab that has been switced to.
* position is valid.
* *
* @return the selected tab or null if position is out of tabs range * @return the selected tab or null if position is out of tabs range.
*/ */
@Nullable @Nullable
public synchronized LightningView switchToTab(final int position) { public synchronized LightningView switchToTab(final int position) {
if (position < 0 || position >= mWebViewList.size()) { if (position < 0 || position >= mTabList.size()) {
Log.e(TAG, "Returning a null LightningView requested for position: " + position); Log.e(TAG, "Returning a null LightningView requested for position: " + position);
return null; return null;
} else { } else {
final LightningView tab = mWebViewList.get(position); final LightningView tab = mTabList.get(position);
if (tab != null) { if (tab != null) {
mCurrentTab = tab; mCurrentTab = tab;
} }

Loading…
Cancel
Save