Java.lang.NullPointerException in JUnit test with class App.getContext().getString - android

I'm trying to test a method that is in a static context in my class and I want to test it in Junit class but I got a null pointer exception.
My App class :
public class App extends MultiDexApplication {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext() {
return mContext;
}
}
My Method :
public class ColleagueChoice {
static ColleagueApiService apiService = DI.getColleagueApiService();
static List<Colleague> colleagueList = apiService.getColleagues();
static String isEatingAt = App.getContext().getResources().getString(R.string.is_eating_at);
static String isJoining = App.getContext().getResources().getString(R.string.is_joining);
static String notDecided = App.getContext().getString(R.string.has_not_decided_yet);
public static List<Colleague> setScarlettAndHughChoice() {
Colleague scarlett = colleagueList.get(0);
Colleague hugh = colleagueList.get(1);
scarlett.setColleagueIsJoining(isJoining);
hugh.setColleagueIsJoining(isJoining);
List<Colleague> colleagueChoiceList = new ArrayList<>();
colleagueChoiceList.add(scarlett);
colleagueChoiceList.add(hugh);
return colleagueChoiceList;
}
So I'm getting this error at line :
static String isEatingAt = App.getContext().getResources().getString(R.string.is_eating_at);
UP!

Simply remove the App class because this is not very good to put getString in a logic code like services. I just add an enum to my model Colleague and then use: holder.itemView.getContext().getString()
in my adapter with a switch condition.

Related

use static android context in static method

I have a PrefUtils class like this:
public class PrefUtils {
public PrefUtils() {
}
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences("APP_PREF", Context.MODE_PRIVATE);
}
public static void storeAccessToken(Context context, String access_token) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putString("Access_Token", access_token);
editor.commit();
}
public static String getAccessToken(Context context) {
return getSharedPreferences(context).getString("Access_Token", null);
}
}
In my MainActivity I have a static method and I should use a static Context for it :
public class MainActivity extends AppCompatActivity {
private static Context mcontex;
// Is It right To Add Context To static Variable???
#SuppressLint("CheckResult")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
my_method();
}
public static void my_method(){
String access_token =PrefUtils.getAccessToken(mcontex);
// more code ...
}
}
Is it right to add Context to a static variable?
Android Studio says: "Do not place Android Context class in static field".
Does this cause an error like memory leak? And if answer is Yes, what is the right way?
Pass the Context as a parameter to the method rather than keeping the context in a static variable.
public static void myMethod(#NonNull Context context){
String access_token =PrefUtils.getAccessToken(context);
// more code ...
}
The downside of having a static context variable is that there is no guarantee that the non-static onCreate() will have been called before some static initialization code tries to fetch your static Context object. That means your calling code will need to be ready to deal with null values.

Attempt to invoke virtual method on a null object reference - Global Variables Class

I'm learning about MVC. My project has tons of variables. So I made a new class for them called MainVariables.
public class MainVariables {
private String mPictureDirectory;
private String mNameOfThePictureFile;
private String mFullPathPicture;
private double mLongitude;
private double mLatitude;
private String mAddress;
private String mCity;
private String mState;
private String mCountry;
private String mPostalCode;
private String mKnownName;
private String mDescription;
private String mSolicitationType;
...
...
The rest is composed by automatic getters and setters for each variable.
I'm having a problem accessing and casting those variables across my application.
I tried accessing it by casting the following in other files:
private MainVariables mMainVariables;
The above code throws the error Attempt to invoke virtual method on a null object reference
Then I tried the following:
private MainVariables mMainVariables = new MainVariables();
Now, this does work. Only in the file it's using though. For Example, I set variables from within the "SolicitationFragment" and when I try to access it on "PostFragment", I get an empty result.
That's because I'm having to initialize MainVariables on each file.
How can I get around this and be able to access my variables globally?
Make the variables static, or final if you're not going to change them. This way you don't have to create a new instance and can call MainVariables.mPictureDirectory immediately
public class MainVariables {
public static String mPictureDirectory;
}
Another option is a singleton pattern, this way you create only one instance of an object and still can use getters and setters
public class MainVariables {
private static MainVariables mInstance = null;
private String mString;
private MainVariables(){
mString = "Hello";
}
public static MainVariables getInstance(){
if(mInstance == null)
{
synchronized (MainVariables.class) {
if (mInstance== null) {
mInstance= new MainVariables();
}
}
return mInstance;
}
public String getString(){
return this.mString;
}
public void setString(String value){
mString = value;
}
}
In your MainActivity you can declare a field
MainVariables mainVariables = MainVariables.getInstance()
and call
mainVariables.[METHOD] from basically anywhere in your MainActivity
Create a class extending your Application class and create a method to get instance of MainVariables:
AppController.java
public class AppController extends Application {
private MainVariables mMainVariables;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public MainVariables getMainVariables() {
if (mMainVariables == null) {
mMainVariables = new MainVariables();
}
return mMainVariables;
}
}
MainVariables.java
public class MainVariables {
private String string;
public String getString(){
return this.string;
}
public void setString(String string){
this.string = string;
}
}
USE:
// SET VALUE
AppController.getInstance().getMainVariables().setString("Hello Android");
// GET VALUE
String str = AppController.getInstance().getMainVariables().getString();
FYI, You have to add AppController class under application name in your AndroidManifest.xml file.
<application
android:name=".AppController">
</application>
Hope this will help~

Android Thread Synchronization - synchronized keyword doesn't work?

I'm using a singleton class SingletonA for my resources and I have a service ServiceS who uses the resources.
public class SingletonA {
private static SingletonA ourInstance = new SingletonA();
public static SingletonA getInstance() { return ourInstance; }
private SingletonA () {}
String resources;
synchronized public void importSomething() {
resources = "I have some value now";
}
}
public class ServiceS extends Handler {
private static ServiceS ourInstance = new ServiceS();
public static ServiceS getInstance() { return ourInstance; }
private ServiceS () {}
SingletonA sa = SingletonA.getInstance();
public void printResources() {
println(sa.resources);
}
}
public class MyActivity extends Activity {
SingletonA sa = SingletonA.getInstance();
#override
protected void onCreateBundle savedInstanceState) {
super.onCreate(savedInstanceState);
sa.importSomthing();
ServiceS.printResources();
}
}
-> In ServicesS class, sa value is null -> sa.printResources() causes NPE
However, since I add one more sa = SingletonA.getInstance(); into ServiceS.printResources() like this:
public void printResources() {
sa = SingletonA.getInstance();
println(sa);
}
-> It worked: sa != null and resources = "I have some value now".
Can someone explain for me why sa in ServiceS still null ? Thanks,
As the comment of Buddy:
it's due to static initialization order. The static ServiceS.ourService is initialized before SingletonA.ourInstance.
See here for more information on static initialization order. But the easy solution would be to just call SingletonA.getInstance() when necessary (vs caching in a member variable). Or to lazily initialize ServiceS.ourInstance inside getInstance

null reference to a Singleton object

I am trying to create a global variable where it can be accessed from any any where including Activity, Fragment and other custom classes.
public class Global extends Application {
private static Global sInstance;
private String mSharedInfoFileName; //can be any custom object
public static Global getInstance() { return sInstance; }
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
initialize();
}
private void initialize() { mSharedInfoFileName = "globalInfo"; }
public String getFileName() { return mSharedInfoFileName; }
private Global() { }
}
and try to use it like this
public class MyFragment extends android.support.v4.app.Fragment {
String s = Global.getInstance().getFileName();
}
even after declaring it in class scope still gave same error
private static Global mGlobal = Global.getInstance();
which give me Attempt to invoice... .Global.getFileName()' on a null object reference. What am I missing?
Thank you
Change this method to static :
public static String getFileName() {
return mSharedInfoFileName;
}
and call it like below:
Global.getFileName();
The mSharedInfoFileName variable has to be static too :
private static String mSharedInfoFileName;

sending string value from classes extending BaseAdapter to Overlay

i am writing a code where i get a string value in a class that extends BaseAdapter. I want this value to be used in another class that extends an Overlay. If my class extends an Activity i can use intent,putstring() and getString, but is to be used for these above specified classes..Can anyone tell me how can i do this. Thanks in advance.
You can either make your variable global or make a singleton FileHelper class that contains values you want to pass between classes.
MyClass:
public String myString = "Hello";
and if you want to use it in
OtherClass:
String myString = MyClass.myString;
If your the FileHelper use this:
public class FileHelper {
private static FileHelper instance;
private String myString;
private FileHelper() {
}
public static FileHelper getInstance() {
if (instance == null) {
instance = new FileHelper();
}
return instance;
}
public void setMyString(String s){
myString = s;
}
public String getMyString(){
return myString();
}
}
You can use the FileHelper with this:
private static FileHelper fileHelper = FileHelper.getInstance();
fileHelper.setString("hello");
String myString = fileHelper.getMyString();

Categories

Resources