mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 865060 - Clean up threads in AboutHome views. r=lucasr
This commit is contained in:
parent
597f33c342
commit
9d8e74f38e
@ -10,6 +10,7 @@ import org.mozilla.gecko.Favicons;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@ -26,6 +27,7 @@ import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
@ -138,9 +140,9 @@ public class AddonsSection extends AboutHomeSection {
|
||||
}
|
||||
|
||||
public void readRecommendedAddons() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
new UiAsyncTask<Void, Void, JSONArray>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public JSONArray doInBackground(Void... params) {
|
||||
final String addonsFilename = "recommended-addons.json";
|
||||
String jsonString;
|
||||
try {
|
||||
@ -159,68 +161,72 @@ public class AddonsSection extends AboutHomeSection {
|
||||
}
|
||||
}
|
||||
|
||||
final JSONArray array = addonsArray;
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (array == null || array.length() == 0) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
return addonsArray;
|
||||
}
|
||||
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
JSONObject jsonobj = array.getJSONObject(i);
|
||||
String name = jsonobj.getString("name");
|
||||
String version = jsonobj.getString("version");
|
||||
String text = name + " " + version;
|
||||
@Override
|
||||
public void onPostExecute(JSONArray addons) {
|
||||
if (addons == null || addons.length() == 0) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
SpannableString spannable = new SpannableString(text);
|
||||
spannable.setSpan(sSubTitleSpan, name.length() + 1, text.length(), 0);
|
||||
|
||||
final TextView row = (TextView) LayoutInflater.from(mContext).inflate(R.layout.abouthome_addon_row, getItemsContainer(), false);
|
||||
row.setText(spannable, TextView.BufferType.SPANNABLE);
|
||||
|
||||
Drawable drawable = mContext.getResources().getDrawable(R.drawable.ic_addons_empty);
|
||||
drawable.setBounds(sIconBounds);
|
||||
row.setCompoundDrawables(drawable, null, null, null);
|
||||
|
||||
String iconUrl = jsonobj.getString("iconURL");
|
||||
String pageUrl = getPageUrlFromIconUrl(iconUrl);
|
||||
|
||||
final String homepageUrl = jsonobj.getString("homepageURL");
|
||||
row.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mUriLoadListener != null)
|
||||
mUriLoadListener.onAboutHomeUriLoad(homepageUrl);
|
||||
}
|
||||
});
|
||||
row.setOnKeyListener(GamepadUtils.getClickDispatcher());
|
||||
|
||||
Favicons favicons = Favicons.getInstance();
|
||||
favicons.loadFavicon(pageUrl, iconUrl, true,
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
@Override
|
||||
public void onFaviconLoaded(String url, Bitmap favicon) {
|
||||
if (favicon != null) {
|
||||
Drawable drawable = new BitmapDrawable(favicon);
|
||||
drawable.setBounds(sIconBounds);
|
||||
row.setCompoundDrawables(drawable, null, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addItem(row);
|
||||
}
|
||||
|
||||
show();
|
||||
} catch (JSONException e) {
|
||||
Log.i(LOGTAG, "error reading json file", e);
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < addons.length(); i++) {
|
||||
View addonView = createAddonView(addons.getJSONObject(i), getItemsContainer());
|
||||
addItem(addonView);
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error reading JSON", e);
|
||||
return;
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
View createAddonView(JSONObject addonJSON, ViewGroup parent) throws JSONException {
|
||||
String name = addonJSON.getString("name");
|
||||
String version = addonJSON.getString("version");
|
||||
String text = name + " " + version;
|
||||
|
||||
SpannableString spannable = new SpannableString(text);
|
||||
spannable.setSpan(sSubTitleSpan, name.length() + 1, text.length(), 0);
|
||||
|
||||
final TextView row = (TextView) LayoutInflater.from(mContext).inflate(R.layout.abouthome_addon_row, getItemsContainer(), false);
|
||||
row.setText(spannable, TextView.BufferType.SPANNABLE);
|
||||
|
||||
Drawable drawable = mContext.getResources().getDrawable(R.drawable.ic_addons_empty);
|
||||
drawable.setBounds(sIconBounds);
|
||||
row.setCompoundDrawables(drawable, null, null, null);
|
||||
|
||||
String iconUrl = addonJSON.getString("iconURL");
|
||||
String pageUrl = getPageUrlFromIconUrl(iconUrl);
|
||||
|
||||
final String homepageUrl = addonJSON.getString("homepageURL");
|
||||
row.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mUriLoadListener != null)
|
||||
mUriLoadListener.onAboutHomeUriLoad(homepageUrl);
|
||||
}
|
||||
});
|
||||
row.setOnKeyListener(GamepadUtils.getClickDispatcher());
|
||||
|
||||
Favicons favicons = Favicons.getInstance();
|
||||
favicons.loadFavicon(pageUrl, iconUrl, true,
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
@Override
|
||||
public void onFaviconLoaded(String url, Bitmap favicon) {
|
||||
if (favicon != null) {
|
||||
Drawable drawable = new BitmapDrawable(favicon);
|
||||
drawable.setBounds(sIconBounds);
|
||||
row.setCompoundDrawables(drawable, null, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@ -19,6 +20,7 @@ import android.graphics.Bitmap;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -27,22 +29,34 @@ import java.util.ArrayList;
|
||||
public class LastTabsSection extends AboutHomeSection {
|
||||
private Context mContext;
|
||||
|
||||
private class TabInfo {
|
||||
final String url;
|
||||
final String title;
|
||||
final Bitmap favicon;
|
||||
|
||||
TabInfo(String url, String title, Bitmap favicon) {
|
||||
this.url = url;
|
||||
this.title = title;
|
||||
this.favicon = favicon;
|
||||
}
|
||||
}
|
||||
|
||||
public LastTabsSection(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void readLastTabs() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
new UiAsyncTask<Void, Void, ArrayList<TabInfo>>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
public void run() {
|
||||
protected ArrayList<TabInfo> doInBackground(Void... params) {
|
||||
String jsonString = GeckoProfile.get(mContext).readSessionFile(true);
|
||||
if (jsonString == null) {
|
||||
// no previous session data
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
final ArrayList<String> lastTabUrlsList = new ArrayList<String>();
|
||||
final ArrayList<TabInfo> lastTabs = new ArrayList<TabInfo>();
|
||||
new SessionParser() {
|
||||
@Override
|
||||
public void onTabRead(final SessionTab tab) {
|
||||
@ -54,61 +68,74 @@ public class LastTabsSection extends AboutHomeSection {
|
||||
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
final Bitmap favicon = BrowserDB.getFaviconForUrl(resolver, url);
|
||||
lastTabUrlsList.add(url);
|
||||
|
||||
LastTabsSection.this.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
View container = LayoutInflater.from(mContext).inflate(R.layout.abouthome_last_tabs_row, getItemsContainer(), false);
|
||||
((TextView) container.findViewById(R.id.last_tab_title)).setText(tab.getSelectedTitle());
|
||||
((TextView) container.findViewById(R.id.last_tab_url)).setText(tab.getSelectedUrl());
|
||||
if (favicon != null) {
|
||||
((ImageView) container.findViewById(R.id.last_tab_favicon)).setImageBitmap(favicon);
|
||||
}
|
||||
|
||||
container.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int flags = Tabs.LOADURL_NEW_TAB;
|
||||
if (Tabs.getInstance().getSelectedTab().isPrivate())
|
||||
flags |= Tabs.LOADURL_PRIVATE;
|
||||
Tabs.getInstance().loadUrl(url, flags);
|
||||
}
|
||||
});
|
||||
container.setOnKeyListener(GamepadUtils.getClickDispatcher());
|
||||
|
||||
addItem(container);
|
||||
}
|
||||
});
|
||||
final String title = tab.getSelectedTitle();
|
||||
lastTabs.add(new TabInfo(url, title, favicon));
|
||||
}
|
||||
}.parse(jsonString);
|
||||
|
||||
final int nu = lastTabUrlsList.size();
|
||||
if (nu >= 1) {
|
||||
post(new Runnable() {
|
||||
return lastTabs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(final ArrayList<TabInfo> lastTabs) {
|
||||
if (lastTabs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TabInfo tab : lastTabs) {
|
||||
final View tabView = createTabView(tab, getItemsContainer());
|
||||
addItem(tabView);
|
||||
}
|
||||
|
||||
// If we have at least one tab from last time, show the
|
||||
// container view.
|
||||
final int numTabs = lastTabs.size();
|
||||
if (numTabs > 1) {
|
||||
// If we have more than one tab from last time, show the
|
||||
// "Open all tabs" button
|
||||
showMoreText();
|
||||
setOnMoreTextClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (nu > 1) {
|
||||
showMoreText();
|
||||
setOnMoreTextClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int flags = Tabs.LOADURL_NEW_TAB;
|
||||
if (Tabs.getInstance().getSelectedTab().isPrivate())
|
||||
flags |= Tabs.LOADURL_PRIVATE;
|
||||
for (String url : lastTabUrlsList) {
|
||||
Tabs.getInstance().loadUrl(url, flags);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (nu == 1) {
|
||||
hideMoreText();
|
||||
public void onClick(View v) {
|
||||
int flags = Tabs.LOADURL_NEW_TAB;
|
||||
if (Tabs.getInstance().getSelectedTab().isPrivate())
|
||||
flags |= Tabs.LOADURL_PRIVATE;
|
||||
for (TabInfo tab : lastTabs) {
|
||||
Tabs.getInstance().loadUrl(tab.url, flags);
|
||||
}
|
||||
show();
|
||||
}
|
||||
});
|
||||
show();
|
||||
} else if (numTabs == 1) {
|
||||
hideMoreText();
|
||||
show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
View createTabView(final TabInfo tab, ViewGroup parent) {
|
||||
final String url = tab.url;
|
||||
final Bitmap favicon = tab.favicon;
|
||||
|
||||
View tabView = LayoutInflater.from(mContext).inflate(R.layout.abouthome_last_tabs_row, parent, false);
|
||||
((TextView) tabView.findViewById(R.id.last_tab_title)).setText(tab.title);
|
||||
((TextView) tabView.findViewById(R.id.last_tab_url)).setText(url);
|
||||
if (favicon != null) {
|
||||
((ImageView) tabView.findViewById(R.id.last_tab_favicon)).setImageBitmap(favicon);
|
||||
}
|
||||
|
||||
tabView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int flags = Tabs.LOADURL_NEW_TAB;
|
||||
if (Tabs.getInstance().getSelectedTab().isPrivate())
|
||||
flags |= Tabs.LOADURL_PRIVATE;
|
||||
Tabs.getInstance().loadUrl(url, flags);
|
||||
}
|
||||
});
|
||||
tabView.setOnKeyListener(GamepadUtils.getClickDispatcher());
|
||||
|
||||
return tabView;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.mozilla.gecko.TabsAccessor;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
@ -56,22 +57,22 @@ public class RemoteTabsSection extends AboutHomeSection
|
||||
}
|
||||
|
||||
public void loadRemoteTabs() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
new UiAsyncTask<Void, Void, Boolean>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public Boolean doInBackground(Void... params) {
|
||||
if (!SyncAccounts.syncAccountsExist(mActivity)) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hide();
|
||||
}
|
||||
});
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
TabsAccessor.getTabs(getContext(), NUMBER_OF_REMOTE_TABS, RemoteTabsSection.this);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
public void onPostExecute(Boolean syncAccountsExist) {
|
||||
if (!syncAccountsExist) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,46 +194,43 @@ public class TopSitesView extends GridView {
|
||||
}
|
||||
|
||||
public void loadTopSites() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
final Cursor oldCursor = (mTopSitesAdapter != null) ? mTopSitesAdapter.getCursor() : null;
|
||||
|
||||
new UiAsyncTask<Void, Void, Cursor>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
public void run() {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
|
||||
// Swap in the new cursor.
|
||||
final Cursor oldCursor = (mTopSitesAdapter != null) ? mTopSitesAdapter.getCursor() : null;
|
||||
final Cursor newCursor = BrowserDB.getTopSites(resolver, mNumberOfTopSites);
|
||||
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mTopSitesAdapter == null) {
|
||||
mTopSitesAdapter = new TopSitesCursorAdapter(mContext,
|
||||
R.layout.abouthome_topsite_item,
|
||||
newCursor,
|
||||
new String[] { URLColumns.TITLE },
|
||||
new int[] { R.id.title });
|
||||
|
||||
setAdapter(mTopSitesAdapter);
|
||||
} else {
|
||||
mTopSitesAdapter.changeCursor(newCursor);
|
||||
}
|
||||
|
||||
if (mTopSitesAdapter.getCount() > 0)
|
||||
loadTopSitesThumbnails(resolver);
|
||||
|
||||
// Free the old Cursor in the right thread now.
|
||||
if (oldCursor != null && !oldCursor.isClosed())
|
||||
oldCursor.close();
|
||||
|
||||
// Even if AboutHome isn't necessarily entirely loaded if we
|
||||
// get here, for phones this is the part the user initially sees,
|
||||
// so it's the one we will care about for now.
|
||||
if (mLoadCompleteListener != null)
|
||||
mLoadCompleteListener.onAboutHomeLoadComplete();
|
||||
}
|
||||
});
|
||||
protected Cursor doInBackground(Void... params) {
|
||||
return BrowserDB.getTopSites(resolver, mNumberOfTopSites);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Cursor newCursor) {
|
||||
if (mTopSitesAdapter == null) {
|
||||
mTopSitesAdapter = new TopSitesCursorAdapter(mContext,
|
||||
R.layout.abouthome_topsite_item,
|
||||
newCursor,
|
||||
new String[] { URLColumns.TITLE },
|
||||
new int[] { R.id.title });
|
||||
|
||||
setAdapter(mTopSitesAdapter);
|
||||
} else {
|
||||
mTopSitesAdapter.changeCursor(newCursor);
|
||||
}
|
||||
|
||||
if (mTopSitesAdapter.getCount() > 0)
|
||||
loadTopSitesThumbnails(resolver);
|
||||
|
||||
// Free the old Cursor in the right thread now.
|
||||
if (oldCursor != null && !oldCursor.isClosed())
|
||||
oldCursor.close();
|
||||
|
||||
// Even if AboutHome isn't necessarily entirely loaded if we
|
||||
// get here, for phones this is the part the user initially sees,
|
||||
// so it's the one we will care about for now.
|
||||
if (mLoadCompleteListener != null)
|
||||
mLoadCompleteListener.onAboutHomeLoadComplete();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -331,18 +328,23 @@ public class TopSitesView extends GridView {
|
||||
}
|
||||
|
||||
private void loadTopSitesThumbnails(final ContentResolver cr) {
|
||||
final List<String> urls = getTopSitesUrls();
|
||||
if (urls.size() == 0)
|
||||
return;
|
||||
|
||||
(new UiAsyncTask<Void, Void, Map<String, Bitmap> >(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
public Map<String, Bitmap> doInBackground(Void... params) {
|
||||
final List<String> urls = getTopSitesUrls();
|
||||
if (urls.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getThumbnailsFromCursor(BrowserDB.getThumbnailsForUrls(cr, urls));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Map<String, Bitmap> thumbnails) {
|
||||
if (thumbnails == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're waiting for a layout to happen, the GridView may be
|
||||
// stale, so store the pending thumbnails here. They will be
|
||||
// shown on the next layout pass.
|
||||
|
Loading…
Reference in New Issue
Block a user