What am I doing wrong with my handling of Contex ( Java - Android)

14,875

Solution 1

NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

Because firstElement,secondElement and thirdElement TextView's is created using con before calling class constructor in which you are initializing con . do it as:

private TextView firstElement,secondElement,thirdElement;
public ToDoItem(Context c){
        con = c;
        firstElement= new TextView(con);
        secondElement = new TextView(con);
        thirdElement = new TextView(con);
    }

Suggestion: Use current application component context instead of getApplicationContext() to create Views.

ToDoItem test = new ToDoItem(ActivityName.this);

Solution 2

Never initialize class members with data that is not constant or already set.

You are creating the objects using a reference to the Context before the actual constructor of the class is called and the context is set.

public ToDoItem(Context c){
    con = c;
    firstElement = new TextView(con);
    secondElement = new TextView(con);
    thirdElement = new TextView(con);
}
Share:
14,875
MrSquirreleo
Author by

MrSquirreleo

Updated on June 04, 2022

Comments

  • MrSquirreleo
    MrSquirreleo about 2 years

    I made a class (first block of code) that take in a bunch of data, creates 3 TextViews and then returns a RelativeLayout with all three them as children. Do accomplish this I needed to make the constructor of the class take in a argument for 'Context' since I need 'Context' to create the TextView. However when I try to create the class and pass in context (through getApplicationContex)I get an error (please see the log below in the second block of code)

    Class:

    package com.pp.camry.schoolprojectorganizer;
    //These imports are used to setup the android widgets that the class generates
    import android.content.Context;
    import android.view.View;
    import android.widget.TextView;
    import android.widget.RelativeLayout;
    
    //Imports for the date handling in the createPartTwo method
    import java.util.Date;
    import org.joda.time.DateTime;
    import java.util.GregorianCalendar;
    import org.joda.time.Interval;
    import org.joda.time.Period;
    
    
    
    public class ToDoItem {
        //Context Variable
        private Context con;
        // Variable Storage for the three different TextView instances
        private TextView firstElement = new TextView(con);
        private TextView secondElement = new TextView(con);
        private TextView thirdElement = new TextView(con);
        //Class Version (to prevent errors in serialization
        public final double version = 1.0;
        //Calaender input variable
        private DateTime finalInputDate;
        //Main Return Variable
        private RelativeLayout finalLayout = new RelativeLayout(con);
    
        /**
         * This is the main public constructor method of the class
         * @param c The current context of the program
         */
        public ToDoItem(Context c){
            con = c;
        }
    
        /**
         * This method calls the create method on all three other views and cobines them into a view container
         * @param eventName Name of the event for the first text box
         * @param className Name of the class for the third text box
         * @param year Year of the end of the timer
         * @param month Month of the end of the timer
         * @param day Day of the end of the timer
         * @param hour Hour of the end of the timer
         * @param minute Minute of the end of the timer
         */
        public RelativeLayout createViews(String eventName, String className, int year, int month, int day, int hour, int minute){
            firstElement = createPartOne(eventName);
            secondElement= createPartTwo(year, month, day, hour, minute);
            thirdElement = createPartThree(className);
            finalLayout.addView(firstElement);
            finalLayout.addView(secondElement);
            finalLayout.addView(thirdElement);
            //TODO Finish this method, so that the layout looks nice when its returned
            return finalLayout;
        }
    
        /**
         * The next three methods are the main constructors of the elements of the class. These methods
         * create the various TextView that get put together in the later methods
         */
    
        /**
         *Creates a TextView with from the given string
         * @param title Title used for the Text View
         * @return  Returns a TextView Instance
         */
        public TextView createPartOne(String title){
            //Create and apply the various properties to the new TextView before returning it
            //TODO add some more configuration code in here once we see what the feild looks like
            TextView tempText = new TextView(con);
            tempText.setText(title);
            tempText.setHeight(150);
            tempText.setWidth(950);
            tempText.setTextSize(40);
            tempText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
            return tempText;
        }
    
        /**
         * Sets up the second TextView for the block. This one contains the countdown timer to the
         * date passed into it
         * @param year Int number representing the year
         * @param month Int number representing the month
         * @param day Int number representing the day
         * @param hour Int number representing the hour
         * @param minute Int number representing the minute
         * @return Returns a TextView with the specified countdown timer
         */
        public TextView createPartTwo(int year, int month, int day, int hour, int minute){
            //Construct the current time
            Date currentDate = new Date();
            DateTime currentTime = new DateTime(currentDate);
            //Construct the inputed time
            GregorianCalendar input = new GregorianCalendar();
            input.set(year, month, day, hour, minute);
            DateTime inputTime = new DateTime(input.getTime());
            finalInputDate = inputTime.toDateTime();
            //Do the Comparison
            Interval timeBet = new Interval(inputTime, currentTime);
            //Create the Ui Element
            TextView tempText = new TextView(con);
            Period outputTime = timeBet.toPeriod();
            //Formating stuff down here (really borring, and propaly has the bug your looking for)
            int outcome;
            if(outputTime.getYears()<1 && outputTime.getMonths()<1 && outputTime.getDays()<1 && outputTime.getHours()<1){
                tempText.setText(outputTime.getMinutes() + " Minutes");
                outcome = 0;
            }
            if(outputTime.getYears()<1 && outputTime.getMonths()<1 && outputTime.getDays()<1){
                tempText.setText(outputTime.getHours() + " Hours " + outputTime.getMinutes() + " Minutes ");
                outcome = 1;
            }
            if(outputTime.getYears()<1 && outputTime.getMonths()<1){
                tempText.setText(outputTime.getDays() + " Days " + outputTime.getHours() + " Hours " +
                    outputTime.getMinutes() + " Minutes ");
                outcome = 2;
            }
            if(outputTime.getYears() < 1){
                tempText.setText(outputTime.getMonths() + " Months " + outputTime.getDays()
                        + " Days " + outputTime.getHours() + " Hours " + outputTime.getMinutes() + " Minutes ");
                outcome = 3;
            }
            else{
                tempText.setText( outputTime.getYears() + " Years " + outputTime.getMonths() +
                        " Months " + outputTime.getDays() + " Days " + outputTime.getHours()
                        + " Hours " + outputTime.getMinutes() + " Minutes ");
                outcome = 4;
            }
            //Setup the basics of the textView
            tempText.setWidth(950);
            tempText.setHeight(250);
            //Modify the Text box further according to the outcome variable. Bigger amounts of numbers need smaller font
            if(outcome == 0){
                tempText.setTextSize(25);
            }
            if(outcome == 1){
                tempText.setTextSize(20);
            }
            if(outcome == 2 ){
                tempText.setTextSize(15);
            }
            if(outcome == 3){
                tempText.setTextSize(10);
            }
            if(outcome == 4){
                tempText.setTextSize(5);
            }
            //Return tempText
            return tempText;
        }
    
        /**
         * This method creates the class name box, the last of the three
         * @param className Name of the school class provided by the user
         * @return Returns a TextView with the passed in text in it
         */
        public TextView createPartThree(String className){
            TextView tempText = new TextView(con);
            tempText.setText(className);
            tempText.setHeight(125);
            tempText.setWidth(950);
            tempText.setTextSize(30);
            tempText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
            return tempText;
        }
    
        /**
         * The following methods are for the utility of the class
         */
        public void updatePartTwo(){
            createPartTwo(finalInputDate.getYear(), finalInputDate.getMonthOfYear(), finalInputDate.getDayOfMonth(),
                    finalInputDate.getHourOfDay(), finalInputDate.getMinuteOfHour());
        }
    
    }
    

    And here is the error log:

    01-30 23:22:02.077  13627-13627/com.pp.camry.schoolprojectorganizer E/AndroidRuntime﹕ FATAL EXCEPTION: main
            Process: com.pp.camry.schoolprojectorganizer, PID: 13627
            java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pp.camry.schoolprojectorganizer/com.pp.camry.schoolprojectorganizer.MainScreen}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                    at android.app.ActivityThread.access$800(ActivityThread.java:144)
                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                    at android.os.Handler.dispatchMessage(Handler.java:102)
                    at android.os.Looper.loop(Looper.java:135)
                    at android.app.ActivityThread.main(ActivityThread.java:5221)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at java.lang.reflect.Method.invoke(Method.java:372)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
             Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                    at android.view.ViewConfiguration.get(ViewConfiguration.java:359)
                    at android.view.View.<init>(View.java:3580)
                    at android.view.View.<init>(View.java:3675)
                    at android.widget.TextView.<init>(TextView.java:634)
                    at android.widget.TextView.<init>(TextView.java:629)
                    at android.widget.TextView.<init>(TextView.java:625)
                    at android.widget.TextView.<init>(TextView.java:621)
                    at com.pp.camry.schoolprojectorganizer.ToDoItem.<init>(ToDoItem.java:26)
                    at com.pp.camry.schoolprojectorganizer.MainScreen.onCreate(MainScreen.java:19)
                    at android.app.Activity.performCreate(Activity.java:5933)
                    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                    at android.app.ActivityThread.access$800(ActivityThread.java:144)
                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                    at android.os.Handler.dispatchMessage(Handler.java:102)
                    at android.os.Looper.loop(Looper.java:135)
                    at android.app.ActivityThread.main(ActivityThread.java:5221)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at java.lang.reflect.Method.invoke(Method.java:372)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
    

    and here is the call that is cuasing the error:

    ToDoItem test = new ToDoItem(getApplicationContext());
    

    If I understand the error my code is giving me then it seems that my call for context is returning a null object. I however don't understand why this is happening. Any help would be greatly apprecitated, and just a heads up this is my first android app so if I am missing something heavily evident or simple