v7 getSupportActionBar() is throwing NullPointerException - java

I'm launching a new activity (TVMPDFActivity) from my root activity. I'm using Android Annotations, so this is how I'm launching the Activity:
TVMPDFActivity_.intent(this.getActivity()).start();
TVMPDFActivity is a subclass of PDFPreviewActivity which is a subclass of ActionBarActivity.
A NullPointerException is being thrown from onCreate in PDFPreviewActivity when I simply try to GET the ActionBar. On this line:
final ActionBar actionBar = getSupportActionBar();
Here is the stacktrace from my code to the NPE:
Caused by: java.lang.NullPointerException
at android.support.v7.internal.app.WindowDecorActionBar.getDecorToolbar(WindowDecorActionBar.java:248)
at android.support.v7.internal.app.WindowDecorActionBar.init(WindowDecorActionBar.java:201)
at android.support.v7.internal.app.WindowDecorActionBar.<init>(WindowDecorActionBar.java:176)
at android.support.v7.app.ActionBarActivityDelegateBase.createSupportActionBar(ActionBarActivityDelegateBase.java:156)
at android.support.v7.app.ActionBarActivityDelegate.getSupportActionBar(ActionBarActivityDelegate.java:123)
at android.support.v7.app.ActionBarActivity.getSupportActionBar(ActionBarActivity.java:73)
at com.my.app.PDFPreviewActivity.onCreate(PDFPreviewActivity.java:63)
at com.my.app.TVMPDFActivity.onCreate(TVMPDFActivity.java:24)
at com.my.app.TVMPDFActivity_.onCreate(TVMPDFActivity_.java:31)
Here are the onCreate methods of the various classes involved:
public class TVMPDFActivity extends PDFPreviewActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
this.setContentView(R.layout.tvm_pdf_activity);
super.onCreate(savedInstanceState);
...
}
}
public abstract class PDFPreviewActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar(); // throws NullPointerException
...
}
}
Why am I getting a NullPointerException from deep within the support v7 code?

you should call super.onCreate before setContentView in TVMPDFActivity in order to give android the opportunity to initialize its internal state, before trying to access something that relies on that internal state. For onCreate/onStart/onResume call the super always as first statement

Related

Error replacing ButterKnife annotation with native ViewBinding

I'm refactoring a lot my app activities and layouts (e.g. ButterKnife annotation -> viewBinding, *Layout --> ConstraintLayout). For a lot of them there were no problem, but at the moment I'm stuck in this situation of my Activity:
Original code:
...
#BindView(R.id.logged_user)
TextView mUserLoggedView;
#BindView(R.id.patient_code)
EditText mPatientCodeView;
#BindView(R.id.search_form)
ScrollView mFormView;
#BindView(R.id.search_progress_layout)
LinearLayout mProgressLayout;
#BindView(R.id.search_progress_text)
TextView mProgressTextView;
App application;
SearchActivityMapper mapper;
CompositeDisposable mCompositeDisposable;
#Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.activity_search_patient);
ButterKnife.bind(this);
application = (App) getApplication();
application.getAppComponent().inject(this);
...
Code after review:
...
App application;
SearchActivityMapper mapper;
CompositeDisposable mCompositeDisposable;
#Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
viewBinding = ActivitySearchPatientBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
ButterKnife.bind(this);
application = (App) getApplication();
application.getAppComponent().inject(this);
...
I did the same in all the previous Activity and everything went well; when the latter Activity is launched I got this error
java.lang.NoSuchFieldError: No field mUserLoggedView of type Landroid/widget/TextView; in class Lit/company/etmhome/activities/search/SearchActivity; or its superclasses (declaration of 'it.company.etmhome.activities.search.SearchActivity' appears in /data/data/it.company.etmhome.debug/code_cache/.overlay/base.apk/classes27.dex)
I can't understand why it can't find that field that I removed and it's not present in the whole project.
Am I missing something???
Thanks in advance

Is there a way I can use two classes or more for one Activity in android studio?

Is there a way I can use two classes or more for one Activity in android studio?
I used this Test code but this App crashes:
Note : This is for learning purposes so that it can be used to split up huge classes into sub classes
//Main Activity Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test ob=new Test ();
ob.test();
}
}
// Test Class
public class Test extends MainActivity {
public void test()
{
TextView t=findViewById(R.id.h);
t.setText("Miaooo");
}
}
What you can do is to pass the activity with as the parameter of constructor and use that reference to call "findViewbyId()"
public class Test{
public void test(Activity activity)
{
TextView t=activity.findViewById(R.id.h);
t.setText("Miaooo");
}
while in your main activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test ob=new Test (this);
ob.test();
}
If you want to your "Test" class to be extended by an activity than you should use activity creation wizard to setup all the stuff in manifest and .xml. It would be quite long process to do it manually.
When you write class Test extends MainActivity it means that Test should be activity too and you have to write setContentView(R.layout.your_layout); to set the view layer for your activity. Also, Test should be registered as Activity in your manifest file. Anyway if you want to change the text of the TextView why you want to create a new activity?
place your code in the activity main.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test();
}
public void test()
{
TextView t=findViewById(R.id.h);
t.setText("Miaooo");
}

How to correct add a listener to a Fragment

I got two Fragments (basic-setup) with a FragmentPagerAdapter for use in a TabLayout.
tabLayout.setupWithViewPager(myViewPagerWithAdapter);
My Adapter takes an array of Fragments and titles as argument (also the FragmentManger for the super call).
MyViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager() ,fragments, titles);
My Fragments (indeed 2) got a WebView in their xml file. To use the WebViews outside the fragments (it's kinda odd to code the control of the WebViews inside fragments, because the MainActivity is mainly involved with my user interaction). To know when my WebViews in the fragments were inflated, I added a simple interface, called OnFragmentCreatedListener, which is triggered in public void onActivityCreated(Bundle savedInstanceState) of the fragments. I add the listener through following way:
private OnFragmentCreatedListener listener;
...
public void addOnFragmentCreatedListener(OnFragmentCreatedListener listener) {
this.listener = listener;
}
In my MainActivity I add this listener like this:
public class MainActivity extends AppCompatActivity implements OnFragmentCreatedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
MyFragment fragment = MyFragment.newInstance();
...
fragment.addOnFragmentCreatedListener(this);
...
}
#Override
public void onFragmentCreatedListener() {
// Do my stuff
}
Now when the screen rotates and the activity is restarted, the listener in the fragment stays null (wasn't initialized). Now I don't know what to do, because I don't understand this behavior. The code should do the same like in the first protected void onCreate(Bundle savedInstanceState) of the MainActivity. It's adding the listener but it stays null (like wtf?).
Thank you for spending your time!

Android toolbar save state when visible/gone

I'm making a calculator (those bits are not shown in the code below) and I have a toolbar at the bottom of the application, and I can toggle its visibility from a menu. This is my current MainActivity class:
public class MainActivity extends Activity implements OnClickListener {
public Toolbar toolbar_btm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar_btm = findViewById(R.id.toolbar_bottom);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Toolbar toolbar_btm = findViewById(R.id.toolbar_bottom);
outState.putInt("TOOLBAR_VISIBLE", toolbar_btm.getVisibility());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//Toolbar toolbar_btm = findViewById(R.id.toolbar_bottom);
toolbar_btm.setVisibility(savedInstanceState.getInt("TOOLBAR_VISIBLE"));
}
//Toggles the toolbar to show/hide
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.toolbar_toggle:
Toolbar toolbar_btmtog = findViewById(R.id.toolbar_bottom);
if (toolbar_btmtog.getVisibility() == View.GONE)
toolbar_btmtog.setVisibility(View.VISIBLE);
else if (toolbar_btmtog.getVisibility() == View.VISIBLE)
toolbar_btmtog.setVisibility(View.GONE);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
However, I cannot seem to keep this visible/gone state in memory. I've tried using onSaveInstanceState and onRestoreInstanceState, but when I run my code, it throws the following exception:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.calculator/com.example.calculator.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.Toolbar.setVisibility(int)' on a null object reference
I simply cannot figure out what the issue is. I'm using putInt and getInt and I'm declaring the toolbar with the right name. So, why am I getting a null object reference?
You have two varaibles named toolbar_btm. One is global and unassigned, and another is in onOptionsItemSelected(MenuItem item). That local variable "overwrites" local variable (in function)
You should declare Toolbar as global, and then assign its value in OnCreate() or, if that doesn't work, in overridden function OnResume(). You assign value by not using Toolbar keyword for a second time, so like this.
toolbar_btm = findViewById(R.id.toolbar_bottom);
UPDATE:
You could also drop Toolbar altogether and use ActionBar instead. This snippet will toggle action bar visibility in Activity (not Fragment):
ActionBar actionBar = getActionBar();
if(actionBar.isShowing())
actionBar.hide();
else
actionBar.show();
this.invalidateOptionsMenu();
You are not assigning your Toolbar variable. After menu option was selected you are using local one. Put this code in onCreate() :
toolbar_btm = findViewById(R.id.toolbar_bottom);

Chronometer is null even though parent class initialised it

I got this weird problem and it's bugging me. I don't understand why I get this NullPointerException when I did initialise chronometer in MainActivity. If I initialise chronometer in SecondActivity the program works fine.
Hopefully someone can clear this up...
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Chronometer.setOnChronometerTickListener(android.widget.Chronometer$OnChronometerTickListener)' on a null object reference
-
public class MainActivity extends AppCompatActivity {
protected Chronometer chronometer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//chronometer gets initialised here but it's still null appearantly
chronometer = (Chronometer) findViewById(R.id.chronometer1);
//this works
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#cd2626")));
}
}
-
public class SecondActivity extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
//if chronometer gets initialised again, program does work.
//chronometer = (Chronometer) findViewById(R.id.chronometer1)
}
}
include setContentView(R.layout.main_layout); in your mainactivity otherwise findviewbyid will not be able to find chronometer and it will always show null exception
Your chronometer variable is not initialized in MainActivity.onCreate because layout is inflated (setContentView called) only in SecondActivity.onCreate. So findViewById in your MainActivity has no effect.
In general I recommend not to build class hierarchies aroun Activity. Try to use something else, like interfaces to achieve what you need.

Categories