Bug 931843 - Part 2: rewrite OnFaviconLoadedListeners to hold fewer references. r=bnicholson

This commit is contained in:
Richard Newman 2013-11-04 11:48:58 -08:00
parent dfb7a3475c
commit 55808f7a19
8 changed files with 104 additions and 52 deletions

View File

@ -738,21 +738,22 @@ abstract public class BrowserApp extends GeckoApp
if (itemId == R.id.add_to_launcher) {
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab != null) {
final String url = tab.getURL();
final String title = tab.getDisplayTitle();
if (url == null || title == null) {
return true;
}
Favicons.getFaviconForSize(url, tab.getFaviconURL(), Integer.MAX_VALUE, LoadFaviconTask.FLAG_PERSIST,
new OnFaviconLoadedListener() {
@Override
public void onFaviconLoaded(String pageUrl, String faviconURL, Bitmap favicon) {
GeckoAppShell.createShortcut(title, url, url, favicon, "");
}
});
if (tab == null) {
return true;
}
final String url = tab.getURL();
final String title = tab.getDisplayTitle();
if (url == null || title == null) {
return true;
}
final OnFaviconLoadedListener listener = new GeckoAppShell.CreateShortcutFaviconLoadedListener(url, title);
Favicons.getFaviconForSize(url,
tab.getFaviconURL(),
Integer.MAX_VALUE,
LoadFaviconTask.FLAG_PERSIST,
listener);
return true;
}
@ -1359,35 +1360,24 @@ abstract public class BrowserApp extends GeckoApp
Tabs.getInstance().loadUrl(ABOUT_HOME, Tabs.LOADURL_READING_LIST);
}
/* Favicon methods */
/* Favicon stuff. */
private static OnFaviconLoadedListener sFaviconLoadedListener = new OnFaviconLoadedListener() {
@Override
public void onFaviconLoaded(String pageUrl, String faviconURL, Bitmap favicon) {
// If we failed to load a favicon, we use the default favicon instead.
Tabs.getInstance()
.updateFaviconForURL(pageUrl,
(favicon == null) ? Favicons.sDefaultFavicon : favicon);
}
};
private void loadFavicon(final Tab tab) {
maybeCancelFaviconLoad(tab);
final int tabFaviconSize = getResources().getDimensionPixelSize(R.dimen.browser_toolbar_favicon_size);
int flags = (tab.isPrivate() || tab.getErrorType() != Tab.ErrorType.NONE) ? 0 : LoadFaviconTask.FLAG_PERSIST;
int id = Favicons.getFaviconForSize(tab.getURL(), tab.getFaviconURL(), tabFaviconSize, flags,
new OnFaviconLoadedListener() {
@Override
public void onFaviconLoaded(String pageUrl, String faviconURL, Bitmap favicon) {
// If we failed to load a favicon, we use the default favicon instead.
if (favicon == null) {
favicon = Favicons.sDefaultFavicon;
}
// The tab might be pointing to another URL by the time the
// favicon is finally loaded, in which case we simply ignore it.
// See also: Bug 920331.
if (!tab.getURL().equals(pageUrl)) {
return;
}
tab.updateFavicon(favicon);
tab.setFaviconLoadId(Favicons.NOT_LOADING);
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.FAVICON);
}
});
int id = Favicons.getFaviconForSize(tab.getURL(), tab.getFaviconURL(), tabFaviconSize, flags, sFaviconLoadedListener);
tab.setFaviconLoadId(id);
}

View File

@ -5,6 +5,7 @@
package org.mozilla.gecko;
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.GeckoLayerClient;
import org.mozilla.gecko.gfx.GfxInfoThread;
@ -256,6 +257,21 @@ public class GeckoAppShell
public static native void onFullScreenPluginHidden(View view);
public static class CreateShortcutFaviconLoadedListener implements OnFaviconLoadedListener {
private final String title;
private final String url;
public CreateShortcutFaviconLoadedListener(final String url, final String title) {
this.url = url;
this.title = title;
}
@Override
public void onFaviconLoaded(String pageUrl, String faviconURL, Bitmap favicon) {
GeckoAppShell.createShortcut(title, url, url, favicon, "");
}
}
private static final class GeckoMediaScannerClient implements MediaScannerConnectionClient {
private final String mFile;
private final String mMimeType;

View File

@ -359,8 +359,15 @@ public class Tab {
return mFaviconLoadId;
}
public void updateFavicon(Bitmap favicon) {
/**
* Returns true if the favicon changed.
*/
public boolean updateFavicon(Bitmap favicon) {
if (mFavicon == favicon) {
return false;
}
mFavicon = favicon;
return true;
}
public synchronized void updateFaviconURL(String faviconUrl, int size) {

View File

@ -6,6 +6,7 @@
package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.favicons.Favicons;
import org.mozilla.gecko.home.HomePager;
import org.mozilla.gecko.sync.setup.SyncAccounts;
import org.mozilla.gecko.util.GeckoEventListener;
@ -19,6 +20,7 @@ import android.accounts.OnAccountsUpdateListener;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Handler;
@ -279,6 +281,9 @@ public class Tabs implements GeckoEventListener {
}
public synchronized Tab getTab(int id) {
if (id == -1)
return null;
if (mTabs.size() == 0)
return null;
@ -477,6 +482,24 @@ public class Tabs implements GeckoEventListener {
}
}
/**
* Set the favicon for any tabs loaded with this page URL.
*/
public void updateFaviconForURL(String pageURL, Bitmap favicon) {
// The tab might be pointing to another URL by the time the
// favicon is finally loaded, in which case we won't find the tab.
// See also: Bug 920331.
for (Tab tab : mOrder) {
String tabURL = tab.getURL();
if (pageURL.equals(tabURL)) {
tab.setFaviconLoadId(Favicons.NOT_LOADING);
if (tab.updateFavicon(favicon)) {
notifyListeners(tab, TabEvents.FAVICON);
}
}
}
}
public void refreshThumbnails() {
final ThumbnailHelper helper = ThumbnailHelper.getInstance();
ThreadUtils.postToBackgroundThread(new Runnable() {

View File

@ -7,7 +7,6 @@ package org.mozilla.gecko.home;
import org.mozilla.gecko.EditBookmarkDialog;
import org.mozilla.gecko.favicons.Favicons;
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.GeckoProfile;
@ -133,13 +132,7 @@ abstract class HomeFragment extends Fragment {
}
// Fetch the largest cacheable icon size.
Favicons.getLargestFaviconForPage(info.url, new OnFaviconLoadedListener() {
@Override
public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) {
GeckoAppShell.createShortcut(info.getDisplayTitle(), info.url, favicon, "");
}
});
Favicons.getLargestFaviconForPage(info.url, new GeckoAppShell.CreateShortcutFaviconLoadedListener(info.url, info.getDisplayTitle()));
return true;
}

View File

@ -33,7 +33,7 @@ public class TopSitesGridItemView extends RelativeLayout {
private static final ScaleType SCALE_TYPE_FAVICON = ScaleType.CENTER;
private static final ScaleType SCALE_TYPE_RESOURCE = ScaleType.CENTER;
private static final ScaleType SCALE_TYPE_THUMBNAIL = ScaleType.CENTER_CROP;
// Child views.
private final TextView mTitleView;
private final ImageView mThumbnailView;

View File

@ -607,7 +607,7 @@ public class TopSitesPage extends HomeFragment {
}
}
private class LoadIDAwareFaviconLoadedListener implements OnFaviconLoadedListener {
private static class LoadIDAwareFaviconLoadedListener implements OnFaviconLoadedListener {
private volatile int loadId = Favicons.NOT_LOADING;
private final TopSitesGridItemView view;
public LoadIDAwareFaviconLoadedListener(TopSitesGridItemView view) {

View File

@ -26,6 +26,8 @@ import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class TwoLinePageRow extends LinearLayout
implements Tabs.OnTabsChangedListener {
private static final int NO_ICON = 0;
@ -39,13 +41,33 @@ public class TwoLinePageRow extends LinearLayout
private boolean mShowIcons;
private int mLoadFaviconJobId = Favicons.NOT_LOADING;
// Listener for handling Favicon loads.
private final OnFaviconLoadedListener mFaviconListener = new OnFaviconLoadedListener() {
// Only holds a reference to the FaviconView itself, so if the row gets
// discarded while a task is outstanding, we'll leak less memory.
private static class UpdateViewFaviconLoadedListener implements OnFaviconLoadedListener {
private final WeakReference<FaviconView> view;
public UpdateViewFaviconLoadedListener(FaviconView view) {
this.view = new WeakReference<FaviconView>(view);
}
@Override
public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) {
setFaviconWithUrl(favicon, faviconURL);
FaviconView v = view.get();
if (v == null) {
// Guess we stuck around after the TwoLinePageRow went away.
return;
}
if (favicon == null) {
v.showDefaultFavicon();
return;
}
v.updateImage(favicon, url);
}
};
}
// Listener for handling Favicon loads.
private final OnFaviconLoadedListener mFaviconListener;
// The URL for the page corresponding to this view.
private String mPageUrl;
@ -67,6 +89,7 @@ public class TwoLinePageRow extends LinearLayout
mTitle = (TextView) findViewById(R.id.title);
mUrl = (TextView) findViewById(R.id.url);
mFavicon = (FaviconView) findViewById(R.id.favicon);
mFaviconListener = new UpdateViewFaviconLoadedListener(mFavicon);
}
@Override