Browse Source

Initial slow move toward MVP pattern

master
Anthony Restaino 9 years ago
parent
commit
65c2c9c461
  1. 131
      app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
  2. 41
      app/src/main/java/acr/browser/lightning/activity/TabsManager.java
  3. 3
      app/src/main/java/acr/browser/lightning/app/AppComponent.java
  4. 84
      app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java
  5. 16
      app/src/main/java/acr/browser/lightning/browser/BrowserView.java
  6. 1
      app/src/main/java/acr/browser/lightning/utils/ThemeUtils.java
  7. 3
      app/src/main/java/acr/browser/lightning/utils/UrlUtils.java

131
app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java

@ -90,6 +90,8 @@ import javax.inject.Inject; @@ -90,6 +90,8 @@ import javax.inject.Inject;
import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.browser.BrowserPresenter;
import acr.browser.lightning.browser.BrowserView;
import acr.browser.lightning.bus.BookmarkEvents;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.bus.NavigationEvents;
@ -119,7 +121,7 @@ import acr.browser.lightning.view.LightningView; @@ -119,7 +121,7 @@ import acr.browser.lightning.view.LightningView;
import butterknife.Bind;
import butterknife.ButterKnife;
public abstract class BrowserActivity extends ThemableBrowserActivity implements UIController, OnClickListener, OnLongClickListener {
public abstract class BrowserActivity extends ThemableBrowserActivity implements BrowserView, UIController, OnClickListener, OnLongClickListener {
// Static Layout
@Bind(R.id.drawer_layout)
@ -195,6 +197,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -195,6 +197,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private Drawable mDeleteIcon, mRefreshIcon, mClearIcon, mIcon;
private DrawerArrowDrawable mArrowDrawable;
private BrowserPresenter mPresenter;
// Proxy
@Inject ProxyUtils mProxyUtils;
@ -221,6 +225,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -221,6 +225,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
BrowserApp.getAppComponent().inject(this);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mPresenter = new BrowserPresenter(this);
initialize();
}
@ -828,6 +835,102 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -828,6 +835,102 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
builder.show();
}
private View mCurrentView;
@Override
public void removeTabView() {
// Set the background color so the color mode color doesn't show through
mBrowserFrame.setBackgroundColor(mBackgroundColor);
mIsNewIntent = false;
mBrowserFrame.removeAllViews();
removeViewFromParent(mCurrentView);
if (mFullScreen) {
// mToolbarLayout has already been removed
mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront();
mToolbarLayout.setTranslationY(0);
}
mCurrentView = null;
// Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code
// and cause a janky motion
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawers();
}
}, 200);
}
@Override
public void setTabView(@NonNull View view) {
if (mCurrentView == view) {
return;
}
// Set the background color so the color mode color doesn't show through
mBrowserFrame.setBackgroundColor(mBackgroundColor);
mIsNewIntent = false;
final float translation = mToolbarLayout.getTranslationY();
mBrowserFrame.removeAllViews();
removeViewFromParent(view);
removeViewFromParent(mCurrentView);
mBrowserFrame.addView(view, MATCH_PARENT);
view.requestFocus();
if (mFullScreen) {
// mToolbarLayout has already been removed
mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront();
Log.d(Constants.TAG, "Move view to browser frame");
int height = mToolbarLayout.getHeight();
if (height == 0) {
mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
height = mToolbarLayout.getMeasuredHeight();
}
view.setTranslationY(translation + height);
mToolbarLayout.setTranslationY(translation);
} else {
view.setTranslationY(0);
}
mCurrentView = view;
showActionBar();
// Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code
// and cause a janky motion
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawers();
}
}, 200);
// new Handler().postDelayed(new Runnable() {
// @Override
// public void run() {
// Remove browser frame background to reduce overdraw
//TODO evaluate performance
// mBrowserFrame.setBackgroundColor(Color.TRANSPARENT);
// }
// }, 300);
}
/**
* displays the WebView contained in the LightningView Also handles the
* removal of previous views
@ -837,11 +940,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -837,11 +940,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private synchronized void showTab(final int position) {
final LightningView currentView = mTabsManager.getCurrentTab();
final LightningView newView = mTabsManager.switchToTab(position);
switchTabs(currentView, newView);
//TODO move this code elsewhere
// switchTabs(currentView, newView);
}
// This is commodity to breack the flow between regular tab management and the CLIQZ's search
// interface.
// TODO remove all usages, switch to using the presenter instead
@Deprecated
private void switchTabs(final LightningView currentView, final LightningView newView) {
final WebView newWebView = newView != null ? newView.getWebView() : null;
if (newView == null || newWebView == null) {
@ -912,7 +1018,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -912,7 +1018,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
}
private static void removeViewFromParent(View view) {
private static void removeViewFromParent(@Nullable View view) {
if (view == null) {
return;
}
ViewGroup parent = ((ViewGroup) view.getParent());
if (parent != null) {
parent.removeView(view);
@ -988,6 +1097,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -988,6 +1097,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
}
}
// TODO move to presenter
private synchronized boolean newTab(String url, boolean show) {
// Limit number of tabs for limited version of app
if (!Constants.FULL_VERSION && mTabsManager.size() >= 10) {
@ -1018,6 +1128,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -1018,6 +1128,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
return true;
}
// TODO move this to presenter
private synchronized void deleteTab(int position) {
final LightningView tabToDelete = mTabsManager.getTabAtPosition(position);
@ -1050,10 +1161,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -1050,10 +1161,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
closeBrowser();
return;
} else if (afterTab != currentTab) {
switchTabs(currentTab, afterTab);
if (currentTab != null) {
currentTab.pauseTimers();
}
//TODO remove this?
// switchTabs(currentTab, afterTab);
// if (currentTab != null) {
// currentTab.pauseTimers();
// }
}
mEventBus.post(new BrowserEvents.TabsChanged());
@ -1177,6 +1289,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @@ -1177,6 +1289,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
@Override
protected void onDestroy() {
Log.d(Constants.TAG, "onDestroy");
if (mPresenter != null) {
mPresenter.destroy();
}
if (mHistoryDatabase != null) {
mHistoryDatabase.close();
mHistoryDatabase = null;

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

@ -45,9 +45,28 @@ public class TabsManager { @@ -45,9 +45,28 @@ public class TabsManager {
@Inject Bus mEventBus;
@Inject Application mApp;
@Nullable private TabChangeListener mListener;
public interface TabChangeListener {
void tabChanged(LightningView newTab);
}
@Inject
public TabsManager() {}
/**
* Sets the {@link TabChangeListener} to a new
* listener. Can be set to null if the caller
* wishes to unregister the listener.
*
* @param listener the new listener to use or
* null if the caller wishes to
* unregister the listener.
*/
public void setTabChangeListener(@Nullable TabChangeListener listener) {
mListener = listener;
}
/**
* Restores old tabs that were open before the browser
* was closed. Handles the intent used to open the browser.
@ -137,6 +156,7 @@ public class TabsManager { @@ -137,6 +156,7 @@ public class TabsManager {
* released for garbage collection.
*/
public synchronized void shutdown() {
sendTabChangedEvent(null);
for (LightningView tab : mTabList) {
tab.onDestroy();
}
@ -195,6 +215,7 @@ public class TabsManager { @@ -195,6 +215,7 @@ public class TabsManager {
public synchronized LightningView newTab(@NonNull final Activity activity,
@Nullable final String url,
final boolean isIncognito) {
Log.d(TAG, "New tab");
final LightningView tab = new LightningView(activity, url, isIncognito);
mTabList.add(tab);
return tab;
@ -227,6 +248,7 @@ public class TabsManager { @@ -227,6 +248,7 @@ public class TabsManager {
* @param position the position of the tab to delete.
*/
public synchronized void deleteTab(int position) {
Log.d(TAG, "Delete tab: " + position);
final LightningView currentTab = getCurrentTab();
int current = positionOf(currentTab);
@ -239,6 +261,7 @@ public class TabsManager { @@ -239,6 +261,7 @@ public class TabsManager {
} else {
mCurrentTab = getTabAtPosition(current - 1);
}
sendTabChangedEvent(mCurrentTab);
removeTab(current);
} else {
removeTab(position);
@ -330,16 +353,34 @@ public class TabsManager { @@ -330,16 +353,34 @@ public class TabsManager {
*/
@Nullable
public synchronized LightningView switchToTab(final int position) {
Log.d(TAG, "switch to tab: " + position);
if (position < 0 || position >= mTabList.size()) {
Log.e(TAG, "Returning a null LightningView requested for position: " + position);
sendTabChangedEvent(null);
return null;
} else {
final LightningView tab = mTabList.get(position);
if (tab != null) {
mCurrentTab = tab;
}
sendTabChangedEvent(tab);
return tab;
}
}
/**
* Send the event that the current tab has changed to
* a new tab to the {@link TabChangeListener} if it is
* not null.
*
* @param newView the new tab that we have switcted to,
* can be null if the last tab has been
* deleted.
*/
private void sendTabChangedEvent(@Nullable LightningView newView) {
if (mListener != null) {
mListener.tabChanged(newView);
}
}
}

3
app/src/main/java/acr/browser/lightning/app/AppComponent.java

@ -6,6 +6,7 @@ import acr.browser.lightning.activity.BrowserActivity; @@ -6,6 +6,7 @@ import acr.browser.lightning.activity.BrowserActivity;
import acr.browser.lightning.activity.ReadingActivity;
import acr.browser.lightning.activity.ThemableBrowserActivity;
import acr.browser.lightning.activity.ThemableSettingsActivity;
import acr.browser.lightning.browser.BrowserPresenter;
import acr.browser.lightning.constant.StartPage;
import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.download.LightningDownloadListener;
@ -61,4 +62,6 @@ public interface AppComponent { @@ -61,4 +62,6 @@ public interface AppComponent {
void inject(StartPage startPage);
void inject(BrowserPresenter presenter);
}

84
app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
package acr.browser.lightning.browser;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import javax.inject.Inject;
import acr.browser.lightning.activity.TabsManager;
import acr.browser.lightning.activity.TabsManager.TabChangeListener;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.view.LightningView;
/**
* Presenter in charge of keeping track of
* the current tab and setting the current tab
* of the
*/
public class BrowserPresenter {
private static final String TAG = BrowserPresenter.class.getSimpleName();
@Inject TabsManager mTabsModel;
@NonNull private BrowserView mView;
@Nullable private LightningView mCurrentTab;
private static class TabListener implements TabChangeListener {
private BrowserPresenter mPresenter;
public TabListener(@NonNull BrowserPresenter presenter) {
mPresenter = presenter;
}
@Override
public void tabChanged(@Nullable LightningView newTab) {
mPresenter.onTabChanged(newTab);
}
}
public BrowserPresenter(@NonNull BrowserView view) {
BrowserApp.getAppComponent().inject(this);
mView = view;
mTabsModel.setTabChangeListener(new TabListener(this));
}
private void onTabChanged(@Nullable LightningView newTab) {
Log.d(TAG, "On tab changed");
if (newTab == null) {
mView.removeTabView();
if (mCurrentTab != null) {
mCurrentTab.pauseTimers();
mCurrentTab.onDestroy();
}
} else {
if (newTab.getWebView() == null) {
mView.removeTabView();
if (mCurrentTab != null) {
mCurrentTab.pauseTimers();
mCurrentTab.onDestroy();
}
} else {
if (mCurrentTab != null) {
mCurrentTab.onPause();
mCurrentTab.setForegroundTab(false);
}
newTab.onResume();
newTab.resumeTimers();
newTab.setForegroundTab(true);
mView.updateProgress(newTab.getProgress());
mView.updateUrl(newTab.getUrl(), true);
mView.setTabView(newTab.getWebView());
}
}
mCurrentTab = newTab;
}
public void destroy() {
mTabsModel.setTabChangeListener(null);
}
}

16
app/src/main/java/acr/browser/lightning/browser/BrowserView.java

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
package acr.browser.lightning.browser;
import android.support.annotation.NonNull;
import android.view.View;
public interface BrowserView {
void setTabView(@NonNull View view);
void removeTabView();
void updateUrl(String url, boolean shortUrl);
void updateProgress(int progress);
}

1
app/src/main/java/acr/browser/lightning/utils/ThemeUtils.java

@ -15,7 +15,6 @@ import android.support.annotation.AttrRes; @@ -15,7 +15,6 @@ import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.TypedValue;
import android.widget.ImageView;

3
app/src/main/java/acr/browser/lightning/utils/UrlUtils.java

@ -82,6 +82,7 @@ public class UrlUtils { @@ -82,6 +82,7 @@ public class UrlUtils {
* URL. If false, invalid URLs will return null
* @return Original or modified URL
*/
@NonNull
public static String smartUrlFilter(@NonNull String url, boolean canBeSearch, String searchUrl) {
String inUrl = url.trim();
boolean hasSpace = inUrl.indexOf(' ') != -1;
@ -107,7 +108,7 @@ public class UrlUtils { @@ -107,7 +108,7 @@ public class UrlUtils {
return URLUtil.composeSearchUrl(inUrl,
searchUrl, QUERY_PLACE_HOLDER);
}
return null;
return "";
}
/* package */

Loading…
Cancel
Save