Fixed issue 472, NPE on android 3.1 (and 3.0).

The Activity.getActionBar() method can only be called after
setContentView() has been invoked, as described here:

  http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html

I couldn't think of any way to enforce this safely
(i.e. make the compiler kick up a stink if we didn't do it). As such,
I just put a comment above each usage of the ActionBarCompat class.

Another outstanding issue is a duplicate of 474, where it crashes when you
press the "Up" button from ManageRepos, but I'll create a different issue
for that.
This commit is contained in:
Peter Serwylo 2014-03-22 08:25:26 +11:00
parent 0e47ac6900
commit 9c9ecc5140
6 changed files with 43 additions and 4 deletions

View File

@ -261,11 +261,13 @@ public class AppDetails extends ListActivity {
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
ActionBarCompat abCompat = ActionBarCompat.create(this);
abCompat.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.appdetails);
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
// for reason why.
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
Uri data = i.getData();
if (data != null) {

View File

@ -27,6 +27,7 @@ import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.MenuItem;
import android.widget.LinearLayout;
import org.fdroid.fdroid.compat.ActionBarCompat;
import org.fdroid.fdroid.views.fragments.RepoListFragment;
@ -49,6 +50,14 @@ public class ManageRepo extends FragmentActivity {
((FDroidApp) getApplication()).applyTheme(this);
if (savedInstanceState == null) {
// Need to set a dummy view (which will get overridden by the fragment manager
// below) so that we can call setContentView(). This is a work around for
// a (bug?) thing in 3.0, 3.1 which requires setContentView to be invoked before
// the actionbar is played with:
// http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
setContentView( new LinearLayout(this) );
listFragment = new RepoListFragment();
getSupportFragmentManager()
.beginTransaction()

View File

@ -59,7 +59,12 @@ public class PreferencesActivity extends PreferenceActivity implements
protected void onCreate(Bundle savedInstanceState) {
((FDroidApp) getApplication()).applyTheme(this);
super.onCreate(savedInstanceState);
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
// for reason why.
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
addPreferencesFromResource(R.xml.preferences);
}

View File

@ -73,9 +73,14 @@ public class SearchResults extends ListActivity {
((FDroidApp) getApplication()).applyTheme(this);
super.onCreate(savedInstanceState);
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.searchresults);
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
// for reason why.
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
// Start a search by just typing
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
}

View File

@ -20,6 +20,15 @@ public abstract class ActionBarCompat extends Compatibility {
this.activity = activity;
}
/**
* Cannot be accessed until after setContentView (on 3.0 and 3.1 devices) has
* been called on the relevant activity. If you don't have a content view
* (e.g. when using fragment manager to add fragments to the activity) then you
* will still need to call setContentView(), with a "new LinearLayout()" or something
* useless like that.
* See: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
* for details.
*/
public abstract void setDisplayHomeAsUpEnabled(boolean value);
}

View File

@ -15,6 +15,7 @@ import android.os.Parcelable;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.Toast;
import org.fdroid.fdroid.FDroidApp;
@ -41,6 +42,14 @@ public class RepoDetailsActivity extends FragmentActivity {
long repoId = getIntent().getLongExtra(RepoDetailsFragment.ARG_REPO_ID, 0);
if (savedInstanceState == null) {
// Need to set a dummy view (which will get overridden by the fragment manager
// below) so that we can call setContentView(). This is a work around for
// a (bug?) thing in 3.0, 3.1 which requires setContentView to be invoked before
// the actionbar is played with:
// http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
setContentView( new LinearLayout(this) );
RepoDetailsFragment fragment = new RepoDetailsFragment();
fragment.setArguments(getIntent().getExtras());
getSupportFragmentManager()