Browse Source

Fixed bug with WebView onResume, improved Observable, fixed some other stuff

master
Anthony Restaino 9 years ago
parent
commit
d80e7e2edc
  1. 25
      app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
  2. 38
      app/src/main/java/acr/browser/lightning/activity/TabsManager.java
  3. 7
      app/src/main/java/acr/browser/lightning/app/BrowserApp.java
  4. 10
      app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java
  5. 22
      app/src/main/java/acr/browser/lightning/react/Observable.java
  6. 21
      app/src/main/java/acr/browser/lightning/view/LightningView.java

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

@ -186,6 +186,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private String mUntitledTitle; private String mUntitledTitle;
private String mCameraPhotoPath; private String mCameraPhotoPath;
private final Handler mDrawerHandler = new Handler();
// The singleton BookmarkManager // The singleton BookmarkManager
@Inject BookmarkManager mBookmarkManager; @Inject BookmarkManager mBookmarkManager;
@ -923,7 +925,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
// Use a delayed handler to make the transition smooth // Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code // otherwise it will get caught up with the showTab code
// and cause a janky motion // and cause a janky motion
new Handler().postDelayed(new Runnable() { mDrawerHandler.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
mDrawerLayout.closeDrawers(); mDrawerLayout.closeDrawers();
@ -959,14 +961,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
// Use a delayed handler to make the transition smooth // Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code // otherwise it will get caught up with the showTab code
// and cause a janky motion // and cause a janky motion
new Handler().postDelayed(new Runnable() { mDrawerHandler.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
mDrawerLayout.closeDrawers(); mDrawerLayout.closeDrawers();
} }
}, 200); }, 200);
// new Handler().postDelayed(new Runnable() { // mDrawerHandler.postDelayed(new Runnable() {
// @Override // @Override
// public void run() { // public void run() {
// Remove browser frame background to reduce overdraw // Remove browser frame background to reduce overdraw
@ -1168,16 +1170,12 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
final LightningView currentTab = mTabsManager.getCurrentTab();
Log.d(TAG, "onPause"); Log.d(TAG, "onPause");
if (currentTab != null) { mTabsManager.pauseAll();
currentTab.pauseTimers();
currentTab.onPause();
}
try { try {
BrowserApp.get(this).unregisterReceiver(mNetworkReceiver); BrowserApp.get(this).unregisterReceiver(mNetworkReceiver);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); Log.e(TAG, "Receiver was not registered", e);
} }
if (isIncognito() && isFinishing()) { if (isIncognito() && isFinishing()) {
overridePendingTransition(R.anim.fade_in_scale, R.anim.slide_down_out); overridePendingTransition(R.anim.fade_in_scale, R.anim.slide_down_out);
@ -1227,16 +1225,12 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
final LightningView currentTab = mTabsManager.getCurrentTab();
Log.d(TAG, "onResume"); Log.d(TAG, "onResume");
if (mSuggestionsAdapter != null) { if (mSuggestionsAdapter != null) {
mSuggestionsAdapter.refreshPreferences(); mSuggestionsAdapter.refreshPreferences();
mSuggestionsAdapter.refreshBookmarks(); mSuggestionsAdapter.refreshBookmarks();
} }
if (currentTab != null) { mTabsManager.resumeAll();
currentTab.resumeTimers();
currentTab.onResume();
}
initializePreferences(); initializePreferences();
mTabsManager.resume(this); mTabsManager.resume(this);
@ -2157,8 +2151,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
mPresenter.loadUrlInCurrentView(event.url); mPresenter.loadUrlInCurrentView(event.url);
// keep any jank from happening when the drawer is closed after the // keep any jank from happening when the drawer is closed after the
// URL starts to load // URL starts to load
final Handler handler = new Handler(); mDrawerHandler.postDelayed(new Runnable() {
handler.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
mDrawerLayout.closeDrawer(mDrawerRight); mDrawerLayout.closeDrawer(mDrawerRight);

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

@ -190,6 +190,44 @@ public class TabsManager {
}); });
} }
/**
* Method used to resume all the tabs in the browser.
* This is necessary because we cannot pause the
* WebView when the app is open currently due to a
* bug in the WebView, where calling onResume doesn't
* consistently resume it.
*/
public void resumeAll() {
LightningView current = getCurrentTab();
if (current != null) {
current.resumeTimers();
}
for (LightningView tab : mTabList) {
if (tab != null) {
tab.onResume();
}
}
}
/**
* Method used to pause all the tabs in the browser.
* This is necessary because we cannot pause the
* WebView when the app is open currently due to a
* bug in the WebView, where calling onResume doesn't
* consistently resume it.
*/
public void pauseAll() {
LightningView current = getCurrentTab();
if (current != null) {
current.pauseTimers();
}
for (LightningView tab : mTabList) {
if (tab != null) {
tab.onPause();
}
}
}
/** /**
* Return the tab at the given position in tabs list, or * Return the tab at the given position in tabs list, or
* null if position is not in tabs list range. * null if position is not in tabs list range.

7
app/src/main/java/acr/browser/lightning/app/BrowserApp.java

@ -2,7 +2,9 @@ package acr.browser.lightning.app;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.webkit.WebView;
import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.LeakCanary;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
@ -12,6 +14,8 @@ import java.util.concurrent.Executors;
import javax.inject.Inject; import javax.inject.Inject;
import acr.browser.lightning.BuildConfig;
public class BrowserApp extends Application { public class BrowserApp extends Application {
private static AppComponent mAppComponent; private static AppComponent mAppComponent;
@ -26,6 +30,9 @@ public class BrowserApp extends Application {
mAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build(); mAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
mAppComponent.inject(this); mAppComponent.inject(this);
LeakCanary.install(this); LeakCanary.install(this);
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
} }
@NonNull @NonNull

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

@ -100,12 +100,16 @@ public class BrowserPresenter {
} }
} else { } else {
if (mCurrentTab != null) { if (mCurrentTab != null) {
mCurrentTab.onPause(); // TODO: Restore this when Google fixes the bug where the WebView is
// blank after calling onPause followed by onResume.
// mCurrentTab.onPause();
mCurrentTab.setForegroundTab(false); mCurrentTab.setForegroundTab(false);
} }
newTab.onResume();
newTab.resumeTimers(); newTab.resumeTimers();
newTab.onResume();
newTab.setForegroundTab(true); newTab.setForegroundTab(true);
mView.updateProgress(newTab.getProgress()); mView.updateProgress(newTab.getProgress());
mView.setBackButtonEnabled(newTab.canGoBack()); mView.setBackButtonEnabled(newTab.canGoBack());
mView.setForwardButtonEnabled(newTab.canGoForward()); mView.setForwardButtonEnabled(newTab.canGoForward());
@ -143,6 +147,7 @@ public class BrowserPresenter {
* delete the tab. * delete the tab.
*/ */
public void deleteTab(int position) { public void deleteTab(int position) {
Log.d(TAG, "delete Tab");
final LightningView tabToDelete = mTabsModel.getTabAtPosition(position); final LightningView tabToDelete = mTabsModel.getTabAtPosition(position);
if (tabToDelete == null) { if (tabToDelete == null) {
@ -280,6 +285,7 @@ public class BrowserPresenter {
* tab to switch to. * tab to switch to.
*/ */
public synchronized void tabChanged(int position) { public synchronized void tabChanged(int position) {
Log.d(TAG, "tabChanged: " + position);
if (position < 0 || position >= mTabsModel.size()) { if (position < 0 || position >= mTabsModel.size()) {
return; return;
} }

22
app/src/main/java/acr/browser/lightning/react/Observable.java

@ -143,7 +143,7 @@ public class Observable<T> {
private static class SubscriberImpl<T> implements Subscriber<T> { private static class SubscriberImpl<T> implements Subscriber<T> {
@Nullable private OnSubscribe<T> mOnSubscribe; @Nullable private volatile OnSubscribe<T> mOnSubscribe;
@NonNull private final Observable<T> mObservable; @NonNull private final Observable<T> mObservable;
private boolean mOnCompleteExecuted = false; private boolean mOnCompleteExecuted = false;
@ -159,9 +159,10 @@ public class Observable<T> {
@Override @Override
public void onComplete() { public void onComplete() {
if (!mOnCompleteExecuted && mOnSubscribe != null) { OnSubscribe<T> onSubscribe = mOnSubscribe;
if (!mOnCompleteExecuted && onSubscribe != null) {
mOnCompleteExecuted = true; mOnCompleteExecuted = true;
mObservable.executeOnObserverThread(new OnCompleteRunnable<>(mOnSubscribe)); mObservable.executeOnObserverThread(new OnCompleteRunnable<>(onSubscribe));
} else { } else {
Log.e(TAG, "onComplete called more than once"); Log.e(TAG, "onComplete called more than once");
throw new RuntimeException("onComplete called more than once"); throw new RuntimeException("onComplete called more than once");
@ -170,23 +171,26 @@ public class Observable<T> {
@Override @Override
public void onStart() { public void onStart() {
if (mOnSubscribe != null) { OnSubscribe<T> onSubscribe = mOnSubscribe;
mObservable.executeOnObserverThread(new OnStartRunnable<>(mOnSubscribe)); if (onSubscribe != null) {
mObservable.executeOnObserverThread(new OnStartRunnable<>(onSubscribe));
} }
} }
@Override @Override
public void onError(@NonNull final Throwable throwable) { public void onError(@NonNull final Throwable throwable) {
if (mOnSubscribe != null) { OnSubscribe<T> onSubscribe = mOnSubscribe;
if (onSubscribe != null) {
mOnCompleteExecuted = true; mOnCompleteExecuted = true;
mObservable.executeOnObserverThread(new OnErrorRunnable<>(mOnSubscribe, throwable)); mObservable.executeOnObserverThread(new OnErrorRunnable<>(onSubscribe, throwable));
} }
} }
@Override @Override
public void onNext(final T item) { public void onNext(final T item) {
if (!mOnCompleteExecuted && mOnSubscribe != null) { OnSubscribe<T> onSubscribe = mOnSubscribe;
mObservable.executeOnObserverThread(new OnNextRunnable<>(mOnSubscribe, item)); if (!mOnCompleteExecuted && onSubscribe != null) {
mObservable.executeOnObserverThread(new OnNextRunnable<>(onSubscribe, item));
} else { } else {
Log.e(TAG, "onComplete has been already called, onNext should not be called"); Log.e(TAG, "onComplete has been already called, onNext should not be called");
throw new RuntimeException("onNext should not be called after onComplete has been called"); throw new RuntimeException("onNext should not be called after onComplete has been called");

21
app/src/main/java/acr/browser/lightning/view/LightningView.java

@ -77,7 +77,7 @@ public class LightningView {
private static String sHomepage; private static String sHomepage;
private static String sDefaultUserAgent; private static String sDefaultUserAgent;
private static float mMaxFling; private static float sMaxFling;
private static final float[] sNegativeColorArray = { private static final float[] sNegativeColorArray = {
-1.0f, 0, 0, 0, 255, // red -1.0f, 0, 0, 0, 255, // red
0, -1.0f, 0, 0, 255, // green 0, -1.0f, 0, 0, 255, // green
@ -116,10 +116,13 @@ public class LightningView {
mActivity = activity; mActivity = activity;
mUIController = (UIController) activity; mUIController = (UIController) activity;
mWebView = new WebView(activity); mWebView = new WebView(activity);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
mWebView.setId(View.generateViewId());
}
mIsIncognitoTab = isIncognito; mIsIncognitoTab = isIncognito;
mTitle = new LightningViewTitle(activity); mTitle = new LightningViewTitle(activity);
mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity(); sMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity();
mWebView.setDrawingCacheBackgroundColor(Color.WHITE); mWebView.setDrawingCacheBackgroundColor(Color.WHITE);
mWebView.setFocusableInTouchMode(true); mWebView.setFocusableInTouchMode(true);
@ -560,16 +563,20 @@ public class LightningView {
* Pause the current WebView instance. * Pause the current WebView instance.
*/ */
public synchronized void onPause() { public synchronized void onPause() {
if (mWebView != null) if (mWebView != null) {
mWebView.onPause(); mWebView.onPause();
Log.d(TAG, "WebView onPause: " + mWebView.getId());
}
} }
/** /**
* Resume the current WebView instance. * Resume the current WebView instance.
*/ */
public synchronized void onResume() { public synchronized void onResume() {
if (mWebView != null) if (mWebView != null) {
mWebView.onResume(); mWebView.onResume();
Log.d(TAG, "WebView onResume: " + mWebView.getId());
}
} }
/** /**
@ -737,17 +744,19 @@ public class LightningView {
public synchronized void pauseTimers() { public synchronized void pauseTimers() {
if (mWebView != null) { if (mWebView != null) {
mWebView.pauseTimers(); mWebView.pauseTimers();
Log.d(TAG, "Pausing JS timers");
} }
} }
/** /**
* Resumes the JavaScript timers of the * Resumes the JavaScript timers of the
* WebView instance, whihc will trigger a * WebView instance, which will trigger a
* resume for all WebViews in the app. * resume for all WebViews in the app.
*/ */
public synchronized void resumeTimers() { public synchronized void resumeTimers() {
if (mWebView != null) { if (mWebView != null) {
mWebView.resumeTimers(); mWebView.resumeTimers();
Log.d(TAG, "Resuming JS timers");
} }
} }
@ -1122,7 +1131,7 @@ public class LightningView {
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int power = (int) (velocityY * 100 / mMaxFling); int power = (int) (velocityY * 100 / sMaxFling);
if (power < -10) { if (power < -10) {
mUIController.hideActionBar(); mUIController.hideActionBar();
} else if (power > 15) { } else if (power > 15) {

Loading…
Cancel
Save