我在处理 Contex 时做错了什么(Java - Android)
What am I doing wrong with my handling of Contex ( Java - Android)
我制作了一个 class(第一个代码块),它接收一堆数据,创建 3 个 TextView,然后 returns 一个 RelativeLayout,其中三个都是子视图。要做到这一点,我需要让 class 的构造函数接受 'Context' 的参数,因为我需要 'Context' 来创建 TextView。但是,当我尝试创建 class 并传入上下文(通过 getApplicationContex)时,出现错误(请参阅下面第二个代码块中的日志)
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());
}
}
这是错误日志:
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.access0(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.access0(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)
这是导致错误的调用:
ToDoItem test = new ToDoItem(getApplicationContext());
如果我理解我的代码给我的错误,那么我对上下文的调用似乎返回了一个空对象。但是我不明白为什么会这样。非常感谢任何帮助,请注意这是我的第一个 android 应用程序,所以如果我遗漏了一些非常明显或简单的东西
NullPointerException: Attempt to invoke virtual method
'android.content.res.Resources android.content.Context.getResources()'
on a null object reference
因为 firstElement,secondElement and thirdElement
TextView 是在调用 class 构造函数之前使用 con
创建的,您正在其中初始化 con
。这样做:
private TextView firstElement,secondElement,thirdElement;
public ToDoItem(Context c){
con = c;
firstElement= new TextView(con);
secondElement = new TextView(con);
thirdElement = new TextView(con);
}
建议:
使用当前应用程序组件上下文而不是 getApplicationContext()
来创建视图。
ToDoItem test = new ToDoItem(ActivityName.this);
切勿使用非常量或已设置的数据初始化 class 成员。
在调用 class 的实际构造函数并设置上下文之前,您正在使用对上下文的引用创建对象。
public ToDoItem(Context c){
con = c;
firstElement = new TextView(con);
secondElement = new TextView(con);
thirdElement = new TextView(con);
}
我制作了一个 class(第一个代码块),它接收一堆数据,创建 3 个 TextView,然后 returns 一个 RelativeLayout,其中三个都是子视图。要做到这一点,我需要让 class 的构造函数接受 'Context' 的参数,因为我需要 'Context' 来创建 TextView。但是,当我尝试创建 class 并传入上下文(通过 getApplicationContex)时,出现错误(请参阅下面第二个代码块中的日志)
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());
}
}
这是错误日志:
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.access0(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.access0(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)
这是导致错误的调用:
ToDoItem test = new ToDoItem(getApplicationContext());
如果我理解我的代码给我的错误,那么我对上下文的调用似乎返回了一个空对象。但是我不明白为什么会这样。非常感谢任何帮助,请注意这是我的第一个 android 应用程序,所以如果我遗漏了一些非常明显或简单的东西
NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
因为 firstElement,secondElement and thirdElement
TextView 是在调用 class 构造函数之前使用 con
创建的,您正在其中初始化 con
。这样做:
private TextView firstElement,secondElement,thirdElement;
public ToDoItem(Context c){
con = c;
firstElement= new TextView(con);
secondElement = new TextView(con);
thirdElement = new TextView(con);
}
建议:
使用当前应用程序组件上下文而不是 getApplicationContext()
来创建视图。
ToDoItem test = new ToDoItem(ActivityName.this);
切勿使用非常量或已设置的数据初始化 class 成员。
在调用 class 的实际构造函数并设置上下文之前,您正在使用对上下文的引用创建对象。
public ToDoItem(Context c){
con = c;
firstElement = new TextView(con);
secondElement = new TextView(con);
thirdElement = new TextView(con);
}