eliminate Interfaces used only internal to AppDetails class

When dealing with complex lifecycles like Fragments, it is important
to expose the reliance of the Fragment on the Activity, since they
have different lifecycles.

Just cast to AppDetails instead of adding complexity with unneeded
Interfaces.  The actual instance and class will be the same with or
without the Interfaces, so it does not help with lifecycle issues.
The methods that implement the interfaces only hide the fact that they
rely on an active instance of AppDetails, which can lead to
lifecycle-related crashes.

This is a step along the way to streamlining AppDetails Activity so that it
only uses Fragments when they are beneficial.
This commit is contained in:
Hans-Christoph Steiner 2016-04-12 12:30:39 -04:00
parent 20c66a825d
commit 2e3d2c84ae

View File

@ -97,27 +97,7 @@ import java.io.File;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
interface AppDetailsData { public class AppDetails extends AppCompatActivity {
App getApp();
AppDetails.ApkListAdapter getApks();
}
/**
* Interface which allows the apk list fragment to communicate with the activity when
* a user requests to install/remove an apk by clicking on an item in the list.
* <p/>
* NOTE: This is <em>not</em> to do with with the sudo/packagemanager/other installer
* stuff which allows multiple ways to install apps. It is only here to make fragment-
* activity communication possible.
*/
interface AppInstallListener {
void install(final Apk apk);
void removeApk(String packageName);
}
public class AppDetails extends AppCompatActivity implements AppDetailsData, AppInstallListener {
private static final String TAG = "AppDetails"; private static final String TAG = "AppDetails";
@ -807,7 +787,6 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
} }
// Install the version of this app denoted by 'app.curApk'. // Install the version of this app denoted by 'app.curApk'.
@Override
public void install(final Apk apk) { public void install(final Apk apk) {
if (isFinishing()) { if (isFinishing()) {
return; return;
@ -881,7 +860,6 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
} }
} }
@Override
public void removeApk(String packageName) { public void removeApk(String packageName) {
try { try {
installer.deletePackage(packageName); installer.deletePackage(packageName);
@ -976,12 +954,10 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
} }
} }
@Override
public App getApp() { public App getApp() {
return app; return app;
} }
@Override
public ApkListAdapter getApks() { public ApkListAdapter getApks() {
return adapter; return adapter;
} }
@ -989,7 +965,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
public static class AppDetailsSummaryFragment extends Fragment { public static class AppDetailsSummaryFragment extends Fragment {
final Preferences prefs; final Preferences prefs;
private AppDetailsData data; private AppDetails appDetails;
private static final int MAX_LINES = 5; private static final int MAX_LINES = 5;
private static boolean viewAllDescription; private static boolean viewAllDescription;
private static LinearLayout llViewMoreDescription; private static LinearLayout llViewMoreDescription;
@ -1018,15 +994,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
@Override @Override
public void onAttach(Activity activity) { public void onAttach(Activity activity) {
super.onAttach(activity); super.onAttach(activity);
data = (AppDetailsData) activity; appDetails = (AppDetails) activity;
}
App getApp() {
return data.getApp();
}
ApkListAdapter getApks() {
return data.getApks();
} }
@Override @Override
@ -1085,7 +1053,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
private final View.OnClickListener mOnClickListener = new View.OnClickListener() { private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
String url = null; String url = null;
App app = getApp(); App app = appDetails.getApp();
switch (v.getId()) { switch (v.getId()) {
case R.id.website: case R.id.website:
url = app.webURL; url = app.webURL;
@ -1138,7 +1106,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
}; };
private void setupView(final View view) { private void setupView(final View view) {
App app = getApp(); App app = appDetails.getApp();
// Expandable description // Expandable description
final TextView description = (TextView) view.findViewById(R.id.description); final TextView description = (TextView) view.findViewById(R.id.description);
final Spanned desc = Html.fromHtml(app.description, null, new Utils.HtmlTagHandler()); final Spanned desc = Html.fromHtml(app.description, null, new Utils.HtmlTagHandler());
@ -1264,8 +1232,8 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
} }
Apk curApk = null; Apk curApk = null;
for (int i = 0; i < getApks().getCount(); i++) { for (int i = 0; i < appDetails.getApks().getCount(); i++) {
final Apk apk = getApks().getItem(i); final Apk apk = appDetails.getApks().getItem(i);
if (apk.vercode == app.suggestedVercode) { if (apk.vercode == app.suggestedVercode) {
curApk = apk; curApk = apk;
break; break;
@ -1277,7 +1245,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
final TextView permissionHeader = (TextView) view.findViewById(R.id.permissions); final TextView permissionHeader = (TextView) view.findViewById(R.id.permissions);
final boolean curApkCompatible = curApk != null && curApk.compatible; final boolean curApkCompatible = curApk != null && curApk.compatible;
if (!getApks().isEmpty() && (curApkCompatible || prefs.showIncompatibleVersions())) { if (!appDetails.getApks().isEmpty() && (curApkCompatible || prefs.showIncompatibleVersions())) {
// build and set the string once // build and set the string once
buildPermissionInfo(); buildPermissionInfo();
permissionHeader.setOnClickListener(expanderPermissions); permissionHeader.setOnClickListener(expanderPermissions);
@ -1310,7 +1278,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
private void buildPermissionInfo() { private void buildPermissionInfo() {
final TextView permissionListView = (TextView) llViewMorePermissions.findViewById(R.id.permissions_list); final TextView permissionListView = (TextView) llViewMorePermissions.findViewById(R.id.permissions_list);
CommaSeparatedList permsList = getApks().getItem(0).permissions; CommaSeparatedList permsList = appDetails.getApks().getItem(0).permissions;
if (permsList == null) { if (permsList == null) {
permissionListView.setText(R.string.no_permissions); permissionListView.setText(R.string.no_permissions);
} else { } else {
@ -1362,7 +1330,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
return; return;
} }
App app = getApp(); App app = appDetails.getApp();
TextView signatureView = (TextView) view.findViewById(R.id.signature); TextView signatureView = (TextView) view.findViewById(R.id.signature);
if (prefs.expertMode() && !TextUtils.isEmpty(app.installedSig)) { if (prefs.expertMode() && !TextUtils.isEmpty(app.installedSig)) {
signatureView.setVisibility(View.VISIBLE); signatureView.setVisibility(View.VISIBLE);
@ -1375,7 +1343,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
public static class AppDetailsHeaderFragment extends Fragment implements View.OnClickListener { public static class AppDetailsHeaderFragment extends Fragment implements View.OnClickListener {
private AppDetailsData data; private AppDetails appDetails;
private Button btMain; private Button btMain;
private ProgressBar progressBar; private ProgressBar progressBar;
private TextView progressSize; private TextView progressSize;
@ -1396,14 +1364,6 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
.build(); .build();
} }
private App getApp() {
return data.getApp();
}
private ApkListAdapter getApks() {
return data.getApks();
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.app_details_header, container, false); View view = inflater.inflate(R.layout.app_details_header, container, false);
@ -1414,11 +1374,11 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
@Override @Override
public void onAttach(Activity activity) { public void onAttach(Activity activity) {
super.onAttach(activity); super.onAttach(activity);
data = (AppDetailsData) activity; appDetails = (AppDetails) activity;
} }
private void setupView(View view) { private void setupView(View view) {
App app = getApp(); App app = appDetails.getApp();
// Set the icon... // Set the icon...
ImageView iv = (ImageView) view.findViewById(R.id.icon); ImageView iv = (ImageView) view.findViewById(R.id.icon);
@ -1506,13 +1466,13 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
*/ */
@Override @Override
public void onClick(View view) { public void onClick(View view) {
AppDetails activity = (AppDetails) getActivity(); AppDetails appDetails = (AppDetails) getActivity();
if (activity == null || activity.downloadHandler == null) { if (appDetails == null || appDetails.downloadHandler == null) {
return; return;
} }
DownloaderService.cancel(getContext(), activity.downloadHandler.urlString); DownloaderService.cancel(getContext(), appDetails.downloadHandler.urlString);
activity.cleanUpFinishedDownload(); appDetails.cleanUpFinishedDownload();
setProgressVisible(false); setProgressVisible(false);
updateViews(); updateViews();
} }
@ -1522,21 +1482,20 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
} }
public void updateViews(View view) { public void updateViews(View view) {
App app = getApp(); App app = appDetails.getApp();
TextView statusView = (TextView) view.findViewById(R.id.status); TextView statusView = (TextView) view.findViewById(R.id.status);
btMain.setVisibility(View.VISIBLE); btMain.setVisibility(View.VISIBLE);
AppDetails activity = (AppDetails) getActivity(); if (appDetails.downloadHandler != null) {
if (activity.downloadHandler != null) {
btMain.setText(R.string.downloading); btMain.setText(R.string.downloading);
btMain.setEnabled(false); btMain.setEnabled(false);
} else if (!app.isInstalled() && app.suggestedVercode > 0 && } else if (!app.isInstalled() && app.suggestedVercode > 0 &&
activity.adapter.getCount() > 0) { appDetails.adapter.getCount() > 0) {
// Check count > 0 due to incompatible apps resulting in an empty list. // Check count > 0 due to incompatible apps resulting in an empty list.
// If App isn't installed // If App isn't installed
installed = false; installed = false;
statusView.setText(R.string.details_notinstalled); statusView.setText(R.string.details_notinstalled);
NfcHelper.disableAndroidBeam(activity); NfcHelper.disableAndroidBeam(appDetails);
// Set Install button and hide second button // Set Install button and hide second button
btMain.setText(R.string.menu_install); btMain.setText(R.string.menu_install);
btMain.setOnClickListener(mOnClickListener); btMain.setOnClickListener(mOnClickListener);
@ -1545,13 +1504,13 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
// If App is installed // If App is installed
installed = true; installed = true;
statusView.setText(getString(R.string.details_installed, app.installedVersionName)); statusView.setText(getString(R.string.details_installed, app.installedVersionName));
NfcHelper.setAndroidBeam(activity, app.packageName); NfcHelper.setAndroidBeam(appDetails, app.packageName);
if (app.canAndWantToUpdate()) { if (app.canAndWantToUpdate()) {
updateWanted = true; updateWanted = true;
btMain.setText(R.string.menu_upgrade); btMain.setText(R.string.menu_upgrade);
} else { } else {
updateWanted = false; updateWanted = false;
if (activity.packageManager.getLaunchIntentForPackage(app.packageName) != null) { if (appDetails.packageManager.getLaunchIntentForPackage(app.packageName) != null) {
btMain.setText(R.string.menu_launch); btMain.setText(R.string.menu_launch);
} else { } else {
btMain.setText(R.string.menu_uninstall); btMain.setText(R.string.menu_uninstall);
@ -1569,8 +1528,8 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
author.setVisibility(View.VISIBLE); author.setVisibility(View.VISIBLE);
} }
TextView currentVersion = (TextView) view.findViewById(R.id.current_version); TextView currentVersion = (TextView) view.findViewById(R.id.current_version);
if (!getApks().isEmpty()) { if (!appDetails.getApks().isEmpty()) {
currentVersion.setText(getApks().getItem(0).version + " (" + app.license + ")"); currentVersion.setText(appDetails.getApks().getItem(0).version + " (" + app.license + ")");
} else { } else {
currentVersion.setVisibility(View.GONE); currentVersion.setVisibility(View.GONE);
btMain.setVisibility(View.GONE); btMain.setVisibility(View.GONE);
@ -1580,7 +1539,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
private final View.OnClickListener mOnClickListener = new View.OnClickListener() { private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
App app = getApp(); App app = appDetails.getApp();
AppDetails activity = (AppDetails) getActivity(); AppDetails activity = (AppDetails) getActivity();
if (updateWanted && app.suggestedVercode > 0) { if (updateWanted && app.suggestedVercode > 0) {
Apk apkToInstall = ApkProvider.Helper.find(activity, app.packageName, app.suggestedVercode); Apk apkToInstall = ApkProvider.Helper.find(activity, app.packageName, app.suggestedVercode);
@ -1610,8 +1569,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
private static final String SUMMARY_TAG = "summary"; private static final String SUMMARY_TAG = "summary";
private AppDetailsData data; private AppDetails appDetails;
private AppInstallListener installListener;
private AppDetailsSummaryFragment summaryFragment; private AppDetailsSummaryFragment summaryFragment;
private FrameLayout headerView; private FrameLayout headerView;
@ -1619,24 +1577,11 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
@Override @Override
public void onAttach(Activity activity) { public void onAttach(Activity activity) {
super.onAttach(activity); super.onAttach(activity);
data = (AppDetailsData) activity; appDetails = (AppDetails) activity;
installListener = (AppInstallListener) activity;
}
void install(final Apk apk) {
installListener.install(apk);
} }
void remove() { void remove() {
installListener.removeApk(getApp().packageName); appDetails.removeApk(appDetails.getApp().packageName);
}
App getApp() {
return data.getApp();
}
ApkListAdapter getApks() {
return data.getApks();
} }
@Override @Override
@ -1658,13 +1603,13 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
setListAdapter(null); setListAdapter(null);
getListView().addHeaderView(headerView); getListView().addHeaderView(headerView);
setListAdapter(getApks()); setListAdapter(appDetails.getApks());
} }
@Override @Override
public void onListItemClick(ListView l, View v, int position, long id) { public void onListItemClick(ListView l, View v, int position, long id) {
App app = getApp(); App app = appDetails.getApp();
final Apk apk = getApks().getItem(position - l.getHeaderViewsCount()); final Apk apk = appDetails.getApks().getItem(position - l.getHeaderViewsCount());
if (app.installedVersionCode == apk.vercode) { if (app.installedVersionCode == apk.vercode) {
remove(); remove();
} else if (app.installedVersionCode > apk.vercode) { } else if (app.installedVersionCode > apk.vercode) {
@ -1675,7 +1620,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
@Override @Override
public void onClick(DialogInterface dialog, public void onClick(DialogInterface dialog,
int whichButton) { int whichButton) {
install(apk); appDetails.install(apk);
} }
}); });
builder.setNegativeButton(R.string.no, builder.setNegativeButton(R.string.no,
@ -1688,7 +1633,7 @@ public class AppDetails extends AppCompatActivity implements AppDetailsData, App
AlertDialog alert = builder.create(); AlertDialog alert = builder.create();
alert.show(); alert.show();
} else { } else {
install(apk); appDetails.install(apk);
} }
} }